diff --git a/ext/or-tools/linear.cpp b/ext/or-tools/linear.cpp index f3fc8f6..fad1464 100644 --- a/ext/or-tools/linear.cpp +++ b/ext/or-tools/linear.cpp @@ -4,6 +4,7 @@ using operations_research::MPConstraint; using operations_research::MPObjective; +using operations_research::MPSolverParameters; using operations_research::MPSolver; using operations_research::MPVariable; @@ -56,8 +57,43 @@ void init_linear(Rice::Module& m) { .define_method("set_coefficient", &MPObjective::SetCoefficient) .define_method("set_offset", &MPObjective::SetOffset) .define_method("set_maximization", &MPObjective::SetMaximization) + .define_method("best_bound", &MPObjective::BestBound) .define_method("set_minimization", &MPObjective::SetMinimization); + Rice::define_class_under(m, "MPSolverParameters") + .define_constructor(Rice::Constructor()) + .define_method("reset", &MPSolverParameters::Reset) + .define_method( + "relative_mip_gap=", + [](MPSolverParameters& self, double relative_mip_gap) { + self.SetDoubleParam(MPSolverParameters::DoubleParam::RELATIVE_MIP_GAP, relative_mip_gap); + }) + .define_method( + "relative_mip_gap", + [](MPSolverParameters& self) { + return self.GetDoubleParam(MPSolverParameters::DoubleParam::RELATIVE_MIP_GAP); + }) + .define_method( + "primal_tolerance=", + [](MPSolverParameters& self, double primal_tolerance) { + self.SetDoubleParam(MPSolverParameters::DoubleParam::PRIMAL_TOLERANCE, primal_tolerance); + }) + .define_method( + "primal_tolerance", + [](MPSolverParameters& self) { + return self.GetDoubleParam(MPSolverParameters::DoubleParam::PRIMAL_TOLERANCE); + }) + .define_method( + "dual_tolerance=", + [](MPSolverParameters& self, double dual_tolerance) { + self.SetDoubleParam(MPSolverParameters::DoubleParam::DUAL_TOLERANCE, dual_tolerance); + }) + .define_method( + "dual_tolerance", + [](MPSolverParameters& self) { + return self.GetDoubleParam(MPSolverParameters::DoubleParam::DUAL_TOLERANCE); + }); + Rice::define_class_under(m, "Solver") .define_singleton_function( "_new", @@ -109,9 +145,9 @@ void init_linear(Rice::Module& m) { return self.MakeRowConstraint(lb, ub); }) .define_method( - "solve", - [](MPSolver& self) { - auto status = self.Solve(); + "_solve", + [](MPSolver& self, MPSolverParameters& params) { + auto status = self.Solve(params); if (status == MPSolver::ResultStatus::OPTIMAL) { return Symbol("optimal"); diff --git a/lib/or_tools/solver.rb b/lib/or_tools/solver.rb index 34bd7e3..f739e59 100644 --- a/lib/or_tools/solver.rb +++ b/lib/or_tools/solver.rb @@ -34,6 +34,14 @@ def minimize(expr) objective.set_minimization end + def solve + _solve(parameters) + end + + def parameters + @parameters ||= MPSolverParameters.new + end + private def set_objective(expr) diff --git a/test/linear_test.rb b/test/linear_test.rb index 350ef0b..4dd4ea9 100644 --- a/test/linear_test.rb +++ b/test/linear_test.rb @@ -96,4 +96,25 @@ def test_unrecognized_solver_type end assert_equal "Unrecognized solver type", error.message end + + def test_relative_mip_gap_parameter + params = ORTools::MPSolverParameters.new + + params.relative_mip_gap = 42 + assert_equal 42, params.relative_mip_gap + end + + def test_primal_tolerance_parameter + params = ORTools::MPSolverParameters.new + + params.primal_tolerance = 42 + assert_equal 42, params.primal_tolerance + end + + def test_dual_tolerance_parameter + params = ORTools::MPSolverParameters.new + + params.dual_tolerance = 42 + assert_equal 42, params.dual_tolerance + end end