Google OR-Tools v9.11
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
solver.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 <stddef.h>
17
18#include <cstdlib>
19#include <cstring>
20#include <ios>
21#include <limits>
22#include <utility>
23
24#include "absl/log/check.h"
25#include "absl/status/status.h"
26#include "absl/status/statusor.h"
30#include "ortools/math_opt/model.pb.h"
31#include "ortools/math_opt/parameters.pb.h"
32#include "ortools/math_opt/result.pb.h"
34
38
40namespace {
41
42// Returns a serialized SolveResultProto and its size. The caller is responsible
43// for freeing the result.
44absl::StatusOr<std::pair<void*, size_t>> SolveImpl(
45 const void* model_bytes, const size_t model_size, const int solver_type,
46 MathOptInterrupter* const interrupter, const bool build_result) {
47 if (model_bytes == nullptr && model_size != 0) {
48 return absl::InvalidArgumentError(
49 "model cannot be null unless model_size is zero");
50 }
51 if (model_size > std::numeric_limits<int>::max()) {
53 << "model_size must be at most max int, was: " << model_size;
54 }
55 ModelProto model;
56 if (model_size > 0) {
57 if (!model.ParseFromArray(model_bytes, static_cast<int>(model_size))) {
58 return absl::InvalidArgumentError("bad model proto");
59 }
60 }
61 Solver::InitArgs init_args;
62 Solver::SolveArgs solve_args;
63 if (interrupter != nullptr) {
64 solve_args.interrupter = &interrupter->cpp_interrupter;
65 }
66 ASSIGN_OR_RETURN(const SolveResultProto result,
68 model, static_cast<SolverTypeProto>(solver_type),
69 init_args, solve_args));
70 const size_t result_size_bytes = result.ByteSizeLong();
71 if (result_size_bytes > std::numeric_limits<int>::max()) {
73 << "cannot serialize a SolveResultProto with more than INT_MAX = "
74 << std::numeric_limits<int>::max() << "(0x" << std::hex
75 << std::numeric_limits<int>::max() << std::dec
76 << ") bytes, but solve result proto needed " << result_size_bytes
77 << " bytes in binary format";
78 }
79 void* result_bin = nullptr;
80 if (build_result) {
81 result_bin = malloc(result_size_bytes);
82 // For current implementation, only fails on proto3 when the size is bigger
83 // than 2 gigs.
84 const bool serialize_ok = result.SerializeToArray(
85 result_bin, static_cast<int>(result_size_bytes));
86 if (!serialize_ok) {
87 free(result_bin);
88 return absl::InternalError("fail to serialize SolveResultProto");
89 }
90 }
91 return std::make_pair(result_bin, result_size_bytes);
92}
93
94} // namespace
95} // namespace operations_research::math_opt
96
98
100 delete interrupter;
101}
102
104 CHECK(interrupter != nullptr);
105 interrupter->cpp_interrupter.Interrupt();
106}
108 CHECK(interrupter != nullptr);
109 return static_cast<int>(interrupter->cpp_interrupter.IsInterrupted());
110}
111
112int MathOptSolve(const void* model, const size_t model_size,
113 const int solver_type, MathOptInterrupter* const interrupter,
114 void** solve_result, size_t* solve_result_size,
115 char** status_msg) {
116 const absl::StatusOr<std::pair<void*, size_t>> result =
117 operations_research::math_opt::SolveImpl(
118 model, model_size, solver_type, interrupter,
119 /*build_result=*/solve_result != nullptr);
120 if (result.ok()) {
121 if (solve_result_size != nullptr) {
122 *solve_result_size = result->second;
123 }
124 if (solve_result != nullptr) {
125 *solve_result = result->first;
126 }
127 if (status_msg != nullptr) {
128 *status_msg = nullptr;
129 }
130 return 0;
131 }
132 // WARNING: failure could be caused by null arguments!
133 if (status_msg != nullptr) {
134 const size_t num_bytes = result.status().message().size() + 1;
135 *status_msg = static_cast<char*>(malloc(num_bytes));
136 std::memcpy(*status_msg, result.status().message().data(), num_bytes);
137 }
138 if (solve_result != nullptr) {
139 *solve_result = nullptr;
140 }
141 if (solve_result_size != nullptr) {
142 *solve_result_size = 0;
143 }
144 return result.status().raw_code();
145}
146
147void MathOptFree(void* ptr) { free(ptr); }
#define ASSIGN_OR_RETURN(lhs, rexpr)
void MathOptFree(void *ptr)
Definition solver.cc:147
int MathOptIsInterrupted(const MathOptInterrupter *interrupter)
Definition solver.cc:107
void MathOptInterrupt(MathOptInterrupter *interrupter)
Definition solver.cc:103
int MathOptSolve(const void *model, const size_t model_size, const int solver_type, MathOptInterrupter *const interrupter, void **solve_result, size_t *solve_result_size, char **status_msg)
Definition solver.cc:112
MathOptInterrupter * MathOptNewInterrupter()
Definition solver.cc:97
void MathOptFreeInterrupter(MathOptInterrupter *interrupter)
Frees interrupter, has no effect when interrupter is NULL.
Definition solver.cc:99
static absl::StatusOr< SolveResultProto > NonIncrementalSolve(const ModelProto &model, SolverTypeProto solver_type, const InitArgs &init_args, const SolveArgs &solve_args)
A shortcut for calling Solver::New() and then Solver::Solve().
Definition solver.cc:70
SolverInterface::InitArgs InitArgs
Definition solver.h:68
GRBmodel * model
An object oriented wrapper for quadratic constraints in ModelStorage.
Definition gurobi_isv.cc:28
StatusBuilder InvalidArgumentErrorBuilder()
void * malloc(YYSIZE_T)
void free(void *)
operations_research::SolveInterrupter cpp_interrupter
Definition solver.cc:36