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