Google OR-Tools v9.11
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
linear_expr.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 <algorithm>
17#include <cstdlib>
18#include <limits>
19#include <ostream>
20#include <string>
21#include <vector>
22
23#include "absl/strings/str_join.h"
24#include "absl/strings/string_view.h"
27
28namespace operations_research {
29
30LinearExpr::LinearExpr(double constant) : offset_(constant), terms_() {}
31
33
35 terms_[var] = 1.0;
36}
37
39 for (const auto& kv : rhs.terms_) {
40 terms_[kv.first] += kv.second;
41 }
42 offset_ += rhs.offset_;
43 return *this;
44}
45
47 for (const auto& kv : rhs.terms_) {
48 terms_[kv.first] -= kv.second;
49 }
50 offset_ -= rhs.offset_;
51 return *this;
52}
53
55 if (rhs == 0) {
56 terms_.clear();
57 offset_ = 0;
58 } else if (rhs != 1) {
59 for (auto& kv : terms_) {
60 kv.second *= rhs;
61 }
62 offset_ *= rhs;
63 }
64 return *this;
65}
66
68 DCHECK_NE(rhs, 0);
69 return (*this) *= 1 / rhs;
70}
71
72LinearExpr LinearExpr::operator-() const { return (*this) * -1; }
73
74// static
76 var *= -1;
77 var += 1;
78 return var;
79}
80
82 double solution = offset_;
83 for (const auto& pair : terms_) {
84 solution += pair.first->solution_value() * pair.second;
85 }
86 return solution;
87}
88
89namespace {
90
91void AppendTerm(const double coef, absl::string_view var_name,
92 const bool is_first, std::string* s) {
93 if (is_first) {
94 if (coef == 1.0) {
95 absl::StrAppend(s, var_name);
96 } else if (coef == -1.0) {
97 absl::StrAppend(s, "-", var_name);
98 } else {
99 absl::StrAppend(s, coef, "*", var_name);
100 }
101 } else {
102 const std::string op = coef < 0 ? "-" : "+";
103 const double abs_coef = std::abs(coef);
104 if (abs_coef == 1.0) {
105 absl::StrAppend(s, " ", op, " ", var_name);
106 } else {
107 absl::StrAppend(s, " ", op, " ", abs_coef, "*", var_name);
108 }
109 }
110}
111
112void AppendOffset(const double offset, const bool is_first, std::string* s) {
113 if (is_first) {
114 absl::StrAppend(s, offset);
115 } else {
116 if (offset != 0.0) {
117 const std::string op = offset < 0 ? "-" : "+";
118 absl::StrAppend(s, " ", op, " ", std::abs(offset));
119 }
120 }
121}
122
123} // namespace
124
125std::string LinearExpr::ToString() const {
126 std::vector<const MPVariable*> vars_in_order;
127 for (const auto& var_val_pair : terms_) {
128 vars_in_order.push_back(var_val_pair.first);
129 }
130 std::sort(vars_in_order.begin(), vars_in_order.end(),
131 [](const MPVariable* v, const MPVariable* u) {
132 return v->index() < u->index();
133 });
134 std::string result;
135 bool is_first = true;
136 for (const MPVariable* var : vars_in_order) {
137 // MPSolver gives names to all variables, even if you don't.
138 DCHECK(!var->name().empty());
139 AppendTerm(terms_.at(var), var->name(), is_first, &result);
140 is_first = false;
141 }
142 AppendOffset(offset_, is_first, &result);
143 // TODO(user): support optionally cropping long strings.
144 return result;
145}
146
147std::ostream& operator<<(std::ostream& stream, const LinearExpr& linear_expr) {
148 stream << linear_expr.ToString();
149 return stream;
150}
151
153 lhs += rhs;
154 return lhs;
155}
157 lhs -= rhs;
158 return lhs;
159}
161 lhs *= rhs;
162 return lhs;
163}
165 lhs /= rhs;
166 return lhs;
167}
169 rhs *= lhs;
170 return rhs;
171}
172
174 double upper_bound)
175 : lower_bound_(lower_bound),
176 linear_expr_(linear_expr),
177 upper_bound_(upper_bound) {
178 lower_bound_ -= linear_expr_.offset();
179 upper_bound_ -= linear_expr_.offset();
180 linear_expr_ -= linear_expr_.offset();
181}
182
184 return LinearRange(-std::numeric_limits<double>::infinity(), lhs - rhs, 0);
185}
187 return LinearRange(0, lhs - rhs, 0);
188}
190 return LinearRange(0, lhs - rhs, std::numeric_limits<double>::infinity());
191}
192
193} // namespace operations_research
LinearExpr & operator/=(double rhs)
LinearExpr & operator+=(const LinearExpr &rhs)
static LinearExpr NotVar(LinearExpr var)
static
LinearExpr & operator-=(const LinearExpr &rhs)
LinearExpr & operator*=(double rhs)
The class for variables of a Mathematical Programming (MP) model.
IntVar * var
int64_t coef
double upper_bound
double lower_bound
double solution
In SWIG mode, we don't want anything besides these top-level includes.
LinearRange operator==(const LinearExpr &lhs, const LinearExpr &rhs)
LinearExpr operator*(LinearExpr lhs, double rhs)
LinearExpr operator-(LinearExpr lhs, const LinearExpr &rhs)
LinearRange operator<=(const LinearExpr &lhs, const LinearExpr &rhs)
std::ostream & operator<<(std::ostream &out, const Assignment &assignment)
LinearExpr operator+(LinearExpr lhs, const LinearExpr &rhs)
LinearExpr operator/(LinearExpr lhs, double rhs)
LinearRange operator>=(const LinearExpr &lhs, const LinearExpr &rhs)