Skip to content

Commit 6728dad

Browse files
committed
Backtracking with backjumping improved.
1 parent 25fdf24 commit 6728dad

File tree

1 file changed

+29
-11
lines changed

1 file changed

+29
-11
lines changed

aima-core/src/main/java/aima/core/search/csp/solver/BackjumpingBacktrackingSolver.java

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,24 @@
66
import aima.core.search.csp.Variable;
77
import aima.core.util.Tasks;
88

9-
import java.util.HashSet;
10-
import java.util.List;
11-
import java.util.Optional;
12-
import java.util.Set;
9+
import java.util.*;
1310
import java.util.stream.Collectors;
1411

1512
// vm-options (Java > 8): --module-path ${PATH_TO_FX} --add-modules javafx.controls,javafx.fxml
1613

1714
/**
18-
* Simple version of Backtracking with backjumping. It analyzes reasons for dead-ends by means of so called nogoods
19-
* and by that tries to avoid useless search in subspaces without solution.
15+
* Artificial Intelligence A Modern Approach (3rd Ed.): Section 6.3, Page 223.<br>
16+
* A more intelligent approach to backtracking is to backtrack to a variable that might fix the problem — a variable
17+
* that was responsible for making one of the possible values of SA impossible. To do this, we will keep track of
18+
* a set of assignments that are in conflict with some value for SA. The set (in this case {Q=red, NSW=green, V=blue,}),
19+
* is called the conflict set for SA. The backjumping method backtracks to the most recent assignment in
20+
* the conflict set; in this case, backjumping would jump over Tasmania and try a new value for V. This method
21+
* is easily implemented by a modification to BACK TRACK such that it accumulates the conflict set while checking
22+
* for a legal value to assign. If no legal value is found, the algorithm should return the most recent element of
23+
* the conflict set along with the failure indicator.<br>
24+
*
25+
* In this implementation, backtrack returns the whole set of variables causing the dead-end instead of just the most
26+
* recent element. The set of variables involved in a conflict set is called nogood here.
2027
*
2128
* Limitations:
2229
* Only one nogood is tracked at a time thought there could be more of them
@@ -82,11 +89,7 @@ private SolutionOrNogood<VAR, VAL> backtrack(CSP<VAR, VAL> csp, Assignment<VAR,
8289
else
8390
result.nogood.addAll(res.nogood);
8491
} else {
85-
for (Constraint<VAR, VAL> cons : csp.getConstraints(var))
86-
if (!cons.isSatisfiedWith(assignment)) {
87-
result.nogood.addAll(cons.getScope());
88-
break; // only one nogood is tracked (kiss)
89-
}
92+
result.nogood.addAll(findCause(csp, assignment, var));
9093
}
9194
assignment.remove(var);
9295
}
@@ -95,6 +98,18 @@ private SolutionOrNogood<VAR, VAL> backtrack(CSP<VAR, VAL> csp, Assignment<VAR,
9598
return result;
9699
}
97100

101+
/**
102+
* Gets an assignment which is inconsistent at <code>var</code> and returns a collection of variables causing the
103+
* inconsistency. This implementation just returns the scope of one unsatisfied constraint. A smarter
104+
* selection could increase jump length.
105+
*/
106+
protected Collection<VAR> findCause(CSP<VAR, VAL> csp, Assignment<VAR, VAL> assignment, VAR var) {
107+
for (Constraint<VAR, VAL> cons : csp.getConstraints(var))
108+
if (!cons.isSatisfiedWith(assignment))
109+
return cons.getScope();
110+
return null; // will never happen!
111+
}
112+
98113
/**
99114
* Primitive operation, selecting a not yet assigned variable.
100115
*/
@@ -113,6 +128,9 @@ private Iterable<VAL> orderDomainValues(CSP<VAR, VAL> csp, Assignment<VAR, VAL>
113128
return (valOrderingStrategy != null) ? valOrderingStrategy.apply(csp, assignment, var) : csp.getDomain(var);
114129
}
115130

131+
/**
132+
* Data structure which can store an assignment as well as a nogood.
133+
*/
116134
private static class SolutionOrNogood<VAR extends Variable, VAL> {
117135
Assignment<VAR, VAL> solution;
118136
Set<VAR> nogood = new HashSet<>(); // set of variables whose current value bindings caused a dead-end

0 commit comments

Comments
 (0)