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"
26#include "ortools/math_opt/result.pb.h"
34absl::Status ValidateFeasibilityStatus(
const FeasibilityStatusProto&
status) {
35 if (!FeasibilityStatusProto_IsValid(
status)) {
36 return absl::InvalidArgumentError(absl::StrCat(
"invalid status ",
status));
38 if (
status == FEASIBILITY_STATUS_UNSPECIFIED) {
39 return absl::InvalidArgumentError(
40 "invalid status FEASIBILITY_STATUS_UNSPECIFIED");
42 return absl::OkStatus();
48 <<
"invalid primal_status";
50 <<
"invalid dual_status";
51 if (
status.primal_or_dual_infeasible() &&
52 (
status.primal_status() != FEASIBILITY_STATUS_UNDETERMINED ||
53 status.dual_status() != FEASIBILITY_STATUS_UNDETERMINED)) {
54 return absl::InvalidArgumentError(absl::StrCat(
55 "primal_or_dual_infeasible can be true only when primal status = dual "
56 "status = FEASIBILITY_STATUS_UNDETERMINED, and we have primal status "
61 return absl::OkStatus();
66 const FeasibilityStatusProto required_status) {
67 const FeasibilityStatusProto actual_status =
status.primal_status();
68 if (actual_status == required_status) {
69 return absl::OkStatus();
71 return absl::InvalidArgumentError(
72 absl::StrCat(
"expected problem_status.primal_status = ",
79 const ProblemStatusProto&
status,
80 const FeasibilityStatusProto forbidden_status) {
81 const FeasibilityStatusProto actual_status =
status.primal_status();
82 if (actual_status != forbidden_status) {
83 return absl::OkStatus();
85 return absl::InvalidArgumentError(
86 absl::StrCat(
"expected problem_status.primal_status != ",
92 const ProblemStatusProto&
status,
93 const FeasibilityStatusProto forbidden_status) {
94 const FeasibilityStatusProto actual_status =
status.dual_status();
95 if (actual_status != forbidden_status) {
96 return absl::OkStatus();
98 return absl::InvalidArgumentError(
99 absl::StrCat(
"expected problem_status.dual_status != ",
105 const FeasibilityStatusProto required_status,
106 const bool primal_or_dual_infeasible_also_ok) {
107 const FeasibilityStatusProto actual_status =
status.dual_status();
108 if (actual_status == required_status) {
109 return absl::OkStatus();
111 if (primal_or_dual_infeasible_also_ok &&
status.primal_or_dual_infeasible()) {
114 return absl::OkStatus();
116 if (primal_or_dual_infeasible_also_ok) {
117 return absl::InvalidArgumentError(absl::StrCat(
118 "expected either problem_status.dual_status = ",
121 ") or problem_status.primal_or_dual_infeasible = true (and "
124 return absl::InvalidArgumentError(
125 absl::StrCat(
"expected problem_status.dual_status = ",
132absl::Status ValidateSolveStatsConsistency(
const SolveStatsProto& solve_stats) {
135 if (solve_stats.problem_status().primal_or_dual_infeasible() &&
136 std::isfinite(solve_stats.best_primal_bound())) {
137 return absl::InvalidArgumentError(
138 "best_primal_bound is finite, but problem status is "
139 "primal_or_dual_infeasible");
141 if (solve_stats.problem_status().primal_or_dual_infeasible() &&
142 std::isfinite(solve_stats.best_dual_bound())) {
143 return absl::InvalidArgumentError(
144 "best_dual_bound is finite, but problem status is "
145 "primal_or_dual_infeasible");
147 if (solve_stats.problem_status().primal_status() !=
148 FEASIBILITY_STATUS_FEASIBLE &&
149 std::isfinite(solve_stats.best_primal_bound())) {
150 return absl::InvalidArgumentError(
151 absl::StrCat(
"best_primal_bound is finite, but primal_status is not "
152 "feasible (primal_status = ",
153 solve_stats.problem_status().primal_status(),
")"));
155 if (solve_stats.problem_status().dual_status() !=
156 FEASIBILITY_STATUS_FEASIBLE &&
157 std::isfinite(solve_stats.best_dual_bound())) {
158 return absl::InvalidArgumentError(
159 absl::StrCat(
"best_dual_bound is finite, but dual_status is not "
160 "feasible (dual_status = ",
161 solve_stats.problem_status().dual_status(),
")"));
163 return absl::OkStatus();
168 const absl::StatusOr<absl::Duration> solve_time =
170 if (!solve_time.ok()) {
171 return absl::InvalidArgumentError(
172 absl::StrCat(
"invalid solve_time, ", solve_time.status().message()));
174 if (solve_time.value() < absl::ZeroDuration()) {
175 return absl::InvalidArgumentError(
"solve_time must be non-negative");
177 if (solve_stats.simplex_iterations() < 0) {
178 return absl::InvalidArgumentError(
179 "simplex_iterations must be non-negative");
181 if (solve_stats.barrier_iterations() < 0) {
182 return absl::InvalidArgumentError(
183 "barrier_iterations must be non-negative");
185 if (solve_stats.node_count() < 0) {
186 return absl::InvalidArgumentError(
"node_count must be non-negative");
191 <<
"in best_primal_bound";
193 <<
"in best_dual_bound";
195 return absl::OkStatus();
#define RETURN_IF_ERROR(expr)
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)