From ae39ac30330869f37defd229752e46c49e3be8e9 Mon Sep 17 00:00:00 2001 From: Mikael Zayenz Lagerkvist Date: Fri, 10 Jul 2026 16:04:56 +0200 Subject: [PATCH] branch: honor filter in random tie selection --- gecode/kernel/branch/view-sel.hpp | 4 +- test/branch/int.cpp | 97 ++++++++++++++++++++++++++++++- 2 files changed, 98 insertions(+), 3 deletions(-) diff --git a/gecode/kernel/branch/view-sel.hpp b/gecode/kernel/branch/view-sel.hpp index 32c7d68358..cab0b69033 100644 --- a/gecode/kernel/branch/view-sel.hpp +++ b/gecode/kernel/branch/view-sel.hpp @@ -520,8 +520,8 @@ namespace Gecode { void ViewSelRnd::ties(Space& home, ViewArray& x, int s, int* ties, int& n, - BrancherFilter&) { - n=1; ties[0] = select(home,x,s); + BrancherFilter& f) { + n=1; ties[0] = select(home,x,s,f); } template void diff --git a/test/branch/int.cpp b/test/branch/int.cpp index c8947973f0..33837242ec 100644 --- a/test/branch/int.cpp +++ b/test/branch/int.cpp @@ -33,8 +33,104 @@ #include "test/branch.hh" +#include +#include + namespace Test { namespace Branch { + /// Space for testing filtered random tie selection + class FilteredRndTiesSpace : public Gecode::Space { + public: + /// Variables to branch on + Gecode::IntVarArray x; + + /// Initialize space + FilteredRndTiesSpace(Gecode::Rnd r) + : x(*this, 4, 0, 1) { + Gecode::IntVarArgs xa(x); + Gecode::ViewArray xv(*this, xa); + Gecode::ViewSel* vs[2] = { + Gecode::Int::Branch::viewsel(*this, Gecode::INT_VAR_RND(r)), + Gecode::Int::Branch::viewsel(*this, Gecode::INT_VAR_SIZE_MIN()) + }; + // Post directly so the random selector remains first in the tie chain. + Gecode::postviewvalbrancher( + *this, xv, vs, + Gecode::Int::Branch::valselcommit(*this, Gecode::INT_VAL_MIN()), + [](const Gecode::Space&, Gecode::IntVar, int i) { + return (i == 0) || (i == 2); + }, nullptr); + } + + /// Constructor for cloning + FilteredRndTiesSpace(FilteredRndTiesSpace& s) + : Gecode::Space(s) { + x.update(*this, s.x); + } + + /// Copy space during cloning + virtual Gecode::Space* copy(void) { + return new FilteredRndTiesSpace(*this); + } + }; + + /// Test filtered random tie selection with accepted and rejected views + class FilteredRndTies : public Base { + public: + /// Create and register test + FilteredRndTies(void) + : Base("Int::Branch::FilteredRndTies") {} + + /// Run test + virtual bool run(void) { + bool selected[2] = {false, false}; + + for (unsigned int seed = 1; seed <= 16; seed++) { + FilteredRndTiesSpace* probe = + new FilteredRndTiesSpace(Gecode::Rnd(seed)); + if (probe->status() != Gecode::SS_BRANCH) { + delete probe; + return false; + } + const Gecode::Choice* c = probe->choice(); + const Gecode::PosChoice& pc + = static_cast(*c); + const int p = pc.pos().pos; + delete c; + delete probe; + if ((p != 0) && (p != 2)) + return false; + selected[p == 2] = true; + + FilteredRndTiesSpace* root = + new FilteredRndTiesSpace(Gecode::Rnd(seed)); + Gecode::Search::Options o; + o.c_d = 2; + o.a_d = 1; + Gecode::DFS e(root, o); + delete root; + + int n = 0; + while (Gecode::Space* s = e.next()) { + FilteredRndTiesSpace* solution = + static_cast(s); + if (solution->x[1].assigned() || solution->x[3].assigned()) { + delete solution; + return false; + } + delete solution; + n++; + } + if (n != 4) + return false; + } + + return selected[0] && selected[1]; + } + }; + + FilteredRndTies filtered_rnd_ties; + /// %Test brancher with distinct propagator class Int : public IntTest { public: @@ -63,4 +159,3 @@ namespace Test { namespace Branch { }} // STATISTICS: test-branch -