26#include "absl/container/flat_hash_map.h"
27#include "absl/log/check.h"
28#include "absl/log/log.h"
29#include "absl/strings/str_cat.h"
30#include "absl/types/span.h"
31#include "gtest/gtest.h"
43using ::testing::AllOf;
44using ::testing::AllOfArray;
45using ::testing::AnyOf;
46using ::testing::AnyOfArray;
47using ::testing::Contains;
48using ::testing::DoubleNear;
50using ::testing::ExplainMatchResult;
51using ::testing::Field;
52using ::testing::IsEmpty;
53using ::testing::Matcher;
54using ::testing::MatcherInterface;
55using ::testing::MatchResultListener;
56using ::testing::Optional;
57using ::testing::PrintToString;
58using ::testing::Property;
70 explicit Printer(
const T& t) : value(t) {}
74 friend std::ostream&
operator<<(std::ostream& os,
const Printer& printer) {
75 os << PrintToString(printer.value);
81Printer<T> Print(
const T& t) {
89 <<
", objective_value: " << Print(primal_solution.objective_value)
90 <<
", feasibility_status: " << Print(primal_solution.feasibility_status)
94void PrintTo(
const DualSolution& dual_solution, std::ostream*
const os) {
95 *os <<
"{dual_values: " << Print(dual_solution.dual_values)
96 <<
", quadratic_dual_values: "
97 << Print(dual_solution.quadratic_dual_values)
98 <<
", reduced_costs: " << Print(dual_solution.reduced_costs)
99 <<
", objective_value: " << Print(dual_solution.objective_value)
100 <<
", feasibility_status: " << Print(dual_solution.feasibility_status)
104void PrintTo(
const PrimalRay& primal_ray, std::ostream*
const os) {
105 *os <<
"{variable_values: " << Print(primal_ray.variable_values) <<
"}";
108void PrintTo(
const DualRay& dual_ray, std::ostream*
const os) {
109 *os <<
"{dual_values: " << Print(dual_ray.dual_values)
110 <<
", reduced_costs: " << Print(dual_ray.reduced_costs) <<
"}";
113void PrintTo(
const Basis& basis, std::ostream*
const os) {
114 *os <<
"{variable_status: " << Print(basis.variable_status)
115 <<
", constraint_status: " << Print(basis.constraint_status)
116 <<
", basic_dual_feasibility: " << Print(basis.basic_dual_feasibility)
121 *os <<
"{primal_solution: " << Print(
solution.primal_solution)
122 <<
", dual_solution: " << Print(
solution.dual_solution)
123 <<
", basis: " << Print(
solution.basis) <<
"}";
126void PrintTo(
const SolveResult& result, std::ostream*
const os) {
127 *os <<
"{termination: " << Print(result.termination)
128 <<
", solve_stats: " << Print(result.solve_stats)
129 <<
", solutions: " << Print(result.solutions)
130 <<
", primal_rays: " << Print(result.primal_rays)
131 <<
", dual_rays: " << Print(result.dual_rays) <<
"}";
141class MapToDoubleMatcher
144 MapToDoubleMatcher(absl::flat_hash_map<K, double> expected,
145 const bool all_keys,
const double tolerance)
146 : expected_(std::move(expected)),
148 tolerance_(tolerance) {
149 for (
const auto [k, v] : expected_) {
150 CHECK(!std::isnan(v)) <<
"Illegal NaN for key: " << k;
154 bool MatchAndExplain(absl::flat_hash_map<K, double> actual,
155 MatchResultListener*
const os)
const override {
156 for (
const auto& [key, value] : expected_) {
157 if (!actual.contains(key)) {
158 *os <<
"expected key " << key <<
" not found";
161 if (!(std::abs(value - actual.at(key)) <= tolerance_)) {
162 *os <<
"value for key " << key
163 <<
" not within tolerance, expected: " << value
164 <<
" but found: " << actual.at(key);
169 if (all_keys_ && expected_.size() != actual.size()) {
170 for (
const auto& [key, value] : actual) {
171 if (!expected_.contains(key)) {
172 *os <<
"found unexpected key " << key <<
" in actual";
179 LOG(FATAL) <<
"unreachable";
184 void DescribeTo(std::ostream*
const os)
const override {
186 *os <<
"has identical keys to ";
188 *os <<
"keys are contained in ";
191 *os <<
" and values within " << tolerance_;
194 void DescribeNegationTo(std::ostream*
const os)
const override {
196 *os <<
"either keys differ from ";
198 *os <<
"either has a key not in ";
201 *os <<
" or a value differs by more than " << tolerance_;
205 const absl::flat_hash_map<K, double> expected_;
206 const bool all_keys_;
207 const double tolerance_;
214 return Matcher<VariableMap<double>>(
new MapToDoubleMatcher<Variable>(
215 std::move(expected),
false, tolerance));
219 const double tolerance) {
220 return Matcher<VariableMap<double>>(
new MapToDoubleMatcher<Variable>(
221 std::move(expected),
true, tolerance));
226 return Matcher<LinearConstraintMap<double>>(
227 new MapToDoubleMatcher<LinearConstraint>(std::move(expected),
231Matcher<LinearConstraintMap<double>>
IsNear(
233 return Matcher<LinearConstraintMap<double>>(
234 new MapToDoubleMatcher<LinearConstraint>(std::move(expected),
238Matcher<absl::flat_hash_map<QuadraticConstraint, double>>
IsNear(
239 absl::flat_hash_map<QuadraticConstraint, double> expected,
240 const double tolerance) {
241 return Matcher<absl::flat_hash_map<QuadraticConstraint, double>>(
242 new MapToDoubleMatcher<QuadraticConstraint>(
243 std::move(expected),
true, tolerance));
247 absl::flat_hash_map<QuadraticConstraint, double> expected,
249 return Matcher<absl::flat_hash_map<QuadraticConstraint, double>>(
250 new MapToDoubleMatcher<QuadraticConstraint>(std::move(expected),
256Matcher<absl::flat_hash_map<K, double>>
IsNear(
257 absl::flat_hash_map<K, double> expected,
const double tolerance) {
258 return Matcher<absl::flat_hash_map<K, double>>(
new MapToDoubleMatcher<K>(
259 std::move(expected),
true, tolerance));
264 absl::flat_hash_map<K, double> expected,
const double tolerance) {
265 return Matcher<absl::flat_hash_map<K, double>>(
new MapToDoubleMatcher<K>(
266 std::move(expected),
false, tolerance));
273testing::Matcher<LinearExpression>
IsIdentical(LinearExpression expected) {
278 const LinearExpression expected,
const double tolerance) {
279 CHECK(!std::isnan(expected.offset())) <<
"Illegal NaN-valued offset";
283 testing::DoubleNear(expected.offset(), tolerance)),
285 IsNear(expected.terms(), tolerance)));
289testing::Matcher<BoundedLinearExpression> IsNearForSign(
290 const BoundedLinearExpression& expected,
const double tolerance) {
291 return AllOf(Property(
"upper_bound_minus_offset",
293 testing::DoubleNear(expected.upper_bound_minus_offset(),
295 Property(
"lower_bound_minus_offset",
297 testing::DoubleNear(expected.lower_bound_minus_offset(),
301 IsNear(expected.expression.terms(), tolerance))));
308 -expected.expression, -expected.upper_bound,
309 -expected.lower_bound);
310 return AnyOf(IsNearForSign(expected, tolerance),
311 IsNearForSign(expected_negation, tolerance));
315 QuadraticExpression expected) {
316 CHECK(!std::isnan(expected.offset())) <<
"Illegal NaN-valued offset";
319 Eq(expected.storage())),
321 testing::Eq(expected.offset())),
323 IsNear(expected.linear_terms(), 0)),
325 IsNear(expected.quadratic_terms(), 0)));
334template <
typename RayType>
337 RayMatcher(RayType expected,
const double tolerance)
338 : expected_(
std::move(expected)), tolerance_(tolerance) {}
339 void DescribeTo(std::ostream* os)
const final {
340 *os <<
"after L_inf normalization, is within tolerance: " << tolerance_
344 void DescribeNegationTo(std::ostream*
const os)
const final {
345 *os <<
"after L_inf normalization, is not within tolerance: " << tolerance_
351 const RayType expected_;
352 const double tolerance_;
356Matcher<double>
IsNear(
double expected,
const double tolerance) {
357 return DoubleNear(expected, tolerance);
360template <
typename Type>
361Matcher<std::optional<Type>>
IsNear(std::optional<Type> expected,
362 const double tolerance) {
363 if (expected.has_value()) {
364 return Optional(
IsNear(*expected, tolerance));
366 return testing::Eq(std::nullopt);
369template <
typename Type>
370Matcher<std::optional<Type>>
IsNear(std::optional<Type> expected,
371 const double tolerance,
372 const bool allow_undetermined) {
373 if (expected.has_value()) {
374 return Optional(
IsNear(*expected, tolerance, allow_undetermined));
376 return testing::Eq(std::nullopt);
380Matcher<std::optional<Basis>>
BasisIs(
const std::optional<Basis>& expected) {
381 if (expected.has_value()) {
382 return Optional(
BasisIs(*expected));
384 return testing::Eq(std::nullopt);
387testing::Matcher<std::vector<Solution>>
IsNear(
388 absl::Span<const Solution> expected_solutions,
390 if (expected_solutions.empty()) {
393 std::vector<Matcher<Solution>> matchers;
394 for (
const Solution& sol : expected_solutions) {
395 matchers.push_back(
IsNear(sol, options));
397 return ::testing::ElementsAreArray(matchers);
407 const bool allow_undetermined) {
408 if (allow_undetermined) {
415 const bool allow_undetermined) {
418 IsNear(expected.variable_values, tolerance)),
420 IsNear(expected.objective_value, tolerance)),
426 const bool allow_undetermined) {
440Matcher<Basis>
BasisIs(
const Basis& expected) {
442 expected.variable_status),
444 expected.constraint_status),
446 expected.basic_dual_feasibility));
449Matcher<Solution>
IsNear(Solution expected,
451 std::vector<Matcher<Solution>> to_check;
466 return AllOfArray(to_check);
476double InfinityNorm(
const absl::flat_hash_map<K, double>& vector) {
477 double infinity_norm = 0.0;
478 for (
auto [
id, value] : vector) {
479 infinity_norm = std::max(infinity_norm, std::abs(value));
481 return infinity_norm;
494 for (
auto& entry : ray.variable_values) {
495 entry.second /= norm;
501class PrimalRayMatcher :
public RayMatcher<PrimalRay> {
503 PrimalRayMatcher(PrimalRay expected,
const double tolerance)
504 : RayMatcher(std::move(expected), tolerance) {}
506 bool MatchAndExplain(PrimalRay actual,
507 MatchResultListener*
const os)
const override {
508 auto normalized_actual = NormalizePrimalRay(actual);
509 auto normalized_expected = NormalizePrimalRay(expected_);
510 if (os->IsInterested()) {
511 *os <<
"actual normalized: " << PrintToString(normalized_actual)
512 <<
", expected normalized: " << PrintToString(normalized_expected);
514 return ExplainMatchResult(
515 IsNear(normalized_expected.variable_values, tolerance_),
516 normalized_actual.variable_values, os);
523 return Matcher<PrimalRay>(
524 new PrimalRayMatcher(std::move(expected), tolerance));
528 const double tolerance) {
531 return IsNear(expected, tolerance);
552 entry.second /= norm;
555 entry.second /= norm;
561class DualRayMatcher :
public RayMatcher<DualRay> {
563 DualRayMatcher(DualRay expected,
const double tolerance)
564 : RayMatcher(
std::move(expected), tolerance) {}
566 bool MatchAndExplain(DualRay actual, MatchResultListener* os)
const override {
567 auto normalized_actual = NormalizeDualRay(actual);
568 auto normalized_expected = NormalizeDualRay(expected_);
569 if (os->IsInterested()) {
570 *os <<
"actual normalized: " << PrintToString(normalized_actual)
571 <<
", expected normalized: " << PrintToString(normalized_expected);
573 return ExplainMatchResult(
574 IsNear(normalized_expected.dual_values, tolerance_),
575 normalized_actual.dual_values, os) &&
577 IsNear(normalized_expected.reduced_costs, tolerance_),
578 normalized_actual.reduced_costs, os);
584Matcher<DualRay>
IsNear(
DualRay expected,
const double tolerance) {
585 return Matcher<DualRay>(
new DualRayMatcher(std::move(expected), tolerance));
593 const double tolerance) {
595 DoubleNear(expected.primal_bound, tolerance)),
597 DoubleNear(expected.dual_bound, tolerance)));
601 const std::vector<TerminationReason>& allowed) {
602 return Field(
"termination", &SolveResult::termination,
607 return Field(
"termination", &SolveResult::termination,
620testing::Matcher<SolveResult> TerminationLimitIs(
621 const Limit expected,
const bool allow_limit_undetermined) {
622 if (allow_limit_undetermined) {
623 return Field(
"termination", &SolveResult::termination,
627 return Field(
"termination", &SolveResult::termination,
634 const Limit expected,
const bool allow_limit_undetermined) {
635 std::vector<Matcher<SolveResult>> matchers;
636 matchers.push_back(TerminationLimitIs(expected, allow_limit_undetermined));
639 return AllOfArray(matchers);
643 const Limit expected,
const bool allow_limit_undetermined) {
644 std::vector<Matcher<SolveResult>> matchers;
645 matchers.push_back(TerminationLimitIs(expected, allow_limit_undetermined));
647 return AllOfArray(matchers);
651 const Limit expected,
const bool allow_limit_undetermined) {
652 std::vector<Matcher<SolveResult>> matchers;
653 matchers.push_back(TerminationLimitIs(expected, allow_limit_undetermined));
655 return AllOfArray(matchers);
658template <
typename MatcherType>
660 std::ostringstream os;
662 matcher.DescribeNegationTo(&os);
664 matcher.DescribeTo(&os);
679std::string
MatcherToString(const ::testing::PolymorphicMatcher<T>& matcher,
684MATCHER_P(FirstElementIs, first_element_matcher,
686 ? absl::StrCat(
"is empty or first element ",
688 : absl::StrCat(
"has at least one element and first element ",
690 return ExplainMatchResult(UnorderedElementsAre(first_element_matcher),
691 absl::MakeSpan(arg).subspan(0, 1), result_listener);
695 const Matcher<std::string> detail_matcher) {
716 Field(
"primal_or_dual_infeasible",
727 .primal_or_dual_infeasible =
false})));
731 const double primal_objective_value,
732 const std::optional<double> dual_objective_value,
const double tolerance) {
737 .dual_bound = dual_objective_value.value_or(
738 primal_objective_value)},
748 const std::optional<double> expected_primal_objective,
749 const double tolerance) {
750 if (expected_primal_objective.has_value()) {
753 Property(
"has_primal_feasible_solution",
754 &SolveResult::has_primal_feasible_solution,
true),
755 Property(
"objective_value", &SolveResult::objective_value,
756 DoubleNear(*expected_primal_objective, tolerance)));
758 return Field(
"termination", &SolveResult::termination,
763 const double expected_objective,
765 const double tolerance) {
767 IsOptimal(std::make_optional(expected_objective), tolerance),
770 .objective_value = expected_objective,
776 const double expected_objective,
780 IsOptimal(std::make_optional(expected_objective), tolerance),
783 .dual_values = expected_dual_values,
784 .reduced_costs = expected_reduced_costs,
785 .objective_value = std::make_optional(expected_objective),
791 const double expected_objective,
793 const absl::flat_hash_map<QuadraticConstraint, double>
794 expected_quadratic_dual_values,
797 IsOptimal(std::make_optional(expected_objective), tolerance),
800 .dual_values = expected_dual_values,
801 .quadratic_dual_values = expected_quadratic_dual_values,
802 .reduced_costs = expected_reduced_costs,
803 .objective_value = std::make_optional(expected_objective),
808Matcher<SolveResult>
HasSolution(PrimalSolution expected,
809 const double tolerance) {
811 "solutions", &SolveResult::solutions,
813 Optional(
IsNear(std::move(expected), tolerance)))));
817 const double tolerance) {
819 "solutions", &SolveResult::solutions,
821 Optional(
IsNear(std::move(expected), tolerance)))));
825 return Field(
"primal_rays", &SolveResult::primal_rays,
826 Contains(
IsNear(std::move(expected), tolerance)));
830 const double tolerance) {
832 ray.variable_values = std::move(expected_vars);
836Matcher<SolveResult>
HasDualRay(DualRay expected,
const double tolerance) {
837 return Field(
"dual_rays", &SolveResult::dual_rays,
838 Contains(
IsNear(std::move(expected), tolerance)));
854std::vector<TerminationReason> CompatibleReasons(
856 if (!inf_or_unb_soft_match) {
874Matcher<std::vector<Solution>> CheckSolutions(
875 absl::Span<const Solution> expected_solutions,
877 if (options.first_solution_only && !expected_solutions.empty()) {
878 return FirstElementIs(
879 IsNear(expected_solutions[0],
881 .check_primal =
true,
882 .check_dual = options.check_dual,
883 .check_basis = options.check_basis}));
885 return IsNear(expected_solutions,
887 .check_primal =
true,
888 .check_dual = options.check_dual,
889 .check_basis = options.check_basis});
892template <
typename RayType>
893Matcher<std::vector<RayType>> AnyRayNear(
894 const std::vector<RayType>& expected_rays,
const double tolerance) {
895 std::vector<Matcher<RayType>> matchers;
896 for (
const RayType& ray : expected_rays) {
897 matchers.push_back(
IsNear(ray, tolerance));
899 return Contains(AnyOfArray(matchers));
902template <
typename RayType>
903Matcher<std::vector<RayType>> AllRaysNear(
904 const std::vector<RayType>& expected_rays,
const double tolerance) {
905 std::vector<Matcher<RayType>> matchers;
906 for (
const RayType& ray : expected_rays) {
907 matchers.push_back(
IsNear(ray, tolerance));
909 return ::testing::UnorderedElementsAreArray(matchers);
912template <
typename RayType>
913Matcher<std::vector<RayType>> CheckRays(
914 const std::vector<RayType>& expected_rays,
const double tolerance,
916 if (expected_rays.empty()) {
920 return AllRaysNear(expected_rays, tolerance);
922 return AnyRayNear(expected_rays, tolerance);
929 std::vector<Matcher<SolveResult>> to_check;
931 expected.termination.reason, options.inf_or_unb_soft_match)));
932 const bool skip_solution =
933 MightTerminateWithRays(expected.termination.reason) &&
934 !options.check_solutions_if_inf_or_unbounded;
935 if (!skip_solution) {
936 to_check.push_back(Field(
"solutions", &SolveResult::solutions,
937 CheckSolutions(expected.solutions, options)));
939 if (options.check_rays) {
940 to_check.push_back(Field(
"primal_rays", &SolveResult::primal_rays,
941 CheckRays(expected.primal_rays, options.tolerance,
942 !options.first_solution_only)));
943 to_check.push_back(Field(
"dual_rays", &SolveResult::dual_rays,
944 CheckRays(expected.dual_rays, options.tolerance,
945 !options.first_solution_only)));
948 return AllOfArray(to_check);
955testing::Matcher<ComputeInfeasibleSubsystemResult>
IsFeasible() {
959 Field(
"infeasible_subsystem",
966testing::Matcher<ComputeInfeasibleSubsystemResult>
IsUndetermined() {
970 Field(
"infeasible_subsystem",
977testing::Matcher<ComputeInfeasibleSubsystemResult>
IsInfeasible(
978 const std::optional<bool> expected_is_minimal,
979 const std::optional<ModelSubset> expected_infeasible_subsystem) {
980 std::vector<Matcher<ComputeInfeasibleSubsystemResult>> matchers;
981 matchers.push_back(Field(
"feasibility",
985 Field(
"infeasible_subsystem",
988 if (expected_is_minimal.has_value()) {
989 matchers.push_back(Field(
"is_minimal",
991 Eq(expected_is_minimal.value())));
993 if (expected_infeasible_subsystem.has_value()) {
995 Field(
"infeasible_subsystem",
999 expected_infeasible_subsystem.value().Proto()))));
1001 return AllOfArray(matchers);
const VariableMap< double > & terms() const
Returns the terms in this expression.
NullableModelStorageCPtr storage() const
const QuadraticTermMap< double > & quadratic_terms() const
const VariableMap< double > & linear_terms() const
Fractional InfinityNorm(const DenseColumn &v)
Returns the maximum of the coefficients of 'v'.
An object oriented wrapper for quadratic constraints in ModelStorage.
Matcher< SolveResult > IsOptimalWithSolution(const double expected_objective, const VariableMap< double > expected_variable_values, const double tolerance)
Matcher< SolveResult > HasPrimalRay(PrimalRay expected, const double tolerance)
Matcher< Termination > TerminationIsOptimal()
absl::flat_hash_map< Variable, V > VariableMap
Matcher< Termination > ReasonIsOptimal()
Matcher< ObjectiveBounds > ObjectiveBoundsNear(const ObjectiveBounds &expected, const double tolerance)
Matcher< SolutionStatus > SolutionStatusIs(const SolutionStatus expected, const bool allow_undetermined)
TerminationReason
The reason a call to Solve() terminates.
@ kOptimal
A provably optimal solution (up to numerical tolerances) has been found.
@ kInfeasible
The primal problem has no feasible solutions.
absl::flat_hash_map< LinearConstraint, V > LinearConstraintMap
Matcher< Termination > ReasonIs(TerminationReason reason)
Matcher< SolveResult > TerminatesWithOneOf(const std::vector< TerminationReason > &allowed)
Checks that the result has one of the allowed termination reasons.
Matcher< ProblemStatus > ProblemStatusIs(const ProblemStatus &expected)
testing::Matcher< ComputeInfeasibleSubsystemResult > IsInfeasible(const std::optional< bool > expected_is_minimal, const std::optional< ModelSubset > expected_infeasible_subsystem)
Matcher< Termination > LimitIs(math_opt::Limit limit, const Matcher< std::string > detail_matcher)
testing::Matcher< BoundedLinearExpression > IsNearlyEquivalent(const BoundedLinearExpression &expected, const double tolerance)
Matcher< SolveResult > IsConsistentWith(const SolveResult &expected, const SolveResultMatcherOptions &options)
Matcher< Termination > TerminationIsIgnoreDetail(const Termination &expected)
Matcher< SolveResult > HasSolution(PrimalSolution expected, const double tolerance)
SolveResult has a primal solution matching expected within tolerance.
SolutionStatus
Feasibility of a primal or dual solution as claimed by the solver.
@ kUndetermined
Solver does not claim a feasibility status.
@ kFeasible
Solver claims the solution is feasible.
Matcher< SolveResult > HasDualRay(DualRay expected, const double tolerance)
testing::Matcher< SolveResult > TerminatesWithReasonFeasible(const Limit expected, const bool allow_limit_undetermined)
Matcher< SolveResult > TerminatesWith(const TerminationReason expected)
std::string MatcherToString(const Matcher< T > &matcher, bool negate)
testing::Matcher< SolveResult > TerminatesWithLimit(const Limit expected, const bool allow_limit_undetermined)
Matcher< PrimalRay > PrimalRayIsNear(VariableMap< double > expected_var_values, const double tolerance)
std::string MatcherToStringImpl(const MatcherType &matcher, const bool negate)
std::ostream & operator<<(std::ostream &ostr, const SecondOrderConeConstraint &constraint)
testing::Matcher< LinearExpression > IsIdentical(LinearExpression expected)
Matcher< VariableMap< double > > IsNear(VariableMap< double > expected, const double tolerance)
Matcher< VariableMap< double > > IsNearlySubsetOf(VariableMap< double > expected, double tolerance)
Matcher< UpdateResult > DidUpdate()
Actual UpdateResult.did_update is true.
void PrintTo(const PrimalSolution &primal_solution, std::ostream *const os)
MATCHER_P(FirstElementIs, first_element_matcher,(negation ? absl::StrCat("is empty or first element ", MatcherToString(first_element_matcher, true)) :absl::StrCat("has at least one element and first element ", MatcherToString(first_element_matcher, false))))
testing::Matcher< LinearExpression > LinearExpressionIsNear(const LinearExpression expected, const double tolerance)
Matcher< SolveResult > IsOptimalWithDualSolution(const double expected_objective, const LinearConstraintMap< double > expected_dual_values, const VariableMap< double > expected_reduced_costs, const double tolerance)
Matcher< SolveResult > HasDualSolution(DualSolution expected, const double tolerance)
Matcher< Basis > BasisIs(const Basis &expected)
testing::Matcher< ComputeInfeasibleSubsystemResult > IsFeasible()
testing::Matcher< ComputeInfeasibleSubsystemResult > IsUndetermined()
Matcher< SolveResult > IsOptimal(const std::optional< double > expected_primal_objective, const double tolerance)
@ kUndetermined
Solver does not claim a status.
@ kFeasible
Solver claims the problem is feasible.
@ kInfeasible
Solver claims the problem is infeasible.
testing::Matcher< SolveResult > TerminatesWithReasonNoSolutionFound(const Limit expected, const bool allow_limit_undetermined)
dual_gradient T(y - `dual_solution`) class DiagonalTrustRegionProblemFromQp
In SWIG mode, we don't want anything besides these top-level includes.
Select next search node to expand Select next item_i to add this new search node to the search Generate a new search node where item_i is not in the knapsack Check validity of this new partial solution(using propagators) - If valid
internal::ProtoMatcher EqualsProto(const ::google::protobuf::Message &message)
LinearConstraintMap< BasisStatus > constraint_status
VariableMap< BasisStatus > variable_status
std::optional< SolutionStatus > basic_dual_feasibility
A LinearExpression with upper and lower bounds.
double upper_bound_minus_offset() const
LinearExpression expression
double lower_bound_minus_offset() const
ModelSubset infeasible_subsystem
FeasibilityStatus feasibility
The primal feasibility status of the model, as determined by the solver.
LinearConstraintMap< double > dual_values
VariableMap< double > reduced_costs
LinearConstraintMap< double > dual_values
absl::flat_hash_map< QuadraticConstraint, double > quadratic_dual_values
std::optional< double > objective_value
SolutionStatus feasibility_status
VariableMap< double > reduced_costs
bool empty() const
True if this object corresponds to the empty subset.
ModelSubsetProto Proto() const
Bounds on the optimal objective value.
VariableMap< double > variable_values
SolutionStatus feasibility_status
VariableMap< double > variable_values
FeasibilityStatus primal_status
Status for the primal problem.
bool primal_or_dual_infeasible
FeasibilityStatus dual_status
Status for the dual problem (or for the dual of a continuous relaxation).
Options for IsNear(Solution).
std::optional< Basis > basis
std::optional< PrimalSolution > primal_solution
std::optional< DualSolution > dual_solution
Configures SolveResult matcher IsConsistentWith() below.
ProblemStatus problem_status
Feasibility statuses for primal and dual problems.
std::optional< Limit > limit
ObjectiveBounds objective_bounds
Bounds on the optimal objective value.