23 #include "absl/container/flat_hash_map.h"
24 #include "absl/status/status.h"
25 #include "absl/status/statusor.h"
26 #include "absl/strings/string_view.h"
27 #include "absl/time/time.h"
28 #include "absl/types/span.h"
34 #include "ortools/math_opt/solution.pb.h"
47 return "undetermined";
62 return absl::MakeConstSpan(kFeasibilityStatus);
75 return "infeasible_or_unbounded";
81 return "no_solution_found";
83 return "numerical_error";
102 return absl::MakeConstSpan(kTerminationReasonValues);
108 return "undetermined";
126 return "interrupted";
128 return "slow_progress";
136 static constexpr
Limit kLimitValues[] = {
141 return absl::MakeConstSpan(kLimitValues);
145 : reason(reason), detail(std::move(detail)) {}
154 const std::string detail) {
161 TerminationProto
proto;
174 const TerminationProto& termination_proto) {
175 const std::optional<TerminationReason>
reason =
177 if (!
reason.has_value()) {
178 return absl::InvalidArgumentError(
"reason must be specified");
186 ostr <<
"{reason: " << termination.
reason;
187 if (termination.
limit.has_value()) {
188 ostr <<
", limit: " << *termination.
limit;
190 if (!termination.
detail.empty()) {
192 ostr <<
", detail: " << termination.
detail;
199 std::ostringstream stream;
205 ProblemStatusProto
proto;
213 const ProblemStatusProto& problem_status_proto) {
217 return absl::InvalidArgumentError(
"primal_status must be specified");
219 const std::optional<FeasibilityStatus>
dual_status =
222 return absl::InvalidArgumentError(
"dual_status must be specified");
226 .primal_or_dual_infeasible =
227 problem_status_proto.primal_or_dual_infeasible()};
233 ostr <<
", dual_status: " << problem_status.
dual_status;
234 ostr <<
", primal_or_dual_infeasible: "
241 std::ostringstream stream;
247 SolveStatsProto
proto;
250 <<
"invalid solve_time (value must be finite)";
262 const SolveStatsProto& solve_stats_proto) {
267 _ <<
"invalid solve_time");
273 _ <<
"invalid problem_status");
277 result.
node_count = solve_stats_proto.node_count();
282 ostr <<
"{solve_time: " << solve_stats.
solve_time;
283 ostr <<
", best_primal_bound: "
285 ostr <<
", best_dual_bound: "
291 ostr <<
", node_count: " << solve_stats.
node_count;
297 std::ostringstream stream;
303 if (result.solver_specific_output_case() ==
304 SolveResultProto::SOLVER_SPECIFIC_OUTPUT_NOT_SET) {
305 return absl::OkStatus();
308 <<
"cannot set solver specific output twice, was already "
309 <<
static_cast<int>(result.solver_specific_output_case());
313 SolveResultProto result;
316 _ <<
"invalid solve_stats");
318 *result.add_solutions() = solution.Proto();
321 *result.add_primal_rays() = primal_ray.Proto();
324 *result.add_dual_rays() = dual_ray.Proto();
337 _ <<
"invalid termination");
341 _ <<
"invalid solve_stats");
343 for (
int i = 0; i < solve_result_proto.solutions_size(); ++i) {
347 _ <<
"invalid solution at index " << i);
348 result.
solutions.push_back(std::move(solution));
350 for (
int i = 0; i < solve_result_proto.primal_rays_size(); ++i) {
354 _ <<
"invalid primal ray at index " << i);
355 result.
primal_rays.push_back(std::move(primal_ray));
357 for (
int i = 0; i < solve_result_proto.dual_rays_size(); ++i) {
361 _ <<
"invalid dual ray at index " << i);
362 result.
dual_rays.push_back(std::move(dual_ray));
364 switch (solve_result_proto.solver_specific_output_case()) {
365 case SolveResultProto::kGscipOutput:
368 case SolveResultProto::SOLVER_SPECIFIC_OUTPUT_NOT_SET:
372 <<
"unexpected value of solver_specific_output_case "
373 << solve_result_proto.solver_specific_output_case();
378 (
solutions[0].primal_solution->feasibility_status ==
388 return solutions[0].primal_solution->objective_value;
399 return solutions[0].primal_solution->variable_values;
409 (
solutions[0].dual_solution->feasibility_status ==
415 return solutions[0].dual_solution->dual_values;
420 return solutions[0].dual_solution->reduced_costs;
438 return solutions[0].basis->constraint_status;
443 return solutions[0].basis->variable_status;
448 template <
typename T>
449 void PrintVectorSize(std::ostream& out,
const std::vector<T>& v) {
452 out << v.size() <<
" available";
460 <<
", solve_stats: " << result.
solve_stats <<
", solutions: ";
462 out <<
", primal_rays: ";
464 out <<
", dual_rays: ";
467 const std::string gscip_specific_output =
469 if (!gscip_specific_output.empty()) {
470 out <<
", gscip_solver_specific_output: " << gscip_specific_output;
#define RETURN_IF_ERROR(expr)
absl::Status CheckSolverSpecificOutputEmpty(const SolveResultProto &result)
std::optional< typename EnumProto< P >::Cpp > EnumFromProto(const P proto_value)
std::ostream & operator<<(std::ostream &ostr, const IndicatorConstraint &constraint)
Enum< E >::Proto EnumToProto(const std::optional< E > value)
Collection of objects used to extend the Constraint Solver library.
std::string ProtobufShortDebugString(const P &message)
inline ::absl::StatusOr< absl::Duration > DecodeGoogleApiProto(const google::protobuf::Duration &proto)
inline ::absl::StatusOr< google::protobuf::Duration > EncodeGoogleApiProto(absl::Duration d)
StatusBuilder InvalidArgumentErrorBuilder()
static absl::StatusOr< DualRay > FromProto(const ModelStorage *model, const DualRayProto &dual_ray_proto)
static std::optional< absl::string_view > ToOptString(E value)
static absl::Span< const E > AllValues()
static absl::StatusOr< PrimalRay > FromProto(const ModelStorage *model, const PrimalRayProto &primal_ray_proto)
std::string ToString() const
ProblemStatusProto Proto() const
FeasibilityStatus dual_status
static absl::StatusOr< ProblemStatus > FromProto(const ProblemStatusProto &problem_status_proto)
FeasibilityStatus primal_status
bool primal_or_dual_infeasible
static absl::StatusOr< Solution > FromProto(const ModelStorage *model, const SolutionProto &solution_proto)
double best_objective_bound() const
const VariableMap< double > & ray_variable_values() const
const LinearConstraintMap< double > & dual_values() const
const VariableMap< BasisStatus > & variable_status() const
bool has_dual_ray() const
static absl::StatusOr< SolveResult > FromProto(const ModelStorage *model, const SolveResultProto &solve_result_proto)
bool has_dual_feasible_solution() const
const LinearConstraintMap< double > & ray_dual_values() const
std::vector< PrimalRay > primal_rays
double objective_value() const
absl::StatusOr< SolveResultProto > Proto() const
const VariableMap< double > & ray_reduced_costs() const
const LinearConstraintMap< BasisStatus > & constraint_status() const
std::vector< Solution > solutions
const VariableMap< double > & variable_values() const
const VariableMap< double > & reduced_costs() const
GScipOutput gscip_solver_specific_output
bool has_primal_feasible_solution() const
std::vector< DualRay > dual_rays
std::string ToString() const
ProblemStatus problem_status
absl::StatusOr< SolveStatsProto > Proto() const
static absl::StatusOr< SolveStats > FromProto(const SolveStatsProto &solve_stats_proto)
absl::Duration solve_time
int first_order_iterations
std::string ToString() const
Termination(TerminationReason reason, std::string detail={})
bool limit_reached() const
std::optional< Limit > limit
static absl::StatusOr< Termination > FromProto(const TerminationProto &termination_proto)
static Termination Feasible(Limit limit, std::string detail={})
static Termination NoSolutionFound(Limit limit, std::string detail={})
TerminationProto Proto() const
#define OR_ASSIGN_OR_RETURN3(lhs, rexpr, error_expression)