20#include "absl/container/btree_set.h"
21#include "absl/container/flat_hash_map.h"
22#include "absl/log/check.h"
23#include "absl/status/status.h"
24#include "absl/status/statusor.h"
25#include "absl/strings/str_cat.h"
26#include "absl/strings/string_view.h"
30#include "ortools/linear_solver/linear_solver.pb.h"
50 data_->SetDcheckBounds(
false);
57 data_->SetMaximizationProblem(maximize);
61 data_->SetObjectiveOffset(objective_offset);
65 return data_->FindOrCreateConstraint(
name).value();
72 data_->SetCoefficient(RowIndex(row_index), ColIndex(col_index),
76 LOG_FIRST_N(WARNING, 1)
77 <<
"LAZYCONS section detected. It will be handled as an extension of "
81 return data_->constraint_lower_bounds()[RowIndex(row_index)];
84 return data_->constraint_upper_bounds()[RowIndex(row_index)];
88 return data_->FindOrCreateVariable(
name).value();
91 data_->SetVariableType(ColIndex(
index),
95 LOG(FATAL) <<
"Semi continuous variables are not supported";
104 return data_->variable_lower_bounds()[ColIndex(
index)];
107 return data_->variable_upper_bounds()[ColIndex(
index)];
111 int col_index,
bool col_value) {
112 return absl::UnimplementedError(
113 "LinearProgram does not support indicator constraints.");
130 variable_indices_by_name_.clear();
131 constraint_indices_by_name_.clear();
132 constraints_to_delete_.clear();
133 semi_continuous_variables_.clear();
141 data_->set_objective_offset(objective_offset);
145 const auto it = constraint_indices_by_name_.find(
name);
146 if (it != constraint_indices_by_name_.end())
return it->second;
148 const int index = data_->constraint_size();
149 MPConstraintProto*
const constraint = data_->add_constraint();
150 constraint->set_lower_bound(0.0);
151 constraint->set_upper_bound(0.0);
152 constraint->set_name(
name);
153 constraint_indices_by_name_[
name] =
index;
166 MPConstraintProto*
const constraint = data_->mutable_constraint(row_index);
167 constraint->add_var_index(col_index);
171 data_->mutable_constraint(row_index)->set_is_lazy(
true);
174 return data_->constraint(row_index).lower_bound();
177 return data_->constraint(row_index).upper_bound();
181 const auto it = variable_indices_by_name_.find(
name);
182 if (it != variable_indices_by_name_.end())
return it->second;
184 const int index = data_->variable_size();
185 MPVariableProto*
const variable = data_->add_variable();
186 variable->set_lower_bound(0.0);
187 variable->set_name(
name);
192 data_->mutable_variable(
index)->set_is_integer(
true);
195 semi_continuous_variables_.push_back(
index);
205 return data_->variable(
index).lower_bound();
208 return data_->variable(
index).upper_bound();
213 const auto it = constraint_indices_by_name_.find(cst_name);
214 if (it == constraint_indices_by_name_.end()) {
215 return absl::InvalidArgumentError(
216 absl::StrCat(
"Constraint \"", cst_name,
"\" doesn't exist."));
218 const int cst_index = it->second;
220 MPGeneralConstraintProto*
const constraint =
221 data_->add_general_constraint();
222 constraint->set_name(
223 absl::StrCat(
"ind_", data_->constraint(cst_index).name()));
224 MPIndicatorConstraint*
const indicator =
225 constraint->mutable_indicator_constraint();
226 *indicator->mutable_constraint() = data_->constraint(cst_index);
228 indicator->set_var_value(var_value);
229 constraints_to_delete_.insert(cst_index);
231 return absl::OkStatus();
236 constraints_to_delete_);
238 for (
const int index : semi_continuous_variables_) {
239 MPVariableProto* mp_var = data_->mutable_variable(
index);
243 mp_var->lower_bound() == 0 ? 1.0 : mp_var->lower_bound();
245 const double ub = mp_var->upper_bound();
246 mp_var->set_lower_bound(0.0);
249 const int bool_var_index = data_->variable_size();
250 MPVariableProto* bool_var = data_->add_variable();
251 bool_var->set_lower_bound(0.0);
252 bool_var->set_upper_bound(1.0);
253 bool_var->set_is_integer(
true);
258 MPGeneralConstraintProto*
const zero_constraint =
259 data_->add_general_constraint();
260 MPIndicatorConstraint*
const zero_indicator =
261 zero_constraint->mutable_indicator_constraint();
262 zero_indicator->set_var_index(bool_var_index);
263 zero_indicator->set_var_value(0);
264 zero_indicator->mutable_constraint()->set_lower_bound(0.0);
265 zero_indicator->mutable_constraint()->set_upper_bound(0.0);
266 zero_indicator->mutable_constraint()->add_var_index(
index);
267 zero_indicator->mutable_constraint()->add_coefficient(1.0);
270 MPGeneralConstraintProto*
const one_constraint =
271 data_->add_general_constraint();
272 MPIndicatorConstraint*
const one_indicator =
273 one_constraint->mutable_indicator_constraint();
274 one_indicator->set_var_index(bool_var_index);
275 one_indicator->set_var_value(1);
276 one_indicator->mutable_constraint()->set_lower_bound(lb);
277 one_indicator->mutable_constraint()->set_upper_bound(ub);
278 one_indicator->mutable_constraint()->add_var_index(
index);
279 one_indicator->mutable_constraint()->add_coefficient(1.0);
282 MPConstraintProto*
lower = data_->add_constraint();
283 lower->set_lower_bound(0.0);
284 lower->set_upper_bound(std::numeric_limits<double>::infinity());
286 lower->add_coefficient(1.0);
287 lower->add_var_index(bool_var_index);
288 lower->add_coefficient(-lb);
291 MPConstraintProto*
upper = data_->add_constraint();
292 upper->set_lower_bound(-std::numeric_limits<double>::infinity());
293 upper->set_upper_bound(0.0);
295 upper->add_coefficient(1.0);
296 upper->add_var_index(bool_var_index);
297 upper->add_coefficient(-ub);
305 absl::flat_hash_map<std::string, int> variable_indices_by_name_;
306 absl::flat_hash_map<std::string, int> constraint_indices_by_name_;
307 absl::btree_set<int> constraints_to_delete_;
308 std::vector<int> semi_continuous_variables_;
315MPSReaderFormat TemplateFormat(MPSReader::Form form) {
316 return (form == MPSReader::FIXED) ? MPSReaderFormat::kFixed
317 : (form == MPSReader::FREE) ? MPSReaderFormat::kFree
318 : MPSReaderFormat::kAutoDetect;
324absl::Status MPSReader::ParseFile(absl::string_view file_name,
325 LinearProgram* data, Form form) {
326 DataWrapper<LinearProgram> data_wrapper(data);
328 .
ParseFile(file_name, &data_wrapper, TemplateFormat(form))
332absl::Status MPSReader::ParseFile(absl::string_view file_name,
333 MPModelProto* data, Form form) {
334 DataWrapper<MPModelProto> data_wrapper(data);
336 .
ParseFile(file_name, &data_wrapper, TemplateFormat(form))
342absl::Status MPSReader::ParseProblemFromString(absl::string_view source,
344 MPSReader::Form form) {
345 DataWrapper<LinearProgram> data_wrapper(data);
347 .ParseString(source, &data_wrapper, TemplateFormat(form))
351absl::Status MPSReader::ParseProblemFromString(absl::string_view source,
353 MPSReader::Form form) {
354 DataWrapper<MPModelProto> data_wrapper(data);
356 .ParseString(source, &data_wrapper, TemplateFormat(form))
365 .ParseString(mps_data, &data_wrapper, MPSReaderFormat::kAutoDetect)
375 .ParseFile(mps_file, &data_wrapper, MPSReaderFormat::kAutoDetect)
#define RETURN_IF_ERROR(expr)
void SetName(absl::string_view name)
int FindOrCreateVariable(absl::string_view name)
void SetObjectiveCoefficient(int index, double coefficient)
double VariableUpperBound(int index)
void SetVariableTypeToSemiContinuous(int index)
DataWrapper(LinearProgram *data)
void SetObjectiveDirection(bool maximize)
double VariableLowerBound(int index)
int FindOrCreateConstraint(absl::string_view name)
double ConstraintLowerBound(int row_index)
void SetIsLazy(int row_index)
absl::Status CreateIndicatorConstraint(absl::string_view row_name, int col_index, bool col_value)
void SetObjectiveOffset(double objective_offset)
void SetConstraintBounds(int index, double lower_bound, double upper_bound)
void SetVariableTypeToInteger(int index)
double ConstraintUpperBound(int row_index)
void SetConstraintCoefficient(int row_index, int col_index, double coefficient)
void SetVariableBounds(int index, double lower_bound, double upper_bound)
void SetName(absl::string_view name)
void SetVariableTypeToSemiContinuous(int index)
double VariableLowerBound(int index)
double ConstraintLowerBound(int row_index)
double VariableUpperBound(int index)
double ConstraintUpperBound(int row_index)
void SetConstraintBounds(int index, double lower_bound, double upper_bound)
void SetObjectiveCoefficient(int index, double coefficient)
int FindOrCreateConstraint(absl::string_view name)
void SetVariableTypeToInteger(int index)
void SetObjectiveOffset(double objective_offset)
void SetObjectiveDirection(bool maximize)
DataWrapper(MPModelProto *data)
absl::Status CreateIndicatorConstraint(absl::string_view cst_name, int var_index, bool var_value)
void SetConstraintCoefficient(int row_index, int col_index, double coefficient)
void SetVariableBounds(int index, double lower_bound, double upper_bound)
int FindOrCreateVariable(absl::string_view name)
void SetIsLazy(int row_index)
@ INTEGER
The variable must only take integer values.
const std::string name
A name for logging purposes.
int RemoveAt(RepeatedType *array, const IndexContainer &indices)
void ParseFile(const std::string &filename, bool presolve)
absl::StatusOr< MPModelProto > MpsFileToMPModelProto(absl::string_view mps_file)
Parses an MPS model from a file.
absl::StatusOr< MPModelProto > MpsDataToMPModelProto(absl::string_view mps_data)
Parses an MPS model from a string.
In SWIG mode, we don't want anything besides these top-level includes.