Skip to content

Commit d66ecb6

Browse files
fix: alternating brancher did not call the methods correctly (#128)
The `AlternatingBrancher` did not call the correct methods on the default brancher meaning that the solver had poor performance during free search (since it did not restore any keys to the heap upon backtracking). This has been fixed by performing the right calls
1 parent e587458 commit d66ecb6

File tree

2 files changed

+41
-13
lines changed

2 files changed

+41
-13
lines changed

pumpkin-solver/src/branching/branchers/alternating_brancher.rs

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,19 @@ impl<OtherBrancher: Brancher> AlternatingBrancher<OtherBrancher> {
7878
fn toggle_brancher(&mut self) {
7979
self.is_using_default_brancher = !self.is_using_default_brancher
8080
}
81+
82+
/// Returns true if only the default strategy is used from now on and false otherwise.
83+
///
84+
/// This is important if [`AlternatingStrategy::SwitchToDefaultAfterFirstSolution`] is used as
85+
/// the strategy.
86+
fn will_always_use_default(&self) -> bool {
87+
match self.strategy {
88+
AlternatingStrategy::SwitchToDefaultAfterFirstSolution => {
89+
self.is_using_default_brancher
90+
}
91+
_ => false,
92+
}
93+
}
8194
}
8295

8396
impl<OtherBrancher: Brancher> Brancher for AlternatingBrancher<OtherBrancher> {
@@ -97,13 +110,19 @@ impl<OtherBrancher: Brancher> Brancher for AlternatingBrancher<OtherBrancher> {
97110
}
98111

99112
fn on_appearance_in_conflict_predicate(&mut self, predicate: Predicate) {
100-
self.other_brancher
101-
.on_appearance_in_conflict_predicate(predicate)
113+
self.default_brancher
114+
.on_appearance_in_conflict_predicate(predicate);
115+
if !self.will_always_use_default() {
116+
self.other_brancher
117+
.on_appearance_in_conflict_predicate(predicate)
118+
}
102119
}
103120

104121
fn on_conflict(&mut self) {
105-
self.other_brancher.on_conflict();
106-
self.default_brancher.on_conflict()
122+
self.default_brancher.on_conflict();
123+
if !self.will_always_use_default() {
124+
self.other_brancher.on_conflict();
125+
}
107126
}
108127

109128
fn on_solution(&mut self, solution: SolutionReference) {
@@ -120,8 +139,8 @@ impl<OtherBrancher: Brancher> Brancher for AlternatingBrancher<OtherBrancher> {
120139
}
121140
}
122141
AlternatingStrategy::SwitchToDefaultAfterFirstSolution => {
123-
// Switch only the first time, not that `even_number_of_solutions` is initialised to
124-
// true
142+
// Switch only the first time, note that `even_number_of_solutions` is initialised
143+
// to true
125144
if self.even_number_of_solutions {
126145
self.even_number_of_solutions = false;
127146
self.is_using_default_brancher = true;
@@ -130,12 +149,17 @@ impl<OtherBrancher: Brancher> Brancher for AlternatingBrancher<OtherBrancher> {
130149
_ => {}
131150
}
132151

133-
self.other_brancher.on_solution(solution);
134-
self.default_brancher.on_solution(solution)
152+
self.default_brancher.on_solution(solution);
153+
if !self.will_always_use_default() {
154+
self.other_brancher.on_solution(solution);
155+
}
135156
}
136157

137158
fn on_unassign_integer(&mut self, variable: DomainId, value: i32) {
138-
self.other_brancher.on_unassign_integer(variable, value)
159+
self.default_brancher.on_unassign_integer(variable, value);
160+
if !self.will_always_use_default() {
161+
self.other_brancher.on_unassign_integer(variable, value)
162+
}
139163
}
140164

141165
fn on_restart(&mut self) {
@@ -173,12 +197,16 @@ impl<OtherBrancher: Brancher> Brancher for AlternatingBrancher<OtherBrancher> {
173197

174198
fn on_backtrack(&mut self) {
175199
self.default_brancher.on_backtrack();
176-
self.other_brancher.on_backtrack();
200+
if !self.will_always_use_default() {
201+
self.other_brancher.on_backtrack();
202+
}
177203
}
178204

179205
fn synchronise(&mut self, assignments: &Assignments) {
180206
self.default_brancher.synchronise(assignments);
181-
self.other_brancher.synchronise(assignments);
207+
if !self.will_always_use_default() {
208+
self.other_brancher.synchronise(assignments);
209+
}
182210
}
183211
}
184212

pumpkin-solver/src/engine/cp/assignments.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -904,7 +904,7 @@ impl IntegerDomain {
904904
self.lower_bound_updates
905905
.iter()
906906
.filter(|u| u.trail_position <= trail_position)
907-
.last()
907+
.next_back()
908908
.expect("Cannot fail")
909909
.bound
910910
}
@@ -945,7 +945,7 @@ impl IntegerDomain {
945945
self.upper_bound_updates
946946
.iter()
947947
.filter(|u| u.trail_position <= trail_position)
948-
.last()
948+
.next_back()
949949
.expect("Cannot fail")
950950
.bound
951951
}

0 commit comments

Comments
 (0)