20#include "absl/status/status.h"
21#include "absl/strings/str_cat.h"
22#include "absl/strings/string_view.h"
25#include "ortools/math_opt/result.pb.h"
31constexpr double kInf = std::numeric_limits<double>::infinity();
34 if (!FeasibilityStatusProto_IsValid(
status)) {
35 return absl::InvalidArgumentError(absl::StrCat(
"invalid status ",
status));
37 if (
status == FEASIBILITY_STATUS_UNSPECIFIED) {
38 return absl::InvalidArgumentError(
39 "invalid status FEASIBILITY_STATUS_UNSPECIFIED");
41 return absl::OkStatus();
46 <<
"invalid primal_status";
48 <<
"invalid dual_status";
49 if (
status.primal_or_dual_infeasible() &&
50 (
status.primal_status() != FEASIBILITY_STATUS_UNDETERMINED ||
51 status.dual_status() != FEASIBILITY_STATUS_UNDETERMINED)) {
52 return absl::InvalidArgumentError(absl::StrCat(
53 "primal_or_dual_infeasible can be true only when primal status = dual "
54 "status = FEASIBILITY_STATUS_UNDETERMINED, and we have primal status "
59 return absl::OkStatus();
64 const FeasibilityStatusProto required_status) {
65 const FeasibilityStatusProto actual_status =
status.primal_status();
66 if (actual_status == required_status) {
67 return absl::OkStatus();
69 return absl::InvalidArgumentError(
70 absl::StrCat(
"expected problem_status.primal_status = ",
77 const ProblemStatusProto&
status,
78 const FeasibilityStatusProto forbidden_status) {
79 const FeasibilityStatusProto actual_status =
status.primal_status();
80 if (actual_status != forbidden_status) {
81 return absl::OkStatus();
83 return absl::InvalidArgumentError(
84 absl::StrCat(
"expected problem_status.primal_status != ",
90 const ProblemStatusProto&
status,
91 const FeasibilityStatusProto forbidden_status) {
92 const FeasibilityStatusProto actual_status =
status.dual_status();
93 if (actual_status != forbidden_status) {
94 return absl::OkStatus();
96 return absl::InvalidArgumentError(
97 absl::StrCat(
"expected problem_status.dual_status != ",
103 const FeasibilityStatusProto required_status,
104 const bool primal_or_dual_infeasible_also_ok) {
105 const FeasibilityStatusProto actual_status =
status.dual_status();
106 if (actual_status == required_status) {
107 return absl::OkStatus();
109 if (primal_or_dual_infeasible_also_ok &&
status.primal_or_dual_infeasible()) {
112 return absl::OkStatus();
114 if (primal_or_dual_infeasible_also_ok) {
115 return absl::InvalidArgumentError(absl::StrCat(
116 "expected either problem_status.dual_status = ",
119 ") or problem_status.primal_or_dual_infeasible = true (and "
122 return absl::InvalidArgumentError(
123 absl::StrCat(
"expected problem_status.dual_status = ",
131 <<
"in primal_bound";
133 return absl::OkStatus();
137 if (!std::isfinite(bounds.primal_bound())) {
139 <<
"expected finite primal bound, but found "
140 << bounds.primal_bound();
142 return absl::OkStatus();
147absl::Status ValidateFiniteBoundImpliesFeasibleStatus(
148 const double first_bound,
const FeasibilityStatusProto first_status,
149 absl::string_view first_name) {
150 if (!std::isfinite(first_bound)) {
151 return absl::OkStatus();
153 if (first_status == FEASIBILITY_STATUS_FEASIBLE) {
154 return absl::OkStatus();
157 <<
"expected " << first_name
158 <<
" status = FEASIBILITY_STATUS_FEASIBLE for finite " << first_name
159 <<
" bound = " << first_bound <<
", but found " << first_name
163absl::Status ValidateNotUnboundedBoundImpliesNotUnboundedStatus(
164 const double first_bound,
const FeasibilityStatusProto first_status,
165 const FeasibilityStatusProto second_status, absl::string_view first_name,
166 absl::string_view second_name,
const double unbounded_bound) {
167 if (first_bound == unbounded_bound) {
168 return absl::OkStatus();
170 if (first_status != FEASIBILITY_STATUS_FEASIBLE ||
171 second_status != FEASIBILITY_STATUS_INFEASIBLE) {
172 return absl::OkStatus();
175 <<
"unexpected (" << first_name <<
" status, " << second_name
176 <<
" status) = (FEASIBILITY_STATUS_FEASIBLE, "
177 "FEASIBILITY_STATUS_INFEASIBLE) for not-unbounded "
178 << first_name <<
" bound = " << first_bound;
181absl::Status ValidateUnboundedBoundImpliesUnboundedStatus(
182 const double first_bound,
const double second_bound,
183 const FeasibilityStatusProto first_status,
184 const FeasibilityStatusProto second_status, absl::string_view first_name,
185 absl::string_view second_name,
const double unbounded_bound) {
186 if (first_bound != unbounded_bound) {
187 return absl::OkStatus();
189 if (first_status != FEASIBILITY_STATUS_FEASIBLE) {
191 <<
"expected " << first_name
192 <<
" status = FEASIBILITY_STATUS_FEASIBLE for unbounded "
193 << first_name <<
" bound = " << first_bound <<
", but found "
196 if (second_status != FEASIBILITY_STATUS_INFEASIBLE) {
198 <<
"expected " << second_name
199 <<
" status = FEASIBILITY_STATUS_INFEASIBLE for unbounded "
200 << first_name <<
" bound = " << first_bound <<
", but found "
203 if (second_bound != first_bound) {
205 <<
"expected " << second_name <<
" bound = " << first_name
206 <<
" bound for unbounded " << first_name
207 <<
" bound = " << first_bound <<
", but found " << second_name
208 <<
" bound = " << second_bound;
210 return absl::OkStatus();
216 const ObjectiveBoundsProto& objective_bounds,
217 const ProblemStatusProto&
status,
bool is_maximize) {
219 objective_bounds.primal_bound(),
220 objective_bounds.dual_bound(),
222 status.dual_status(),
"primal",
"dual",
224 <<
"for is_maximize = " << std::boolalpha << is_maximize;
226 objective_bounds.dual_bound(),
227 objective_bounds.primal_bound(),
229 status.primal_status(),
"dual",
"primal",
231 <<
"for is_maximize = " << std::boolalpha << is_maximize;
234 objective_bounds.primal_bound(),
235 status.primal_status(),
"primal"));
237 objective_bounds.dual_bound(),
238 status.dual_status(),
"dual"));
241 objective_bounds.primal_bound(),
243 status.dual_status(),
"primal",
"dual",
245 <<
"for is_maximize = " << std::boolalpha << is_maximize;
247 objective_bounds.dual_bound(),
249 status.primal_status(),
"dual",
"primal",
251 <<
"for is_maximize = " << std::boolalpha << is_maximize;
252 return absl::OkStatus();
#define RETURN_IF_ERROR(expr)
An object oriented wrapper for quadratic constraints in ModelStorage.
absl::Status ValidateFeasibilityStatus(const FeasibilityStatusProto &status)
absl::Status CheckDualStatusIsNot(const ProblemStatusProto &status, const FeasibilityStatusProto forbidden_status)
Assumes ValidateProblemStatus(status) is ok.
absl::Status CheckPrimalStatusIs(const ProblemStatusProto &status, const FeasibilityStatusProto required_status)
Assumes ValidateProblemStatus(status) is ok.
absl::Status ValidateProblemStatus(const ProblemStatusProto &status)
absl::Status CheckDualStatusIs(const ProblemStatusProto &status, const FeasibilityStatusProto required_status, const bool primal_or_dual_infeasible_also_ok)
Assumes ValidateProblemStatus(status) is ok.
absl::Status CheckScalar(const double value, const DoubleOptions &options)
Checks value is not NaN and satisfies the additional conditions in options.
absl::Status CheckFinitePrimalBound(const ObjectiveBoundsProto &bounds)
absl::Status ValidateObjectiveBounds(const ObjectiveBoundsProto &bounds)
absl::Status ValidateBoundStatusConsistency(const ObjectiveBoundsProto &objective_bounds, const ProblemStatusProto &status, bool is_maximize)
absl::Status CheckPrimalStatusIsNot(const ProblemStatusProto &status, const FeasibilityStatusProto forbidden_status)
Assumes ValidateProblemStatus(status) is ok.
std::string ProtoEnumToString(ProtoEnumType enum_value)
StatusBuilder InvalidArgumentErrorBuilder()