14 #if defined(USE_HIGHS)
23 #include "absl/base/attributes.h"
24 #include "absl/status/status.h"
25 #include "absl/status/statusor.h"
26 #include "absl/strings/str_cat.h"
27 #include "absl/types/optional.h"
28 #include "google/protobuf/text_format.h"
31 #include "ortools/linear_solver/linear_solver.pb.h"
37 class HighsInterface :
public MPSolverInterface {
39 explicit HighsInterface(MPSolver*
const solver,
bool solve_as_a_mip);
40 ~HighsInterface()
override;
44 std::optional<MPSolutionResponse> DirectlySolveProto(
45 const MPModelRequest& request, std::atomic<bool>* interrupt)
override;
48 void Reset()
override;
49 void SetOptimizationDirection(
bool maximize)
override;
50 void SetVariableBounds(
int index,
double lb,
double ub)
override;
51 void SetVariableInteger(
int index,
bool integer)
override;
52 void SetConstraintBounds(
int index,
double lb,
double ub)
override;
53 void AddRowConstraint(MPConstraint*
const ct)
override;
54 void AddVariable(MPVariable*
const var)
override;
55 void SetCoefficient(MPConstraint*
const constraint,
56 const MPVariable*
const variable,
double new_value,
57 double old_value)
override;
58 void ClearConstraint(MPConstraint*
const constraint)
override;
59 void SetObjectiveCoefficient(
const MPVariable*
const variable,
61 void SetObjectiveOffset(
double value)
override;
62 void ClearObjective()
override;
65 int64_t iterations()
const override;
66 int64_t
nodes()
const override;
71 bool IsContinuous()
const override;
72 bool IsLP()
const override;
73 bool IsMIP()
const override;
75 std::string SolverVersion()
const override;
76 void* underlying_solver()
override;
78 void ExtractNewVariables()
override;
79 void ExtractNewConstraints()
override;
80 void ExtractObjective()
override;
82 void SetParameters(
const MPSolverParameters& param)
override;
83 void SetRelativeMipGap(
double value)
override;
84 void SetPrimalTolerance(
double value)
override;
85 void SetDualTolerance(
double value)
override;
86 void SetPresolveMode(
int value)
override;
87 void SetScalingMode(
int value)
override;
88 void SetLpAlgorithm(
int value)
override;
89 bool SetSolverSpecificParametersAsString(
91 absl::Status SetNumThreads(
int num_threads)
override;
94 void NonIncrementalChange();
96 const bool solve_as_a_mip_;
99 HighsInterface::HighsInterface(MPSolver*
const solver,
bool solve_as_a_mip)
100 : MPSolverInterface(solver), solve_as_a_mip_(solve_as_a_mip) {}
102 HighsInterface::~HighsInterface() {}
109 SetParameters(param);
116 solver_->SetSolverSpecificParametersAsString(
117 solver_->solver_specific_parameter_string_);
120 if (solver_->time_limit()) {
121 VLOG(1) <<
"Setting time limit = " << solver_->time_limit() <<
" ms.";
127 for (
int i = 0; i < solver_->variables_.size(); ++i) {
128 set_variable_as_extracted(i,
true);
130 for (
int i = 0; i < solver_->constraints_.size(); ++i) {
131 set_constraint_as_extracted(i,
true);
136 MPModelRequest request;
138 request.set_solver_type(solve_as_a_mip_
139 ? MPModelRequest::HIGHS_MIXED_INTEGER_PROGRAMMING
140 : MPModelRequest::HIGHS_LINEAR_PROGRAMMING);
146 LOG(ERROR) <<
"Unexpected error solving with Highs: " <<
response.status();
151 sync_status_ = SOLUTION_SYNCHRONIZED;
152 result_status_ =
static_cast<MPSolver::ResultStatus
>(
response->status());
160 if (
response->status() == MPSOLVER_FEASIBLE ||
161 response->status() == MPSOLVER_OPTIMAL) {
162 const absl::Status result = solver_->LoadSolutionFromProto(*
response);
164 LOG(ERROR) <<
"LoadSolutionFromProto failed: " << result;
168 return result_status_;
171 std::optional<MPSolutionResponse> HighsInterface::DirectlySolveProto(
172 const MPModelRequest& request, std::atomic<bool>* interrupt) {
173 if (interrupt)
return std::nullopt;
177 LOG(ERROR) <<
"Unexpected error solving with Highs: " <<
response.status();
178 MPSolutionResponse error_response;
179 error_response.set_status(MPSolverResponseStatus::MPSOLVER_ABNORMAL);
180 error_response.set_status_str(
response.status().ToString());
181 return error_response;
187 void HighsInterface::Reset() { ResetExtractionInformation(); }
189 void HighsInterface::SetOptimizationDirection(
bool maximize) {
190 NonIncrementalChange();
193 void HighsInterface::SetVariableBounds(
int index,
double lb,
double ub) {
194 NonIncrementalChange();
197 void HighsInterface::SetVariableInteger(
int index,
bool integer) {
198 NonIncrementalChange();
201 void HighsInterface::SetConstraintBounds(
int index,
double lb,
double ub) {
202 NonIncrementalChange();
205 void HighsInterface::AddRowConstraint(MPConstraint*
const ct) {
206 NonIncrementalChange();
209 void HighsInterface::AddVariable(MPVariable*
const var) {
210 NonIncrementalChange();
213 void HighsInterface::SetCoefficient(MPConstraint*
const constraint,
214 const MPVariable*
const variable,
215 double new_value,
double old_value) {
216 NonIncrementalChange();
219 void HighsInterface::ClearConstraint(MPConstraint*
const constraint) {
220 NonIncrementalChange();
223 void HighsInterface::SetObjectiveCoefficient(
const MPVariable*
const variable,
225 NonIncrementalChange();
228 void HighsInterface::SetObjectiveOffset(
double value) {
229 NonIncrementalChange();
232 void HighsInterface::ClearObjective() { NonIncrementalChange(); }
234 int64_t HighsInterface::iterations()
const {
239 LOG(DFATAL) <<
"Number of nodes only available for discrete problems";
240 return MPSolverInterface::kUnknownNumberOfNodes;
246 return MPSolver::BasisStatus::FREE;
252 return MPSolver::BasisStatus::FREE;
255 bool HighsInterface::IsContinuous()
const {
return true; }
257 bool HighsInterface::IsLP()
const {
return true; }
259 bool HighsInterface::IsMIP()
const {
return solve_as_a_mip_; }
261 std::string HighsInterface::SolverVersion()
const {
return "PDLP Solver"; }
265 void* HighsInterface::underlying_solver() {
return nullptr; }
267 void HighsInterface::ExtractNewVariables() { NonIncrementalChange(); }
269 void HighsInterface::ExtractNewConstraints() { NonIncrementalChange(); }
271 void HighsInterface::ExtractObjective() { NonIncrementalChange(); }
273 void HighsInterface::SetParameters(
const MPSolverParameters& param) {
274 SetCommonParameters(param);
277 absl::Status HighsInterface::SetNumThreads(
int num_threads) {
278 if (num_threads < 1) {
279 return absl::InvalidArgumentError(
280 absl::StrCat(
"Invalid number of threads: ", num_threads));
283 return absl::OkStatus();
287 void HighsInterface::SetPrimalTolerance(
double value) {}
288 void HighsInterface::SetDualTolerance(
double value) {}
289 void HighsInterface::SetScalingMode(
int value) {}
290 void HighsInterface::SetLpAlgorithm(
int value) {}
291 void HighsInterface::SetRelativeMipGap(
double value) {}
292 void HighsInterface::SetPresolveMode(
int value) {}
294 bool HighsInterface::SetSolverSpecificParametersAsString(
300 void HighsInterface::NonIncrementalChange() {
302 sync_status_ = MUST_RELOAD;
306 MPSolverInterface* BuildHighsInterface(
bool mip, MPSolver*
const solver) {
307 return new HighsInterface(solver, mip);
ResultStatus
The status of solving the problem.
BasisStatus
Advanced usage: possible basis status values for a variable and the slack variable of a linear constr...
CpModelProto const * model_proto
SharedResponseManager * response
A C++ wrapper that provides a simple and unified interface to several linear programming and mixed in...
absl::StatusOr< SolveResult > Solve(const Model &model, const SolverType solver_type, const SolveArguments &solve_args, const SolverInitArguments &init_args)
Collection of objects used to extend the Constraint Solver library.
absl::StatusOr< MPSolutionResponse > HighsSolveProto(MPModelRequest request)
#define VLOG(verboselevel)