20#include "absl/status/status.h"
21#include "absl/status/statusor.h"
22#include "absl/strings/str_cat.h"
23#include "absl/time/time.h"
24#include "ortools/math_opt/result.pb.h"
34constexpr double kInf = std::numeric_limits<double>::infinity();
36absl::Status ValidateFeasibilityStatus(
const FeasibilityStatusProto&
status) {
37 if (!FeasibilityStatusProto_IsValid(
status)) {
38 return absl::InvalidArgumentError(absl::StrCat(
"invalid status ",
status));
40 if (
status == FEASIBILITY_STATUS_UNSPECIFIED) {
41 return absl::InvalidArgumentError(
42 "invalid status FEASIBILITY_STATUS_UNSPECIFIED");
44 return absl::OkStatus();
50 <<
"invalid primal_status";
52 <<
"invalid dual_status";
53 if (
status.primal_or_dual_infeasible() &&
54 (
status.primal_status() != FEASIBILITY_STATUS_UNDETERMINED ||
55 status.dual_status() != FEASIBILITY_STATUS_UNDETERMINED)) {
56 return absl::InvalidArgumentError(absl::StrCat(
57 "primal_or_dual_infeasible can be true only when primal status = dual "
58 "status = FEASIBILITY_STATUS_UNDETERMINED, and we have primal status "
63 return absl::OkStatus();
68 const FeasibilityStatusProto required_status) {
69 const FeasibilityStatusProto actual_status =
status.primal_status();
70 if (actual_status == required_status) {
71 return absl::OkStatus();
73 return absl::InvalidArgumentError(
74 absl::StrCat(
"expected problem_status.primal_status = ",
81 const ProblemStatusProto&
status,
82 const FeasibilityStatusProto forbidden_status) {
83 const FeasibilityStatusProto actual_status =
status.primal_status();
84 if (actual_status != forbidden_status) {
85 return absl::OkStatus();
87 return absl::InvalidArgumentError(
88 absl::StrCat(
"expected problem_status.primal_status != ",
94 const ProblemStatusProto&
status,
95 const FeasibilityStatusProto forbidden_status) {
96 const FeasibilityStatusProto actual_status =
status.dual_status();
97 if (actual_status != forbidden_status) {
98 return absl::OkStatus();
100 return absl::InvalidArgumentError(
101 absl::StrCat(
"expected problem_status.dual_status != ",
107 const FeasibilityStatusProto required_status,
108 const bool primal_or_dual_infeasible_also_ok) {
109 const FeasibilityStatusProto actual_status =
status.dual_status();
110 if (actual_status == required_status) {
111 return absl::OkStatus();
113 if (primal_or_dual_infeasible_also_ok &&
status.primal_or_dual_infeasible()) {
116 return absl::OkStatus();
118 if (primal_or_dual_infeasible_also_ok) {
119 return absl::InvalidArgumentError(absl::StrCat(
120 "expected either problem_status.dual_status = ",
123 ") or problem_status.primal_or_dual_infeasible = true (and "
126 return absl::InvalidArgumentError(
127 absl::StrCat(
"expected problem_status.dual_status = ",
134absl::Status ValidateSolveStatsConsistency(
const SolveStatsProto& solve_stats) {
137 if (solve_stats.problem_status().primal_or_dual_infeasible() &&
138 std::isfinite(solve_stats.best_primal_bound())) {
139 return absl::InvalidArgumentError(
140 "best_primal_bound is finite, but problem status is "
141 "primal_or_dual_infeasible");
143 if (solve_stats.problem_status().primal_or_dual_infeasible() &&
144 std::isfinite(solve_stats.best_dual_bound())) {
145 return absl::InvalidArgumentError(
146 "best_dual_bound is finite, but problem status is "
147 "primal_or_dual_infeasible");
149 if (solve_stats.problem_status().primal_status() !=
150 FEASIBILITY_STATUS_FEASIBLE &&
151 std::isfinite(solve_stats.best_primal_bound())) {
152 return absl::InvalidArgumentError(
153 absl::StrCat(
"best_primal_bound is finite, but primal_status is not "
154 "feasible (primal_status = ",
155 solve_stats.problem_status().primal_status()));
157 if (solve_stats.problem_status().dual_status() !=
158 FEASIBILITY_STATUS_FEASIBLE &&
159 std::isfinite(solve_stats.best_dual_bound())) {
160 return absl::InvalidArgumentError(
161 absl::StrCat(
"best_dual_bound is finite, but dual_status is not "
162 "feasible (dual_status = ",
163 solve_stats.problem_status().dual_status()));
165 return absl::OkStatus();
170 const absl::StatusOr<absl::Duration> solve_time =
172 if (!solve_time.ok()) {
173 return absl::InvalidArgumentError(
174 absl::StrCat(
"invalid solve_time, ", solve_time.status().message()));
176 if (solve_time.value() < absl::ZeroDuration()) {
177 return absl::InvalidArgumentError(
"solve_time must be non-negative");
179 if (solve_stats.simplex_iterations() < 0) {
180 return absl::InvalidArgumentError(
181 "simplex_iterations must be non-negative");
183 if (solve_stats.barrier_iterations() < 0) {
184 return absl::InvalidArgumentError(
185 "barrier_iterations must be non-negative");
187 if (solve_stats.node_count() < 0) {
188 return absl::InvalidArgumentError(
"node_count must be non-negative");
193 <<
"in best_primal_bound";
195 <<
"in best_dual_bound";
197 return absl::OkStatus();
absl::Status CheckScalar(const double value, const DoubleOptions &options)
absl::Status CheckPrimalStatusIs(const ProblemStatusProto &status, const FeasibilityStatusProto required_status)
absl::Status CheckDualStatusIs(const ProblemStatusProto &status, const FeasibilityStatusProto required_status, const bool primal_or_dual_infeasible_also_ok)
absl::Status ValidateProblemStatus(const ProblemStatusProto &status)
absl::Status CheckDualStatusIsNot(const ProblemStatusProto &status, const FeasibilityStatusProto forbidden_status)
absl::Status CheckPrimalStatusIsNot(const ProblemStatusProto &status, const FeasibilityStatusProto forbidden_status)
absl::Status ValidateSolveStats(const SolveStatsProto &solve_stats)
Collection of objects used to extend the Constraint Solver library.
std::string ProtoEnumToString(ProtoEnumType enum_value)
inline ::absl::StatusOr< absl::Duration > DecodeGoogleApiProto(const google::protobuf::Duration &proto)
#define RETURN_IF_ERROR(expr)