Skip to content

Commit

Permalink
Added termination method to MathOpt
Browse files Browse the repository at this point in the history
  • Loading branch information
ankane committed Oct 6, 2024
1 parent c65a922 commit e39e621
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 2 deletions.
38 changes: 37 additions & 1 deletion ext/or-tools/math_opt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ using operations_research::math_opt::Solve;
using operations_research::math_opt::SolveArguments;
using operations_research::math_opt::SolveResult;
using operations_research::math_opt::SolverType;
using operations_research::math_opt::Termination;
using operations_research::math_opt::TerminationReason;
using operations_research::math_opt::Variable;

namespace Rice::detail
Expand Down Expand Up @@ -54,7 +56,41 @@ void init_math_opt(Rice::Module& m) {

Rice::define_class_under<LinearConstraint>(mathopt, "LinearConstraint");

Rice::define_class_under<Termination>(mathopt, "Termination")
.define_method(
"reason",
[](Termination& self) {
auto reason = self.reason;

if (reason == TerminationReason::kOptimal) {
return Rice::Symbol("optimal");
} else if (reason == TerminationReason::kInfeasible) {
return Rice::Symbol("infeasible");
} else if (reason == TerminationReason::kUnbounded) {
return Rice::Symbol("unbounded");
} else if (reason == TerminationReason::kInfeasibleOrUnbounded) {
return Rice::Symbol("infeasible_or_unbounded");
} else if (reason == TerminationReason::kImprecise) {
return Rice::Symbol("imprecise");
} else if (reason == TerminationReason::kFeasible) {
return Rice::Symbol("feasible");
} else if (reason == TerminationReason::kNoSolutionFound) {
return Rice::Symbol("no_solution_found");
} else if (reason == TerminationReason::kNumericalError) {
return Rice::Symbol("numerical_error");
} else if (reason == TerminationReason::kOtherError) {
return Rice::Symbol("other");
} else {
throw std::runtime_error("Unknown termination reason");
}
});

Rice::define_class_under<SolveResult>(mathopt, "SolveResult")
.define_method(
"termination",
[](SolveResult& self) {
return self.termination;
})
.define_method(
"objective_value",
[](SolveResult& self) {
Expand Down Expand Up @@ -119,7 +155,7 @@ void init_math_opt(Rice::Module& m) {
auto result = Solve(self, solver_type, args);

if (!result.ok()) {
throw std::runtime_error(std::string{result.status().message()});
throw std::invalid_argument(std::string{result.status().message()});
}

return *result;
Expand Down
3 changes: 2 additions & 1 deletion test/math_opt_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ def test_basic
model.maximize(x + 2 * y)

result = model.solve
assert_equal :optimal, result.termination.reason

puts "Objective value: #{result.objective_value}"
puts "x: #{result.variable_values[x]}"
Expand Down Expand Up @@ -68,7 +69,7 @@ def test_non_integer_solver
model = ORTools::MathOpt::Model.new("getting_started_lp")
model.add_integer_variable(-1.0, 1.5, "x")

error = assert_raises do
error = assert_raises(ArgumentError) do
model.solve(:glop)
end
assert_equal "Glop does not support integer variables", error.message
Expand Down

0 comments on commit e39e621

Please sign in to comment.