Google OR-Tools v9.11
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
highs_solver.h
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
14#ifndef OR_TOOLS_MATH_OPT_SOLVERS_HIGHS_SOLVER_H_
15#define OR_TOOLS_MATH_OPT_SOLVERS_HIGHS_SOLVER_H_
16
17#include <cmath>
18#include <memory>
19#include <optional>
20#include <utility>
21#include <vector>
22
23#include "Highs.h"
24#include "absl/container/flat_hash_map.h"
25#include "absl/status/status.h"
26#include "absl/status/statusor.h"
28#include "ortools/math_opt/callback.pb.h"
31#include "ortools/math_opt/model.pb.h"
32#include "ortools/math_opt/model_parameters.pb.h"
33#include "ortools/math_opt/model_update.pb.h"
34#include "ortools/math_opt/parameters.pb.h"
35#include "ortools/math_opt/result.pb.h"
36#include "ortools/math_opt/solution.pb.h"
38
40
42 public:
43 static absl::StatusOr<std::unique_ptr<SolverInterface>> New(
44 const ModelProto& model, const InitArgs& init_args);
45
46 absl::StatusOr<SolveResultProto> Solve(
47 const SolveParametersProto& parameters,
48 const ModelSolveParametersProto& model_parameters,
49 MessageCallback message_cb,
50 const CallbackRegistrationProto& callback_registration, Callback cb,
51 const SolveInterrupter* interrupter) override;
52 absl::StatusOr<bool> Update(const ModelUpdateProto& model_update) override;
53 absl::StatusOr<ComputeInfeasibleSubsystemResultProto>
54 ComputeInfeasibleSubsystem(const SolveParametersProto& parameters,
55 MessageCallback message_cb,
56 const SolveInterrupter* interrupter) override;
57
58 private:
59 struct SolutionClaims {
60 bool highs_returned_primal_feasible_solution = false;
61 bool highs_returned_dual_feasible_solution = false;
62 bool highs_returned_primal_ray = false;
63 bool highs_returned_dual_ray = false;
64 };
65 struct SolutionsAndClaims {
66 std::vector<SolutionProto> solutions;
67 // TODO(b/271104776): add rays.
68 SolutionClaims solution_claims;
69 };
70
71 // Tracks the upper and lower bounds for either a variable or linear
72 // constraint in the HiGHS model.
73 //
74 // Note that HiGHS does not allow bounds to cross. If a bound would cross, it
75 // is set to zero in the actual HiGHS model and its true values are tracked
76 // here (they may uncross before solve time on a model update).
77 struct IndexAndBound {
78 // The position of the variable/linear constraint in the HiGHS model. Note
79 // that this is distinct from the MathOpt id.
80 int index;
81 double lb;
82 double ub;
83
84 // TODO(b/271595607): we won't need to track this once a bug in HiGHS is
85 // fixed. Always false for constraints.
86 bool is_integer;
87
88 bool bounds_cross() const { return lb > ub; }
89
90 // If we don't round the bounds for integer variables, HiGHS can give
91 // garbage results, see go/paste/4836036214521856 for details. See also
92 // b/271595607.
93 double rounded_lb() const { return is_integer ? std::ceil(lb) : lb; }
94 double rounded_ub() const { return is_integer ? std::floor(ub) : ub; }
95 bool rounded_bounds_cross() const { return rounded_lb() > rounded_ub(); }
96
97 IndexAndBound(int index, double lb, double ub, bool is_integer)
98 : index(index), lb(lb), ub(ub), is_integer(is_integer) {}
99 };
100 HighsSolver(std::unique_ptr<Highs> highs,
101 absl::flat_hash_map<int64_t, IndexAndBound> variable_data,
102 absl::flat_hash_map<int64_t, IndexAndBound> lin_con_data)
103 : highs_(std::move(highs)),
104 variable_data_(std::move(variable_data)),
105 lin_con_data_(std::move(lin_con_data)) {}
106
107 absl::StatusOr<bool> PrimalRayReturned() const;
108 absl::StatusOr<bool> DualRayReturned() const;
109
110 // Will append solutions and rays to result_out. No other modifications are
111 // made to result_out. Requires that highs_->getInfo is validated.
112 absl::StatusOr<SolutionsAndClaims> ExtractSolutionAndRays(
113 const ModelSolveParametersProto& model_params);
114
115 static absl::StatusOr<FeasibilityStatusProto> PrimalFeasibilityStatus(
116 SolutionClaims solution_claims);
117 static absl::StatusOr<FeasibilityStatusProto> DualFeasibilityStatus(
118 const HighsInfo& highs_info, bool is_integer,
119 SolutionClaims solution_claims);
120 static absl::StatusOr<TerminationProto> MakeTermination(
121 HighsModelStatus highs_model_status, const HighsInfo& highs_info,
122 bool is_integer, bool had_node_limit, bool had_solution_limit,
123 bool is_maximize, SolutionClaims solution_claims);
124
125 // Returns the current basis if it is available and MathOpt can represent it
126 // (all kNonBasic values can be made more precise, see b/272767311).
127 absl::StatusOr<std::optional<BasisProto>> ExtractBasis();
128
129 template <typename T>
130 absl::Status EnsureOneEntryPerVariable(const std::vector<T>& vec) {
131 if (vec.size() != variable_data_.size()) {
133 << "expected one entry per variable, but model had "
134 << variable_data_.size() << " variables and found " << vec.size()
135 << " elements";
136 }
137 return absl::OkStatus();
138 }
139
140 template <typename T>
141 absl::Status EnsureOneEntryPerLinearConstraint(const std::vector<T>& vec) {
142 if (vec.size() != lin_con_data_.size()) {
144 << "expected one entry per linear constraint, but model had "
145 << lin_con_data_.size() << " linear constraints and found "
146 << vec.size() << " elements";
147 }
148 return absl::OkStatus();
149 }
150
151 // Returns a SolveResult for when HiGHS returns the model status
152 // HighsModelStatus::kModelEmpty. This happens on models that have no
153 // variables, but may still have (potentially infeasible) linear constraints
154 // and an objective offset.
155 //
156 // Assumes that there are no inverted linear constraint bounds.
157 static SolveResultProto ResultForHighsModelStatusModelEmpty(
158 bool is_maximize, double objective_offset,
159 const absl::flat_hash_map<int64_t, IndexAndBound>& lin_con_data);
160
161 InvertedBounds ListInvertedBounds();
162
163 std::unique_ptr<Highs> highs_;
164
165 // Key is the mathopt id, value.index is the variable index in HiGHS.
166 absl::flat_hash_map<int64_t, IndexAndBound> variable_data_;
167
168 // Key is the mathopt id, value.index is the linear constraint index in HiGHS.
169 absl::flat_hash_map<int64_t, IndexAndBound> lin_con_data_;
170};
171
172} // namespace operations_research::math_opt
173
174#endif // OR_TOOLS_MATH_OPT_SOLVERS_HIGHS_SOLVER_H_
static absl::StatusOr< std::unique_ptr< SolverInterface > > New(const ModelProto &model, const InitArgs &init_args)
absl::StatusOr< SolveResultProto > Solve(const SolveParametersProto &parameters, const ModelSolveParametersProto &model_parameters, MessageCallback message_cb, const CallbackRegistrationProto &callback_registration, Callback cb, const SolveInterrupter *interrupter) override
absl::StatusOr< ComputeInfeasibleSubsystemResultProto > ComputeInfeasibleSubsystem(const SolveParametersProto &parameters, MessageCallback message_cb, const SolveInterrupter *interrupter) override
absl::StatusOr< bool > Update(const ModelUpdateProto &model_update) override
std::function< void(const std::vector< std::string > &)> MessageCallback
std::function< absl::StatusOr< CallbackResultProto >( const CallbackDataProto &)> Callback
SatParameters parameters
GRBmodel * model
int index
An object oriented wrapper for quadratic constraints in ModelStorage.
Definition gurobi_isv.cc:28
StatusBuilder InvalidArgumentErrorBuilder()