OR-Tools  9.1
variable_and_expressions.cc
Go to the documentation of this file.
1 // Copyright 2010-2021 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 <string>
17 #include <utility>
18 #include <vector>
19 
20 #include "ortools/base/logging.h"
21 #include "absl/container/flat_hash_map.h"
22 #include "ortools/base/map_util.h"
23 #include "ortools/base/int_type.h"
25 
26 namespace operations_research {
27 namespace math_opt {
28 
29 #ifdef USE_LINEAR_EXPRESSION_COUNTERS
30 LinearExpression::LinearExpression() { ++num_calls_default_constructor_; }
31 
32 LinearExpression::LinearExpression(const LinearExpression& other)
33  : terms_(other.terms_), offset_(other.offset_) {
34  ++num_calls_copy_constructor_;
35 }
36 
37 LinearExpression::LinearExpression(LinearExpression&& other)
38  : terms_(std::move(other.terms_)),
39  offset_(std::exchange(other.offset_, 0.0)) {
40  ++num_calls_move_constructor_;
41 }
42 
43 LinearExpression& LinearExpression::operator=(const LinearExpression& other) {
44  terms_ = other.terms_;
45  offset_ = other.offset_;
46  return *this;
47 }
48 
49 ABSL_CONST_INIT thread_local int
50  LinearExpression::num_calls_default_constructor_ = 0;
51 ABSL_CONST_INIT thread_local int LinearExpression::num_calls_copy_constructor_ =
52  0;
53 ABSL_CONST_INIT thread_local int LinearExpression::num_calls_move_constructor_ =
54  0;
55 ABSL_CONST_INIT thread_local int
56  LinearExpression::num_calls_initializer_list_constructor_ = 0;
57 
58 void LinearExpression::ResetCounters() {
59  num_calls_default_constructor_ = 0;
60  num_calls_copy_constructor_ = 0;
61  num_calls_move_constructor_ = 0;
62  num_calls_initializer_list_constructor_ = 0;
63 }
64 #endif // USE_LINEAR_EXPRESSION_COUNTERS
65 
66 double LinearExpression::Evaluate(
67  const VariableMap<double>& variable_values) const {
68  if (variable_values.model() != nullptr && model() != nullptr) {
69  CHECK_EQ(variable_values.model(), model())
71  }
72  double result = offset_;
73  for (const auto& [variable_id, coef] : terms_.raw_map()) {
74  result += coef * variable_values.raw_map().at(variable_id);
75  }
76  return result;
77 }
78 
79 double LinearExpression::EvaluateWithDefaultZero(
80  const VariableMap<double>& variable_values) const {
81  if (variable_values.model() != nullptr && model() != nullptr) {
82  CHECK_EQ(variable_values.model(), model())
84  }
85  double result = offset_;
86  for (const auto& [variable_id, coef] : terms_.raw_map()) {
87  result +=
88  coef * gtl::FindWithDefault(variable_values.raw_map(), variable_id);
89  }
90  return result;
91 }
92 
93 std::ostream& operator<<(std::ostream& ostr,
94  const LinearExpression& expression) {
95  // TODO(b/169415597): improve linear expression format:
96  // - use bijective formatting in base10 of the double factors.
97  // - handle negative coefficients, replacing `... + -3*x ` by `... - 3*x`.
98  // - make sure to quote the variable name so that we support:
99  // * variable names contains +, -, ...
100  // * variable names resembling anonymous variable names.
101  const std::vector<Variable> sorted_variables = expression.terms_.SortedKeys();
102  bool first = true;
103  for (const auto v : sorted_variables) {
104  if (first) {
105  first = false;
106  } else {
107  ostr << " + ";
108  }
109  ostr << expression.terms_.at(v) << "*";
110  const std::string& name = v.name();
111  if (name.empty()) {
112  ostr << "[" << v << "]";
113  } else {
114  ostr << name;
115  }
116  }
117 
118  if (!first) {
119  ostr << " + ";
120  }
121  ostr << expression.offset();
122 
123  return ostr;
124 }
125 
126 std::ostream& operator<<(std::ostream& ostr,
127  const BoundedLinearExpression& bounded_expression) {
128  // TODO(b/170991498): use bijective conversion from double to base-10 string
129  // to make sure we can reproduce bugs.
130  ostr << bounded_expression.lower_bound
131  << " <= " << bounded_expression.expression
132  << " <= " << bounded_expression.upper_bound;
133  return ostr;
134 }
135 
136 } // namespace math_opt
137 } // namespace operations_research
constexpr absl::string_view kObjectsFromOtherIndexedModel
Definition: key_types.h:56
const StorageType & raw_map() const
Definition: id_map.h:228
const std::string name
IndexedModel * model() const
Definition: id_map.h:229
GRBmodel * model
int64_t coef
Definition: expr_array.cc:1875
#define CHECK_EQ(val1, val2)
Definition: base/logging.h:698
const Collection::value_type::second_type & FindWithDefault(const Collection &collection, const typename Collection::value_type::first_type &key, const typename Collection::value_type::second_type &value)
Definition: map_util.h:29
Collection of objects used to extend the Constraint Solver library.
const int64_t offset_
Definition: interval.cc:2108
std::ostream & operator<<(std::ostream &os, const BoolVar &var)
Definition: cp_model.cc:68