OR-Tools  9.3
solution.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 <optional>
17#include <utility>
18
19#include "absl/container/flat_hash_map.h"
20#include "absl/strings/string_view.h"
21#include "absl/types/span.h"
28#include "ortools/math_opt/solution.pb.h"
29#include "ortools/math_opt/sparse_containers.pb.h"
30
31namespace operations_research {
32namespace math_opt {
33namespace {
34
35template <typename Key>
36IdMap<Key, double> ValuesFrom(const ModelStorage* const model,
37 const SparseDoubleVectorProto& vars_proto) {
38 return IdMap<Key, double>(
39 model, MakeView(vars_proto).as_map<typename Key::IdType>());
40}
41
42template <typename Key>
43IdMap<Key, BasisStatus> BasisValues(
44 const ModelStorage* const model,
45 const SparseBasisStatusVector& basis_proto) {
46 absl::flat_hash_map<typename Key::IdType, BasisStatus> id_map;
47 for (const auto& [id, basis_status_proto] : MakeView(basis_proto)) {
48 // CHECK fails on BASIS_STATUS_UNSPECIFIED (the validation code should have
49 // tested that).
50 // We need to cast because the C++ proto API stores repeated enums as ints.
51 //
52 // On top of that iOS 11 does not support .value() on optionals so we must
53 // use operator*.
54 const std::optional<BasisStatus> basis_status =
55 EnumFromProto(static_cast<BasisStatusProto>(basis_status_proto));
56 CHECK(basis_status.has_value());
57 id_map[static_cast<typename Key::IdType>(id)] = *basis_status;
58 }
59 return IdMap<Key, BasisStatus>(model, std::move(id_map));
60}
61
62} // namespace
63
64std::optional<absl::string_view> Enum<SolutionStatus>::ToOptString(
66 switch (value) {
68 return "feasible";
70 return "infeasible";
72 return "undetermined";
73 }
74 return std::nullopt;
75}
76
77absl::Span<const SolutionStatus> Enum<SolutionStatus>::AllValues() {
78 static constexpr SolutionStatus kSolutionStatusValues[] = {
82 };
83 return absl::MakeConstSpan(kSolutionStatusValues);
84}
85
86std::optional<absl::string_view> Enum<BasisStatus>::ToOptString(
88 switch (value) {
90 return "free";
92 return "at_lower_bound";
94 return "at_upper_bound";
96 return "fixed_value";
98 return "basic";
99 }
100 return std::nullopt;
101}
102
103absl::Span<const BasisStatus> Enum<BasisStatus>::AllValues() {
104 static constexpr BasisStatus kBasisStatusValues[] = {
108 };
109 return absl::MakeConstSpan(kBasisStatusValues);
110}
111
113 const ModelStorage* model,
114 const PrimalSolutionProto& primal_solution_proto) {
115 PrimalSolution primal_solution;
116 primal_solution.variable_values =
117 ValuesFrom<Variable>(model, primal_solution_proto.variable_values());
118 primal_solution.objective_value = primal_solution_proto.objective_value();
119 // TODO(b/209014770): consider adding a function to simplify this pattern.
120 const std::optional<SolutionStatus> feasibility_status =
121 EnumFromProto(primal_solution_proto.feasibility_status());
122 CHECK(feasibility_status.has_value());
123 primal_solution.feasibility_status = *feasibility_status;
124 return primal_solution;
125}
126
128 const PrimalRayProto& primal_ray_proto) {
129 return {.variable_values =
130 ValuesFrom<Variable>(model, primal_ray_proto.variable_values())};
131}
132
134 const ModelStorage* model, const DualSolutionProto& dual_solution_proto) {
135 DualSolution dual_solution;
136 dual_solution.dual_values =
137 ValuesFrom<LinearConstraint>(model, dual_solution_proto.dual_values());
138 dual_solution.reduced_costs =
139 ValuesFrom<Variable>(model, dual_solution_proto.reduced_costs());
140 if (dual_solution_proto.has_objective_value()) {
141 dual_solution.objective_value = dual_solution_proto.objective_value();
142 }
143 // TODO(b/209014770): consider adding a function to simplify this pattern.
144 const std::optional<SolutionStatus> feasibility_status =
145 EnumFromProto(dual_solution_proto.feasibility_status());
146 CHECK(feasibility_status.has_value());
147 dual_solution.feasibility_status = *feasibility_status;
148 return dual_solution;
149}
150
152 const DualRayProto& dual_ray_proto) {
153 return {.dual_values =
154 ValuesFrom<LinearConstraint>(model, dual_ray_proto.dual_values()),
155 .reduced_costs =
156 ValuesFrom<Variable>(model, dual_ray_proto.reduced_costs())};
157}
158
160 const BasisProto& basis_proto) {
161 Basis basis;
162 basis.constraint_status =
163 BasisValues<LinearConstraint>(model, basis_proto.constraint_status());
164 basis.variable_status =
165 BasisValues<Variable>(model, basis_proto.variable_status());
166 // TODO(b/209014770): consider adding a function to simplify this pattern.
167 const std::optional<SolutionStatus> basic_dual_feasibility =
168 EnumFromProto(basis_proto.basic_dual_feasibility());
169 CHECK(basic_dual_feasibility.has_value());
171 return basis;
172}
173
175 const SolutionProto& solution_proto) {
176 Solution solution;
177 if (solution_proto.has_primal_solution()) {
178 solution.primal_solution =
179 PrimalSolution::FromProto(model, solution_proto.primal_solution());
180 }
181 if (solution_proto.has_dual_solution()) {
182 solution.dual_solution =
183 DualSolution::FromProto(model, solution_proto.dual_solution());
184 }
185 if (solution_proto.has_basis()) {
186 solution.basis = Basis::FromProto(model, solution_proto.basis());
187 }
188 return solution;
189}
190
191} // namespace math_opt
192} // namespace operations_research
#define CHECK(condition)
Definition: base/logging.h:495
int64_t value
GRBmodel * model
SparseVectorView< T > MakeView(absl::Span< const int64_t > ids, const Collection &values)
std::optional< typename EnumProto< P >::Cpp > EnumFromProto(const P proto_value)
Definition: enums.h:275
Collection of objects used to extend the Constraint Solver library.
VariableMap< BasisStatus > variable_status
Definition: solution.h:204
LinearConstraintMap< BasisStatus > constraint_status
Definition: solution.h:203
static Basis FromProto(const ModelStorage *model, const BasisProto &basis_proto)
Definition: solution.cc:159
LinearConstraintMap< double > dual_values
Definition: solution.h:165
static DualRay FromProto(const ModelStorage *model, const DualRayProto &dual_ray_proto)
Definition: solution.cc:151
static DualSolution FromProto(const ModelStorage *model, const DualSolutionProto &dual_solution_proto)
Definition: solution.cc:133
LinearConstraintMap< double > dual_values
Definition: solution.h:134
std::optional< double > objective_value
Definition: solution.h:136
static std::optional< absl::string_view > ToOptString(E value)
Definition: callback.cc:75
static absl::Span< const E > AllValues()
Definition: callback.cc:94
VariableMap< double > variable_values
Definition: solution.h:113
static PrimalRay FromProto(const ModelStorage *model, const PrimalRayProto &primal_ray_proto)
Definition: solution.cc:127
static PrimalSolution FromProto(const ModelStorage *model, const PrimalSolutionProto &primal_solution_proto)
Definition: solution.cc:112
static Solution FromProto(const ModelStorage *model, const SolutionProto &solution_proto)
Definition: solution.cc:174
std::optional< DualSolution > dual_solution
Definition: solution.h:224
std::optional< PrimalSolution > primal_solution
Definition: solution.h:223
std::optional< Basis > basis
Definition: solution.h:225