diff --git a/ext/or-tools/constraint.cpp b/ext/or-tools/constraint.cpp index 7b7cfe8..e4a0a00 100644 --- a/ext/or-tools/constraint.cpp +++ b/ext/or-tools/constraint.cpp @@ -765,6 +765,16 @@ void init_constraint(Rice::Module& m) { [](CpModelBuilder& self, const std::vector& literals) { return self.AddBoolXor(literals); }) + .define_method( + "add_at_most_one", + [](CpModelBuilder& self, const std::vector& literals) { + return self.AddAtMostOne(literals); + }) + .define_method( + "add_exactly_one", + [](CpModelBuilder& self, const std::vector& literals) { + return self.AddExactlyOne(literals); + }) .define_method( "add_implication", [](CpModelBuilder& self, const BoolVar& a, const BoolVar& b) { diff --git a/test/constraint_test.rb b/test/constraint_test.rb index b84aad0..2f026bf 100644 --- a/test/constraint_test.rb +++ b/test/constraint_test.rb @@ -305,6 +305,48 @@ def test_sum_empty_false assert_equal expected, model.inspect end + def test_add_at_most_one + model = ORTools::CpModel.new + x = model.new_bool_var("x") + y = model.new_bool_var("y") + z = model.new_bool_var("z") + model.add_at_most_one([x, y, z]) + model.maximize(model.sum([x, y, z])) + + solver = ORTools::CpSolver.new + assert_equal :optimal, solver.solve(model) + assert_equal 1, solver.objective_value + assert_equal 1, [x, y, z].count { |v| solver.value(v) } + end + + def test_add_exactly_one + model = ORTools::CpModel.new + x = model.new_bool_var("x") + y = model.new_bool_var("y") + z = model.new_bool_var("z") + model.add_exactly_one([x, y, z]) + model.minimize(model.sum([x, y, z])) + + solver = ORTools::CpSolver.new + assert_equal :optimal, solver.solve(model) + assert_equal 1, solver.objective_value + assert_equal 1, [x, y, z].count { |v| solver.value(v) } + end + + def test_add_at_most_one_enforced + model = ORTools::CpModel.new + x = model.new_bool_var("x") + y = model.new_bool_var("y") + guard = model.new_bool_var("guard") + model.add_at_most_one([x, y]).only_enforce_if(guard) + model.add(guard == 1) + model.maximize(model.sum([x, y])) + + solver = ORTools::CpSolver.new + assert_equal :optimal, solver.solve(model) + assert_equal 1, solver.objective_value + end + def test_add_not_supported model = ORTools::CpModel.new error = assert_raises(TypeError) do