OR-Tools  9.6
linear_expr.cc
Go to the documentation of this file.
1 // Copyright 2010-2022 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 <limits>
18 #include <ostream>
19 #include <string>
20 #include <vector>
21 
22 #include "absl/strings/str_join.h"
23 #include "ortools/base/logging.h"
25 
26 namespace operations_research {
27 
28 LinearExpr::LinearExpr(double constant) : offset_(constant), terms_() {}
29 
31 
33  terms_[var] = 1.0;
34 }
35 
37  for (const auto& kv : rhs.terms_) {
38  terms_[kv.first] += kv.second;
39  }
40  offset_ += rhs.offset_;
41  return *this;
42 }
43 
45  for (const auto& kv : rhs.terms_) {
46  terms_[kv.first] -= kv.second;
47  }
48  offset_ -= rhs.offset_;
49  return *this;
50 }
51 
53  if (rhs == 0) {
54  terms_.clear();
55  offset_ = 0;
56  } else if (rhs != 1) {
57  for (auto& kv : terms_) {
58  kv.second *= rhs;
59  }
60  offset_ *= rhs;
61  }
62  return *this;
63 }
64 
66  DCHECK_NE(rhs, 0);
67  return (*this) *= 1 / rhs;
68 }
69 
70 LinearExpr LinearExpr::operator-() const { return (*this) * -1; }
71 
72 // static
74  var *= -1;
75  var += 1;
76  return var;
77 }
78 
79 double LinearExpr::SolutionValue() const {
80  double solution = offset_;
81  for (const auto& pair : terms_) {
82  solution += pair.first->solution_value() * pair.second;
83  }
84  return solution;
85 }
86 
87 namespace {
88 
89 void AppendTerm(const double coef, const std::string& var_name,
90  const bool is_first, std::string* s) {
91  if (is_first) {
92  if (coef == 1.0) {
93  absl::StrAppend(s, var_name);
94  } else if (coef == -1.0) {
95  absl::StrAppend(s, "-", var_name);
96  } else {
97  absl::StrAppend(s, coef, "*", var_name);
98  }
99  } else {
100  const std::string op = coef < 0 ? "-" : "+";
101  const double abs_coef = std::abs(coef);
102  if (abs_coef == 1.0) {
103  absl::StrAppend(s, " ", op, " ", var_name);
104  } else {
105  absl::StrAppend(s, " ", op, " ", abs_coef, "*", var_name);
106  }
107  }
108 }
109 
110 void AppendOffset(const double offset, const bool is_first, std::string* s) {
111  if (is_first) {
112  absl::StrAppend(s, offset);
113  } else {
114  if (offset != 0.0) {
115  const std::string op = offset < 0 ? "-" : "+";
116  absl::StrAppend(s, " ", op, " ", std::abs(offset));
117  }
118  }
119 }
120 
121 } // namespace
122 
123 std::string LinearExpr::ToString() const {
124  std::vector<const MPVariable*> vars_in_order;
125  for (const auto& var_val_pair : terms_) {
126  vars_in_order.push_back(var_val_pair.first);
127  }
128  std::sort(vars_in_order.begin(), vars_in_order.end(),
129  [](const MPVariable* v, const MPVariable* u) {
130  return v->index() < u->index();
131  });
132  std::string result;
133  bool is_first = true;
134  for (const MPVariable* var : vars_in_order) {
135  // MPSolver gives names to all variables, even if you don't.
136  DCHECK(!var->name().empty());
137  AppendTerm(terms_.at(var), var->name(), is_first, &result);
138  is_first = false;
139  }
140  AppendOffset(offset_, is_first, &result);
141  // TODO(user): support optionally cropping long strings.
142  return result;
143 }
144 
145 std::ostream& operator<<(std::ostream& stream, const LinearExpr& linear_expr) {
146  stream << linear_expr.ToString();
147  return stream;
148 }
149 
151  lhs += rhs;
152  return lhs;
153 }
155  lhs -= rhs;
156  return lhs;
157 }
158 LinearExpr operator*(LinearExpr lhs, double rhs) {
159  lhs *= rhs;
160  return lhs;
161 }
162 LinearExpr operator/(LinearExpr lhs, double rhs) {
163  lhs /= rhs;
164  return lhs;
165 }
166 LinearExpr operator*(double lhs, LinearExpr rhs) {
167  rhs *= lhs;
168  return rhs;
169 }
170 
172  double upper_bound)
173  : lower_bound_(lower_bound),
174  linear_expr_(linear_expr),
175  upper_bound_(upper_bound) {
176  lower_bound_ -= linear_expr_.offset();
177  upper_bound_ -= linear_expr_.offset();
178  linear_expr_ -= linear_expr_.offset();
179 }
180 
181 LinearRange operator<=(const LinearExpr& lhs, const LinearExpr& rhs) {
182  return LinearRange(-std::numeric_limits<double>::infinity(), lhs - rhs, 0);
183 }
184 LinearRange operator==(const LinearExpr& lhs, const LinearExpr& rhs) {
185  return LinearRange(0, lhs - rhs, 0);
186 }
187 LinearRange operator>=(const LinearExpr& lhs, const LinearExpr& rhs) {
188  return LinearRange(0, lhs - rhs, std::numeric_limits<double>::infinity());
189 }
190 
191 } // namespace operations_research
LinearExpr models a quantity that is linear in the decision variables (MPVariable) of an optimization...
Definition: linear_expr.h:114
double SolutionValue() const
Evaluates the value of this expression at the solution found.
Definition: linear_expr.cc:79
std::string ToString() const
A human readable representation of this.
Definition: linear_expr.cc:123
LinearExpr operator-() const
Definition: linear_expr.cc:70
LinearExpr & operator*=(double rhs)
Definition: linear_expr.cc:52
LinearExpr & operator+=(const LinearExpr &rhs)
Definition: linear_expr.cc:36
LinearExpr & operator-=(const LinearExpr &rhs)
Definition: linear_expr.cc:44
LinearExpr & operator/=(double rhs)
Definition: linear_expr.cc:65
static LinearExpr NotVar(LinearExpr var)
Returns 1-var.
Definition: linear_expr.cc:73
An expression of the form:
Definition: linear_expr.h:192
The class for variables of a Mathematical Programming (MP) model.
IntVar * var
Definition: expr_array.cc:1874
int64_t coef
Definition: expr_array.cc:1875
const int64_t offset_
Definition: interval.cc:2109
This file allows you to write natural code (like a mathematical equation) to model optimization probl...
A C++ wrapper that provides a simple and unified interface to several linear programming and mixed in...
Collection of objects used to extend the Constraint Solver library.
LinearExpr operator+(LinearExpr lhs, const LinearExpr &rhs)
Definition: linear_expr.cc:150
std::ostream & operator<<(std::ostream &out, const Assignment &assignment)
LinearExpr operator*(LinearExpr lhs, double rhs)
Definition: linear_expr.cc:158
LinearExpr operator/(LinearExpr lhs, double rhs)
Definition: linear_expr.cc:162
LinearExpr operator-(LinearExpr lhs, const LinearExpr &rhs)
Definition: linear_expr.cc:154
LinearRange operator>=(const LinearExpr &lhs, const LinearExpr &rhs)
Definition: linear_expr.cc:187
LinearRange operator<=(const LinearExpr &lhs, const LinearExpr &rhs)
Definition: linear_expr.cc:181
LinearRange operator==(const LinearExpr &lhs, const LinearExpr &rhs)
Definition: linear_expr.cc:184
IntVar * upper_bound
Definition: routing.cc:1087
IntVar * lower_bound
Definition: routing.cc:1086