OR-Tools  9.6
sos/storage.h
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 
14 #ifndef OR_TOOLS_MATH_OPT_CONSTRAINTS_SOS_STORAGE_H_
15 #define OR_TOOLS_MATH_OPT_CONSTRAINTS_SOS_STORAGE_H_
16 
17 #include <cstdint>
18 #include <optional>
19 #include <string>
20 #include <type_traits>
21 #include <utility>
22 #include <vector>
23 
24 #include "absl/container/flat_hash_map.h"
25 #include "absl/container/flat_hash_set.h"
26 #include "absl/log/check.h"
28 #include "ortools/math_opt/model.pb.h"
29 #include "ortools/math_opt/model_update.pb.h"
30 #include "ortools/math_opt/sparse_containers.pb.h"
34 
36 namespace internal {
37 
38 // Internal storage representation for a single SOS constraint.
39 //
40 // Implements the interface specified for the `ConstraintData` parameter of
41 // `AtomicConstraintStorage`.
42 template <typename ConstraintId>
44  public:
45  using IdType = ConstraintId;
46  using ProtoType = SosConstraintProto;
47  using UpdatesProtoType = SosConstraintUpdatesProto;
48 
49  static_assert(
50  std::disjunction_v<std::is_same<ConstraintId, Sos1ConstraintId>,
51  std::is_same<ConstraintId, Sos2ConstraintId>>,
52  "ID type may only be Sos1ConstraintId or Sos2ConstraintId");
53 
55  absl::flat_hash_map<VariableId, double> terms;
56  double offset = 0.0;
57  };
58 
59  // `weights` must either be empty or the same length as `expressions`. If it
60  // is empty, default weights of 1, 2, ... will be used.
61  SosConstraintData(std::vector<LinearExpression> expressions,
62  std::vector<double> weights, std::string name)
63  : expressions_(std::move(expressions)), name_(std::move(name)) {
64  if (!weights.empty()) {
65  CHECK_EQ(weights.size(), expressions_.size());
66  weights_ = std::move(weights);
67  }
68  }
69 
70  // The `in_proto` must be in a valid state; see the inline comments on
71  // `SosConstraintProto` for details.
72  static SosConstraintData FromProto(const ProtoType& in_proto);
73  ProtoType Proto() const;
74  std::vector<VariableId> RelatedVariables() const;
75  void DeleteVariable(VariableId var);
76 
77  bool has_weights() const { return weights_.has_value(); }
78 
79  double weight(const int index) const {
80  AssertInbounds(index);
81  return weights_.has_value() ? (*weights_)[index] : index + 1;
82  }
83  const LinearExpression& expression(const int index) const {
84  AssertInbounds(index);
85  return expressions_[index];
86  }
87  int64_t num_expressions() const { return expressions_.size(); }
88  const std::string& name() const { return name_; }
89 
90  private:
91  SosConstraintData() = default;
92  void AssertInbounds(const int index) const {
93  CHECK_GE(index, 0);
94  CHECK_LT(index, expressions_.size());
95  }
96  // If present, length must be the same as that of `expressions_`.
97  // If absent, default weights of 1, 2, ... are used.
98  std::optional<std::vector<double>> weights_;
99  std::vector<LinearExpression> expressions_;
100  std::string name_;
101 };
102 
103 } // namespace internal
104 
107 
108 template <>
109 struct AtomicConstraintTraits<Sos1ConstraintId> {
111 };
112 
113 template <>
114 struct AtomicConstraintTraits<Sos2ConstraintId> {
116 };
117 
119 // Inline implementations
121 
122 namespace internal {
123 
124 template <typename ConstraintId>
126  const ProtoType& in_proto) {
127  const int num_expressions = in_proto.expressions_size();
128  SosConstraintData data;
129  data.name_ = in_proto.name();
130  for (int i = 0; i < num_expressions; ++i) {
131  LinearExpression& expression = data.expressions_.emplace_back();
132  const LinearExpressionProto& proto_expression = in_proto.expressions(i);
133  expression.offset = proto_expression.offset();
134  for (int j = 0; j < proto_expression.ids_size(); ++j) {
135  expression.terms.insert({VariableId(proto_expression.ids(j)),
136  proto_expression.coefficients(j)});
137  }
138  }
139  // Otherwise proto has default weights, so leave data.weights_ as unset.
140  if (!in_proto.weights().empty()) {
141  data.weights_.emplace().reserve(num_expressions);
142  for (int i = 0; i < num_expressions; ++i) {
143  data.weights_->push_back(in_proto.weights(i));
144  }
145  }
146  return data;
147 }
148 
149 template <typename ConstraintId>
152  ProtoType constraint;
153  constraint.set_name(name());
154  for (int i = 0; i < num_expressions(); ++i) {
155  const LinearExpression& expr = expression(i);
156  LinearExpressionProto& proto_expr = *constraint.add_expressions();
157  proto_expr.set_offset(expr.offset);
158  for (const VariableId id : SortedMapKeys(expr.terms)) {
159  proto_expr.add_ids(id.value());
160  proto_expr.add_coefficients(expr.terms.at(id));
161  }
162  }
163  if (weights_.has_value()) {
164  for (int i = 0; i < num_expressions(); ++i) {
165  constraint.add_weights(weight(i));
166  }
167  }
168  return constraint;
169 }
170 
171 template <typename ConstraintId>
173  const {
174  absl::flat_hash_set<VariableId> vars;
175  for (const LinearExpression& expression : expressions_) {
176  for (const auto [var, _] : expression.terms) {
177  vars.insert(var);
178  }
179  }
180  return std::vector<VariableId>(vars.begin(), vars.end());
181 }
182 
183 template <typename ConstraintId>
185  for (LinearExpression& expression : expressions_) {
186  expression.terms.erase(var);
187  }
188 }
189 
190 } // namespace internal
191 } // namespace operations_research::math_opt
192 
193 #endif // OR_TOOLS_MATH_OPT_CONSTRAINTS_SOS_STORAGE_H_
static SosConstraintData FromProto(const ProtoType &in_proto)
Definition: sos/storage.h:125
std::vector< VariableId > RelatedVariables() const
Definition: sos/storage.h:172
SosConstraintData(std::vector< LinearExpression > expressions, std::vector< double > weights, std::string name)
Definition: sos/storage.h:61
const LinearExpression & expression(const int index) const
Definition: sos/storage.h:83
const std::string name
int64_t value
IntVar * var
Definition: expr_array.cc:1874
int index
internal::SosConstraintData< Sos1ConstraintId > Sos1ConstraintData
Definition: sos/storage.h:105
std::vector< K > SortedMapKeys(const absl::flat_hash_map< K, V > &in_map)
Definition: sorted.h:55
internal::SosConstraintData< Sos2ConstraintId > Sos2ConstraintData
Definition: sos/storage.h:106
int64_t weight
Definition: pack.cc:510