Google OR-Tools v9.11
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
sparse_containers.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 <cstdint>
17#include <optional>
18#include <utility>
19#include <vector>
20
21#include "absl/algorithm/container.h"
22#include "absl/container/flat_hash_map.h"
23#include "absl/status/status.h"
24#include "absl/status/statusor.h"
25#include "absl/types/span.h"
26#include "google/protobuf/map.h"
38
40namespace {
41
42// SparseVectorProtoType should be SparseDoubleVector or SparseBasisStatusVector
43template <typename SparseVectorProtoType>
44absl::Status CheckSparseVectorProto(const SparseVectorProtoType& vec) {
47 return absl::OkStatus();
48}
49
50template <typename Key>
51absl::StatusOr<absl::flat_hash_map<Key, BasisStatus>> BasisVectorFromProto(
52 const ModelStorage* const model,
53 const SparseBasisStatusVector& basis_proto) {
54 using IdType = typename Key::IdType;
55 absl::flat_hash_map<Key, BasisStatus> map;
56 map.reserve(basis_proto.ids_size());
57 for (const auto& [id, basis_status_proto_int] : MakeView(basis_proto)) {
58 const auto basis_status_proto =
59 static_cast<BasisStatusProto>(basis_status_proto_int);
60 const std::optional<BasisStatus> basis_status =
61 EnumFromProto(basis_status_proto);
62 if (!basis_status.has_value()) {
64 << "basis status not specified for id " << id;
65 }
66 map[Key(model, IdType(id))] = *basis_status;
67 }
68 return map;
69}
70
71template <typename Key>
72SparseDoubleVectorProto MapToProto(
73 const absl::flat_hash_map<Key, double>& id_map) {
74 using IdType = typename Key::IdType;
75 std::vector<std::pair<IdType, double>> sorted_entries;
76 sorted_entries.reserve(id_map.size());
77 for (const auto& [k, v] : id_map) {
78 sorted_entries.emplace_back(k.typed_id(), v);
79 }
80 absl::c_sort(sorted_entries);
81 SparseDoubleVectorProto result;
82 for (const auto& [id, val] : sorted_entries) {
83 result.add_ids(id.value());
84 result.add_values(val);
85 }
86 return result;
87}
88
89template <typename Key>
90SparseBasisStatusVector BasisMapToProto(
91 const absl::flat_hash_map<Key, BasisStatus>& basis_map) {
92 using IdType = typename Key::IdType;
93 std::vector<std::pair<IdType, BasisStatus>> sorted_entries;
94 sorted_entries.reserve(basis_map.size());
95 for (const auto& [k, v] : basis_map) {
96 sorted_entries.emplace_back(k.typed_id(), v);
97 }
98 absl::c_sort(sorted_entries);
99 SparseBasisStatusVector result;
100 for (const auto& [id, val] : sorted_entries) {
101 result.add_ids(id.value());
102 result.add_values(EnumToProto(val));
103 }
104 return result;
105}
106
107absl::Status VariableIdsExist(const ModelStorage* const model,
108 const absl::Span<const int64_t> ids) {
109 for (const int64_t id : ids) {
110 if (!model->has_variable(VariableId(id))) {
112 << "no variable with id " << id << " exists";
113 }
114 }
115 return absl::OkStatus();
116}
117
118absl::Status LinearConstraintIdsExist(const ModelStorage* const model,
119 const absl::Span<const int64_t> ids) {
120 for (const int64_t id : ids) {
121 if (!model->has_linear_constraint(LinearConstraintId(id))) {
123 << "no linear constraint with id " << id << " exists";
124 }
125 }
126 return absl::OkStatus();
127}
128
129absl::Status QuadraticConstraintIdsExist(const ModelStorage* const model,
130 const absl::Span<const int64_t> ids) {
131 for (const int64_t id : ids) {
132 if (!model->has_constraint(QuadraticConstraintId(id))) {
134 << "no quadratic constraint with id " << id << " exists";
135 }
136 }
137 return absl::OkStatus();
138}
139
140} // namespace
141
142absl::StatusOr<VariableMap<double>> VariableValuesFromProto(
143 const ModelStorage* const model,
144 const SparseDoubleVectorProto& vars_proto) {
145 RETURN_IF_ERROR(CheckSparseVectorProto(vars_proto));
146 RETURN_IF_ERROR(VariableIdsExist(model, vars_proto.ids()));
147 return MakeView(vars_proto).as_map<Variable>(model);
148}
149
150absl::StatusOr<VariableMap<int32_t>> VariableValuesFromProto(
151 const ModelStorage* model, const SparseInt32VectorProto& vars_proto) {
152 RETURN_IF_ERROR(CheckSparseVectorProto(vars_proto));
153 RETURN_IF_ERROR(VariableIdsExist(model, vars_proto.ids()));
154 return MakeView(vars_proto).as_map<Variable>(model);
155}
156
157SparseDoubleVectorProto VariableValuesToProto(
158 const VariableMap<double>& variable_values) {
159 return MapToProto(variable_values);
160}
161
162absl::StatusOr<absl::flat_hash_map<Objective, double>>
164 const ModelStorage* const model,
165 const google::protobuf::Map<int64_t, double>& aux_obj_proto) {
166 absl::flat_hash_map<Objective, double> result;
167 for (const auto [raw_id, value] : aux_obj_proto) {
168 const AuxiliaryObjectiveId id(raw_id);
169 if (!model->has_auxiliary_objective(id)) {
171 << "no auxiliary objective with id " << raw_id << " exists";
172 }
173 result[Objective::Auxiliary(model, id)] = value;
174 }
175 return result;
176}
177
178google::protobuf::Map<int64_t, double> AuxiliaryObjectiveValuesToProto(
179 const absl::flat_hash_map<Objective, double>& aux_obj_values) {
180 google::protobuf::Map<int64_t, double> result;
181 for (const auto& [objective, value] : aux_obj_values) {
182 CHECK(objective.id().has_value())
183 << "encountered primary objective in auxiliary objective value map";
184 result[objective.id().value()] = value;
185 }
186 return result;
187}
188
189absl::StatusOr<LinearConstraintMap<double>> LinearConstraintValuesFromProto(
190 const ModelStorage* const model,
191 const SparseDoubleVectorProto& lin_cons_proto) {
192 RETURN_IF_ERROR(CheckSparseVectorProto(lin_cons_proto));
193 RETURN_IF_ERROR(LinearConstraintIdsExist(model, lin_cons_proto.ids()));
194 return MakeView(lin_cons_proto).as_map<LinearConstraint>(model);
195}
196
197SparseDoubleVectorProto LinearConstraintValuesToProto(
198 const LinearConstraintMap<double>& linear_constraint_values) {
199 return MapToProto(linear_constraint_values);
200}
201
202absl::StatusOr<absl::flat_hash_map<QuadraticConstraint, double>>
204 const ModelStorage* const model,
205 const SparseDoubleVectorProto& quad_cons_proto) {
206 RETURN_IF_ERROR(CheckSparseVectorProto(quad_cons_proto));
207 RETURN_IF_ERROR(QuadraticConstraintIdsExist(model, quad_cons_proto.ids()));
208 return MakeView(quad_cons_proto).as_map<QuadraticConstraint>(model);
209}
210
211SparseDoubleVectorProto QuadraticConstraintValuesToProto(
212 const absl::flat_hash_map<QuadraticConstraint, double>&
213 quadratic_constraint_values) {
214 return MapToProto(quadratic_constraint_values);
215}
216
217absl::StatusOr<VariableMap<BasisStatus>> VariableBasisFromProto(
218 const ModelStorage* const model,
219 const SparseBasisStatusVector& basis_proto) {
220 RETURN_IF_ERROR(CheckSparseVectorProto(basis_proto));
221 RETURN_IF_ERROR(VariableIdsExist(model, basis_proto.ids()));
222 return BasisVectorFromProto<Variable>(model, basis_proto);
223}
224
225SparseBasisStatusVector VariableBasisToProto(
226 const VariableMap<BasisStatus>& basis_values) {
227 return BasisMapToProto(basis_values);
228}
229
230absl::StatusOr<LinearConstraintMap<BasisStatus>> LinearConstraintBasisFromProto(
231 const ModelStorage* const model,
232 const SparseBasisStatusVector& basis_proto) {
233 RETURN_IF_ERROR(CheckSparseVectorProto(basis_proto));
234 RETURN_IF_ERROR(LinearConstraintIdsExist(model, basis_proto.ids()));
235 return BasisVectorFromProto<LinearConstraint>(model, basis_proto);
236}
237
238SparseBasisStatusVector LinearConstraintBasisToProto(
239 const LinearConstraintMap<BasisStatus>& basis_values) {
240 return BasisMapToProto(basis_values);
241}
242
243} // namespace operations_research::math_opt
#define RETURN_IF_ERROR(expr)
static Objective Auxiliary(const ModelStorage *storage, AuxiliaryObjectiveId id)
Returns an object that refers to an auxiliary objective of the model.
Definition objective.h:224
int64_t value
GRBmodel * model
An object oriented wrapper for quadratic constraints in ModelStorage.
Definition gurobi_isv.cc:28
google::protobuf::Map< int64_t, double > AuxiliaryObjectiveValuesToProto(const absl::flat_hash_map< Objective, double > &aux_obj_values)
absl::StatusOr< absl::flat_hash_map< Objective, double > > AuxiliaryObjectiveValuesFromProto(const ModelStorage *const model, const google::protobuf::Map< int64_t, double > &aux_obj_proto)
absl::Status CheckIdsAndValuesSize(const SparseVectorView< T > &vector_view, absl::string_view value_name="values")
absl::flat_hash_map< Variable, V > VariableMap
absl::flat_hash_map< LinearConstraint, V > LinearConstraintMap
SparseDoubleVectorProto LinearConstraintValuesToProto(const LinearConstraintMap< double > &linear_constraint_values)
Returns the proto equivalent of linear_constraint_values.
absl::StatusOr< LinearConstraintMap< BasisStatus > > LinearConstraintBasisFromProto(const ModelStorage *const model, const SparseBasisStatusVector &basis_proto)
absl::StatusOr< absl::flat_hash_map< QuadraticConstraint, double > > QuadraticConstraintValuesFromProto(const ModelStorage *const model, const SparseDoubleVectorProto &quad_cons_proto)
absl::StatusOr< LinearConstraintMap< double > > LinearConstraintValuesFromProto(const ModelStorage *const model, const SparseDoubleVectorProto &lin_cons_proto)
std::optional< typename EnumProto< P >::Cpp > EnumFromProto(P proto_value)
Definition enums.h:281
absl::StatusOr< VariableMap< double > > VariableValuesFromProto(const ModelStorage *const model, const SparseDoubleVectorProto &vars_proto)
SparseBasisStatusVector VariableBasisToProto(const VariableMap< BasisStatus > &basis_values)
Returns the proto equivalent of basis_values.
SparseVectorView< T > MakeView(absl::Span< const int64_t > ids, const Collection &values)
SparseBasisStatusVector LinearConstraintBasisToProto(const LinearConstraintMap< BasisStatus > &basis_values)
Returns the proto equivalent of basis_values.
SparseDoubleVectorProto VariableValuesToProto(const VariableMap< double > &variable_values)
Returns the proto equivalent of variable_values.
SparseDoubleVectorProto QuadraticConstraintValuesToProto(const absl::flat_hash_map< QuadraticConstraint, double > &quadratic_constraint_values)
Returns the proto equivalent of quadratic_constraint_values.
Enum< E >::Proto EnumToProto(std::optional< E > value)
Definition enums.h:270
absl::StatusOr< VariableMap< BasisStatus > > VariableBasisFromProto(const ModelStorage *const model, const SparseBasisStatusVector &basis_proto)
absl::Status CheckIdsRangeAndStrictlyIncreasing(absl::Span< const int64_t > ids)
StatusBuilder InvalidArgumentErrorBuilder()