Google OR-Tools v9.11
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
lp_model.cc
Go to the documentation of this file.
1// Copyright 2010-2024 Google LLC
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
15
16#include <cmath>
17#include <cstdlib>
18#include <ostream>
19#include <string>
20#include <utility>
21
22#include "absl/status/status.h"
23#include "absl/status/statusor.h"
24#include "absl/strings/escaping.h"
25#include "absl/strings/str_cat.h"
26#include "absl/strings/str_join.h"
31
33namespace {
34
35absl::Status ValidateRelation(Relation relation) {
36 switch (relation) {
40 return absl::OkStatus();
41 }
43 << "Invalid Relation: " << static_cast<int>(relation);
44}
45
46} // namespace
47
48std::ostream& operator<<(std::ostream& ostr, const Relation relation) {
49 switch (relation) {
51 ostr << ">=";
52 return ostr;
54 ostr << "=";
55 return ostr;
57 ostr << "<=";
58 return ostr;
59 }
60 ostr << "__invalid_Relation_" << static_cast<int>(relation) << "__";
61 return ostr;
62}
63
64std::ostream& operator<<(std::ostream& ostr, const Constraint& constraint) {
65 auto term_format = [](std::string* out,
66 const std::pair<double, VariableIndex>& term) {
67 absl::StrAppend(out, "{", RoundTripDoubleFormat(term.first), ", ",
68 term.second, "}");
69 };
70 ostr << "terms: {" << absl::StrJoin(constraint.terms, ", ", term_format)
71 << "} relation: " << constraint.relation
72 << " rhs: " << RoundTripDoubleFormat(constraint.rhs) << " name: \""
73 << absl::CEscape(constraint.name) << "\"";
74 return ostr;
75}
76
77absl::StatusOr<ConstraintIndex> LpModel::AddConstraint(Constraint constraint) {
78 if (!constraint.name.empty()) {
79 RETURN_IF_ERROR(ValidateName(constraint.name)) << "invalid constraint name";
80 }
81 if (constraint.terms.empty()) {
82 return absl::InvalidArgumentError("constraint must have at least one term");
83 }
84 for (const auto [coef, var] : constraint.terms) {
85 if (var < VariableIndex{0} || var >= variables_.end_index()) {
87 << "variable ids should be in [0," << variables_.end_index()
88 << ") but found: " << var;
89 }
90 if (!std::isfinite(coef)) {
92 << "All coefficients in constraints must be finite and not NaN "
93 "but found: "
94 << coef;
95 }
96 }
97 RETURN_IF_ERROR(ValidateRelation(constraint.relation));
98 if (std::isnan(constraint.rhs)) {
99 return absl::InvalidArgumentError("rhs of constraint was NaN");
100 }
101 ConstraintIndex result = constraints_.end_index();
102 constraints_.push_back(std::move(constraint));
103 return result;
104}
105
106absl::StatusOr<VariableIndex> LpModel::AddVariable(absl::string_view name) {
107 if (variable_names_.contains(name)) {
109 << "duplicate variable name: " << name;
110 }
111 RETURN_IF_ERROR(ValidateName(name)) << "invalid variable name";
112 const VariableIndex index = variables_.end_index();
113 variables_.push_back(std::string(name));
114 variable_names_[name] = index;
115 return index;
116}
117
118std::ostream& operator<<(std::ostream& ostr, const LpModel& model) {
119 ostr << "SUBJECT TO" << std::endl;
120 for (const Constraint& constraint : model.constraints()) {
121 ostr << " ";
122 if (!constraint.name.empty()) {
123 ostr << constraint.name << ": ";
124 }
125 bool first = true;
126 for (const auto [coef, var] : constraint.terms) {
127 if (first) {
128 if (coef != 1.0) {
129 ostr << RoundTripDoubleFormat(coef) << " ";
130 }
131 } else {
132 if (coef > 0) {
133 ostr << " + ";
134 } else {
135 ostr << " - ";
136 }
137 ostr << RoundTripDoubleFormat(std::abs(coef)) << " ";
138 }
139 ostr << model.variables()[var];
140 first = false;
141 }
142 ostr << " " << constraint.relation << " "
143 << RoundTripDoubleFormat(constraint.rhs) << std::endl;
144 }
145 ostr << "END" << std::endl;
146 return ostr;
147}
148
149} // namespace operations_research::lp_format
#define RETURN_IF_ERROR(expr)
absl::StatusOr< ConstraintIndex > AddConstraint(Constraint constraint)
Definition lp_model.cc:77
absl::StatusOr< VariableIndex > AddVariable(absl::string_view name)
Definition lp_model.cc:106
void push_back(const value_type &val)
const std::string name
A name for logging purposes.
IntVar * var
int64_t coef
GRBmodel * model
int index
absl::Status ValidateName(absl::string_view name)
Checks if name is a valid name for a variable or constraint in an LP file.
Definition lp_name.cc:57
std::ostream & operator<<(std::ostream &ostr, const Relation relation)
Definition lp_model.cc:48
StatusBuilder InvalidArgumentErrorBuilder()