Google OR-Tools v9.11
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
solution.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 <optional>
17#include <utility>
18
19#include "absl/container/flat_hash_map.h"
20#include "absl/log/check.h"
21#include "absl/status/status.h"
22#include "absl/strings/string_view.h"
23#include "absl/types/span.h"
29#include "ortools/math_opt/solution.pb.h"
30#include "ortools/math_opt/sparse_containers.pb.h"
33
34namespace operations_research {
35namespace math_opt {
36
37std::optional<absl::string_view> Enum<SolutionStatus>::ToOptString(
39 switch (value) {
41 return "feasible";
43 return "infeasible";
45 return "undetermined";
46 }
47 return std::nullopt;
48}
49
50absl::Span<const SolutionStatus> Enum<SolutionStatus>::AllValues() {
51 static constexpr SolutionStatus kSolutionStatusValues[] = {
55 };
56 return absl::MakeConstSpan(kSolutionStatusValues);
57}
58
59absl::StatusOr<PrimalSolution> PrimalSolution::FromProto(
60 const ModelStorage* model,
61 const PrimalSolutionProto& primal_solution_proto) {
62 PrimalSolution primal_solution;
64 primal_solution.variable_values,
65 VariableValuesFromProto(model, primal_solution_proto.variable_values()),
66 _ << "invalid variable_values");
67 primal_solution.objective_value = primal_solution_proto.objective_value();
69 primal_solution.auxiliary_objective_values,
71 model, primal_solution_proto.auxiliary_objective_values()),
72 _ << "invalid auxiliary_objective_values");
73 const std::optional<SolutionStatus> feasibility_status =
74 EnumFromProto(primal_solution_proto.feasibility_status());
75 if (!feasibility_status.has_value()) {
76 return absl::InvalidArgumentError("feasibility_status must be specified");
77 }
78 primal_solution.feasibility_status = *feasibility_status;
79 return primal_solution;
80}
81
82PrimalSolutionProto PrimalSolution::Proto() const {
83 PrimalSolutionProto result;
84 *result.mutable_variable_values() = VariableValuesToProto(variable_values);
85 result.set_objective_value(objective_value);
86 *result.mutable_auxiliary_objective_values() =
88 result.set_feasibility_status(EnumToProto(feasibility_status));
89 return result;
90}
91
92double PrimalSolution::get_objective_value(const Objective objective) const {
93 if (!variable_values.empty()) {
94 // Here we assume all keys are in the same storage. As PrimalSolution is not
95 // properly encapsulated, we can't maintain a ModelStorage pointer and
96 // iterating on all keys would have a too high cost.
97 CHECK_EQ(variable_values.begin()->first.storage(), objective.storage());
98 }
99 if (!objective.is_primary()) {
100 CHECK(auxiliary_objective_values.contains(objective));
101 return auxiliary_objective_values.at(objective);
102 }
103 return objective_value;
104}
105
106absl::StatusOr<PrimalRay> PrimalRay::FromProto(
107 const ModelStorage* model, const PrimalRayProto& primal_ray_proto) {
108 PrimalRay result;
110 result.variable_values,
111 VariableValuesFromProto(model, primal_ray_proto.variable_values()),
112 _ << "invalid variable_values");
113 return result;
114}
115
116PrimalRayProto PrimalRay::Proto() const {
117 PrimalRayProto result;
118 *result.mutable_variable_values() = VariableValuesToProto(variable_values);
119 return result;
120}
121
122absl::StatusOr<DualSolution> DualSolution::FromProto(
123 const ModelStorage* model, const DualSolutionProto& dual_solution_proto) {
124 DualSolution dual_solution;
126 dual_solution.dual_values,
127 LinearConstraintValuesFromProto(model, dual_solution_proto.dual_values()),
128 _ << "invalid dual_values");
131 model, dual_solution_proto.quadratic_dual_values()),
132 _ << "invalid quadratic_dual_values");
134 dual_solution.reduced_costs,
135 VariableValuesFromProto(model, dual_solution_proto.reduced_costs()),
136 _ << "invalid reduced_costs");
137 if (dual_solution_proto.has_objective_value()) {
138 dual_solution.objective_value = dual_solution_proto.objective_value();
139 }
140 const std::optional<SolutionStatus> feasibility_status =
141 EnumFromProto(dual_solution_proto.feasibility_status());
142 if (!feasibility_status.has_value()) {
143 return absl::InvalidArgumentError("feasibility_status must be specified");
144 }
145 dual_solution.feasibility_status = *feasibility_status;
146 return dual_solution;
147}
148
149DualSolutionProto DualSolution::Proto() const {
150 DualSolutionProto result;
151 *result.mutable_dual_values() = LinearConstraintValuesToProto(dual_values);
152 *result.mutable_quadratic_dual_values() =
154 *result.mutable_reduced_costs() = VariableValuesToProto(reduced_costs);
155 if (objective_value.has_value()) {
156 result.set_objective_value(*objective_value);
157 }
158 result.set_feasibility_status(EnumToProto(feasibility_status));
159 return result;
160}
161
162absl::StatusOr<DualRay> DualRay::FromProto(const ModelStorage* model,
163 const DualRayProto& dual_ray_proto) {
164 DualRay result;
166 result.dual_values,
167 LinearConstraintValuesFromProto(model, dual_ray_proto.dual_values()),
168 _ << "invalid dual_values");
170 result.reduced_costs,
171 VariableValuesFromProto(model, dual_ray_proto.reduced_costs()),
172 _ << "invalid reduced_costs");
173 return result;
174}
175
176DualRayProto DualRay::Proto() const {
177 DualRayProto result;
178 *result.mutable_dual_values() = LinearConstraintValuesToProto(dual_values);
179 *result.mutable_reduced_costs() = VariableValuesToProto(reduced_costs);
180 return result;
181}
182
183absl::StatusOr<Basis> Basis::FromProto(const ModelStorage* model,
184 const BasisProto& basis_proto) {
185 Basis basis;
187 basis.constraint_status,
188 LinearConstraintBasisFromProto(model, basis_proto.constraint_status()),
189 _ << "invalid constraint_status");
191 basis.variable_status,
192 VariableBasisFromProto(model, basis_proto.variable_status()),
193 _ << "invalid variable_status");
195 EnumFromProto(basis_proto.basic_dual_feasibility());
196 return basis;
197}
198
200 const ModelStorage* const expected_storage) const {
201 for (const auto& [v, _] : variable_status) {
203 internal::CheckModelStorage(/*storage=*/v.storage(),
204 /*expected_storage=*/expected_storage))
205 << "invalid variable " << v << " in variable_status";
206 }
207 for (const auto& [c, _] : constraint_status) {
210 /*expected_storage=*/expected_storage))
211 << "invalid constraint " << c << " in constraint_status";
212 }
213 return absl::OkStatus();
214}
215
216BasisProto Basis::Proto() const {
217 BasisProto result;
218 *result.mutable_constraint_status() =
220 *result.mutable_variable_status() = VariableBasisToProto(variable_status);
221 result.set_basic_dual_feasibility(EnumToProto(basic_dual_feasibility));
222 return result;
223}
224
225absl::StatusOr<Solution> Solution::FromProto(
226 const ModelStorage* model, const SolutionProto& solution_proto) {
228 if (solution_proto.has_primal_solution()) {
230 solution.primal_solution,
231 PrimalSolution::FromProto(model, solution_proto.primal_solution()),
232 _ << "invalid primal_solution");
233 }
234 if (solution_proto.has_dual_solution()) {
236 solution.dual_solution,
237 DualSolution::FromProto(model, solution_proto.dual_solution()),
238 _ << "invalid dual_solution");
239 }
240 if (solution_proto.has_basis()) {
242 Basis::FromProto(model, solution_proto.basis()),
243 _ << "invalid basis");
244 }
245 return solution;
246}
247
248SolutionProto Solution::Proto() const {
249 SolutionProto result;
250 if (primal_solution.has_value()) {
251 *result.mutable_primal_solution() = primal_solution->Proto();
252 }
253 if (dual_solution.has_value()) {
254 *result.mutable_dual_solution() = dual_solution->Proto();
255 }
256 if (basis.has_value()) {
257 *result.mutable_basis() = basis->Proto();
258 }
259 return result;
260}
261
262} // namespace math_opt
263} // namespace operations_research
#define RETURN_IF_ERROR(expr)
const ModelStorage * storage() const
Returns a const-pointer to the underlying storage object for the model.
Definition objective.h:144
int64_t value
GRBmodel * model
double solution
absl::Status CheckModelStorage(const ModelStorage *const storage, const ModelStorage *const expected_storage)
Definition key_types.h:168
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)
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)
SolutionStatus
Feasibility of a primal or dual solution as claimed by the solver.
Definition solution.h:39
@ kUndetermined
Solver does not claim a feasibility status.
@ kFeasible
Solver claims the solution is feasible.
@ kInfeasible
Solver claims the solution is infeasible.
SparseBasisStatusVector VariableBasisToProto(const VariableMap< BasisStatus > &basis_values)
Returns the proto equivalent of basis_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)
In SWIG mode, we don't want anything besides these top-level includes.
absl::Status CheckModelStorage(const ModelStorage *expected_storage) const
Definition solution.cc:199
LinearConstraintMap< BasisStatus > constraint_status
Definition solution.h:234
static absl::StatusOr< Basis > FromProto(const ModelStorage *model, const BasisProto &basis_proto)
Definition solution.cc:183
VariableMap< BasisStatus > variable_status
Definition solution.h:235
std::optional< SolutionStatus > basic_dual_feasibility
Definition solution.h:249
DualRayProto Proto() const
Returns the proto equivalent of this.
Definition solution.cc:176
static absl::StatusOr< DualRay > FromProto(const ModelStorage *model, const DualRayProto &dual_ray_proto)
Definition solution.cc:162
LinearConstraintMap< double > dual_values
Definition solution.h:188
VariableMap< double > reduced_costs
Definition solution.h:189
static absl::StatusOr< DualSolution > FromProto(const ModelStorage *model, const DualSolutionProto &dual_solution_proto)
Definition solution.cc:122
LinearConstraintMap< double > dual_values
Definition solution.h:147
absl::flat_hash_map< QuadraticConstraint, double > quadratic_dual_values
Definition solution.h:152
std::optional< double > objective_value
Definition solution.h:154
DualSolutionProto Proto() const
Returns the proto equivalent of this.
Definition solution.cc:149
static absl::Span< const E > AllValues()
Returns all possible values of the enum.
static std::optional< absl::string_view > ToOptString(E value)
PrimalRayProto Proto() const
Returns the proto equivalent of this.
Definition solution.cc:116
VariableMap< double > variable_values
Definition solution.h:120
static absl::StatusOr< PrimalRay > FromProto(const ModelStorage *model, const PrimalRayProto &primal_ray_proto)
Definition solution.cc:106
absl::flat_hash_map< Objective, double > auxiliary_objective_values
Definition solution.h:85
static absl::StatusOr< PrimalSolution > FromProto(const ModelStorage *model, const PrimalSolutionProto &primal_solution_proto)
Definition solution.cc:59
PrimalSolutionProto Proto() const
Returns the proto equivalent of this.
Definition solution.cc:82
double get_objective_value(Objective objective) const
Definition solution.cc:92
std::optional< PrimalSolution > primal_solution
Definition solution.h:270
std::optional< DualSolution > dual_solution
Definition solution.h:271
SolutionProto Proto() const
Returns the proto equivalent of this.
Definition solution.cc:248
static absl::StatusOr< Solution > FromProto(const ModelStorage *model, const SolutionProto &solution_proto)
Definition solution.cc:225
#define OR_ASSIGN_OR_RETURN3(lhs, rexpr, error_expression)