75void MpsDriver::AddColumn(
const std::string &column,
const std::string &row, mpq_class value) {
76 DLINEAR_TRACE_FMT(
"Driver::AddColumn {} {} {}", row, column, value);
77 if (columns_.find(column) == columns_.end()) {
78 DLINEAR_TRACE_FMT(
"Added column {}", column);
80 const Variable var{
"x" + std::to_string(columns_.size())};
81 columns_[column] = var;
82 context_.DeclareVariable(var);
84 if (!context_.config().optimize() && row == obj_row_)
return;
85 rows_[row].emplace(columns_[column], value);
86 DLINEAR_TRACE_FMT(
"Updated row {}", row);
89void MpsDriver::AddRhs(
const std::string &rhs,
const std::string &row, mpq_class value) {
90 DLINEAR_TRACE_FMT(
"Driver::AddRhs {} {} {}", rhs, row, value);
91 if (!VerifyStrictRhs(rhs))
return;
92 rhs_values_[row] = value;
95 switch (row_senses_.at(row)) {
97 rhs_[row] = row_expression <= value;
100 rhs_[row] = value <= row_expression;
103 rhs_[row] = row_expression == value;
106 DLINEAR_WARN(
"Sense N is used only for objective function. No action to take");
109 DLINEAR_UNREACHABLE();
111 }
catch (
const std::out_of_range &e) {
112 DLINEAR_RUNTIME_ERROR_FMT(
"Row {} not found", row);
114 DLINEAR_TRACE_FMT(
"Updated rhs {}", rhs_[row]);
117void MpsDriver::AddRange(
const std::string &rhs,
const std::string &row, mpq_class value) {
118 DLINEAR_TRACE_FMT(
"Driver::AddRange {} {} {}", rhs, row, value);
119 if (!VerifyStrictRhs(rhs))
return;
122 switch (row_senses_.at(row)) {
124 mpq_abs(value.get_mpq_t(), value.get_mpq_t());
125 rhs_[row] &= mpq_class{rhs_values_[row] - value} <= row_expression;
128 mpq_abs(value.get_mpq_t(), value.get_mpq_t());
129 rhs_[row] &= row_expression <= mpq_class{rhs_values_[row] + value};
132 rhs_[row] = value > 0
133 ? rhs_values_[row] <= row_expression && row_expression <= mpq_class(rhs_values_[row] + value)
134 : mpq_class{rhs_values_[row] + value} <= row_expression && row_expression <= rhs_values_[row];
137 DLINEAR_WARN(
"Sense N is used only for objective function. No action to take");
140 DLINEAR_UNREACHABLE();
142 }
catch (
const std::out_of_range &e) {
143 DLINEAR_RUNTIME_ERROR_FMT(
"Row {} not found", row);
147void MpsDriver::AddBound(
BoundType bound_type,
const std::string &bound,
const std::string &column, mpq_class value) {
148 DLINEAR_TRACE_FMT(
"Driver::AddBound {} {} {} {}", bound_type, bound, column, value);
149 if (!VerifyStrictBound(bound))
return;
151 switch (bound_type) {
154 bounds_[column] &= columns_.at(column) <= value;
155 if (value <= 0) skip_lower_bound_[column] =
true;
159 bounds_[column] &= value <= columns_.at(column);
160 skip_lower_bound_[column] =
true;
163 bounds_[column] &= (value <= columns_.at(column)) && (columns_.at(column) <= value);
164 skip_lower_bound_[column] =
true;
167 DLINEAR_UNREACHABLE();
169 }
catch (
const std::out_of_range &e) {
170 DLINEAR_RUNTIME_ERROR_FMT(
"Column {} not found", column);
173 DLINEAR_TRACE_FMT(
"Updated bound {}", bounds_[column]);
176void MpsDriver::AddBound(
BoundType bound_type,
const std::string &bound,
const std::string &column) {
177 DLINEAR_TRACE_FMT(
"Driver::AddBound {} {} {}", bound_type, bound, column);
178 if (!VerifyStrictBound(bound))
return;
180 switch (bound_type) {
182 bounds_[column] = (0 <= columns_.at(column)) && (columns_.at(column) <= 1);
183 skip_lower_bound_[column] =
true;
187 skip_lower_bound_[column] =
true;
190 DLINEAR_DEBUG(
"Infinity bound, no action to take");
193 DLINEAR_UNREACHABLE();
195 }
catch (
const std::out_of_range &e) {
196 DLINEAR_RUNTIME_ERROR_FMT(
"Column {} not found", column);
199 DLINEAR_TRACE_FMT(
"Updated bound {}", bounds_[column]);
202void MpsDriver::End() {
203 DLINEAR_DEBUG_FMT(
"Driver::EndData reached end of file {}", problem_name_);
204 for (
const auto &[row, sense] : row_senses_) {
205 if (sense != Sense::N && rhs_.find(row) == rhs_.end()) {
206 DLINEAR_TRACE_FMT(
"Row {} has no RHS. Adding 0", row);
207 AddRhs(rhs_name_, row, 0);
210 for (
const auto &[column, var] : columns_) {
211 if (skip_lower_bound_.find(column) == skip_lower_bound_.end()) {
212 DLINEAR_TRACE_FMT(
"Column has no lower bound. Adding 0 <= {}", column);
213 AddBound(BoundType::LO, bound_name_, column, 0);
216 DLINEAR_DEBUG_FMT(
"Found {} assertions", n_assertions());
217 for (
const auto &[name, bound] : bounds_) {
218 context_.Assert(bound);
220 for (
const auto &[name, row] : rhs_) {
221 if (row.EqualTo(Formula::True()))
continue;
222 context_.Assert(row);
224 if (context_.config().optimize() && !obj_row_.empty()) {
227 context_.Minimize(obj_expression);
229 context_.Maximize(obj_expression);
234void MpsDriver::ToSmt2(std::ostream &os)
const {
235 os <<
"(set-logic QF_LRA)\n";
236 if (!context_.GetInfo(
":status").empty()) os <<
"(set-info :status " << context_.GetInfo(
":status") <<
")\n";
237 for (
const auto &[name, column] : columns_) {
238 os <<
"(declare-const " << column <<
" Real)\n";
240 for (
const auto &[name, bound] : bounds_) {
241 os <<
"(assert " << bound.to_smt2_string() <<
")\n";
243 for (
const auto &[name, row] : rhs_) {
244 if (row.EqualTo(Formula::True()))
continue;
245 os <<
"(assert " << row.to_smt2_string() <<
")\n";
247 os <<
"(check-sat)\n";