Skip to content

Commit 4682183

Browse files
committed
To bugs in GraphPlan fixed (missing search and wrong nogood handling).
1 parent 05fa84a commit 4682183

File tree

2 files changed

+41
-48
lines changed

2 files changed

+41
-48
lines changed

aima-core/src/main/java/aima/core/logic/planning/GraphPlanAlgorithm.java

Lines changed: 41 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ public List<List<ActionSchema>> graphPlan(Problem problem) {
5454
// if goals all non-mutex in St of graph then
5555
if (checkAllGoalsNonMutex(state, goals)) {
5656
// solution ← EXTRACT-SOLUTION(graph, goals, NUMLEVELS(graph), nogoods)
57-
List<List<ActionSchema>> solution = extractSolution(graph, goals, graph.numLevels(), nogoods);
57+
List<List<ActionSchema>> solution = extractSolution(graph, goals, graph.numLevels()-1, nogoods);
5858
// if solution ≠ failure then return solution
5959
if (solution != null && solution.size() != 0)
6060
return solution;
@@ -74,8 +74,8 @@ public List<List<ActionSchema>> graphPlan(Problem problem) {
7474
* Artificial Intelligence A Modern Approach (3rd Edition): page 384.<br>
7575
* <p>
7676
* We can define EXTRACT -SOLUTION as a backward search problem, where
77-
* each state in the search contains a pointer to a level in the planning graph and a set of unsat-
78-
* isfied goals. We define this search problem as follows:
77+
* each state in the search contains a pointer to a level in the planning graph and a set of
78+
* unsatisfied goals. We define this search problem as follows:
7979
* • The initial state is the last level of the planning graph, S n , along with the set of goals
8080
* from the planning problem.
8181
* • The actions available in a state at level S i are to select any conflict-free subset of the
@@ -85,66 +85,60 @@ public List<List<ActionSchema>> graphPlan(Problem problem) {
8585
* of their preconditions are mutex.
8686
* • The goal is to reach a state at level S 0 such that all the goals are satisfied.
8787
* • The cost of each action is 1.
88+
* Here a simple depth-first search is used.
8889
*
8990
* @param graph The planning graph.
9091
* @param goals Goals of the planning problem.
9192
* @param numLevel Number of levels in the graph.
9293
* @param nogoods A hash table to store previously calculated results.
9394
* @return a solution if found else null
9495
*/
95-
private List<List<ActionSchema>> extractSolution(Graph graph, List<Literal> goals, int numLevel,
96+
private List<List<ActionSchema>> extractSolution(Graph graph, List<Literal> goals, int level,
9697
Hashtable<Integer, List<Literal>> nogoods) {
97-
if (nogoods.contains(numLevel))
98+
if (level <= 0)
99+
return new ArrayList<>();
100+
if (nogoods.containsKey(level) && nogoods.get(level).contains(goals))
98101
return null;
99102

100-
List<Literal> goalsCurr = new ArrayList<>(goals);
101-
List<List<ActionSchema>> solution = new ArrayList<>();
102-
for (int level = (graph.numLevels() - 1) / 2; level > 0; level--) {
103-
Level currLevel = graph.getLevels().get(2 * level);
104-
List<List<ActionSchema>> setOfPossibleActions = new ArrayList<>();
105-
HashMap<Object, List<Object>> mutexLinks = currLevel.getPrevLevel().getMutexLinks();
106-
for (Literal literal : goalsCurr) {
107-
List<ActionSchema> possibleActionsPerLiteral = new ArrayList<>();
108-
for (Object action : currLevel.getPrevLinks().get(literal)) {
109-
possibleActionsPerLiteral.add((ActionSchema) action);
103+
Level currLevel = graph.getLevels().get(level);
104+
List<List<ActionSchema>> setOfPossibleActions = new ArrayList<>();
105+
HashMap<Object, List<Object>> mutexLinks = currLevel.getPrevLevel().getMutexLinks();
106+
for (Literal literal : goals) {
107+
List<ActionSchema> possibleActionsPerLiteral = new ArrayList<>();
108+
for (Object action : currLevel.getPrevLinks().get(literal))
109+
possibleActionsPerLiteral.add((ActionSchema) action);
110+
setOfPossibleActions.add(possibleActionsPerLiteral);
111+
}
112+
List<List<ActionSchema>> allPossibleSubSets = generateCombinations(setOfPossibleActions);
113+
boolean validSet;
114+
List<ActionSchema> setToBeTaken = null;
115+
for (List<ActionSchema> possibleSet : allPossibleSubSets) {
116+
validSet = true;
117+
ActionSchema firstAction, secondAction;
118+
for (int i = 0; i < possibleSet.size(); i++) {
119+
firstAction = possibleSet.get(i);
120+
for (int j = i + 1; j < possibleSet.size(); j++) {
121+
secondAction = possibleSet.get(j);
122+
if (mutexLinks.containsKey(firstAction) && mutexLinks.get(firstAction).contains(secondAction))
123+
validSet = false;
110124
}
111-
setOfPossibleActions.add(possibleActionsPerLiteral);
112125
}
113-
List<List<ActionSchema>> allPossibleSubSets = generateCombinations(setOfPossibleActions);
114-
boolean validSet;
115-
List<ActionSchema> setToBeTaken = null;
116-
for (List<ActionSchema> possibleSet : allPossibleSubSets) {
117-
validSet = true;
118-
ActionSchema firstAction, secondAction;
119-
for (int i = 0; i < possibleSet.size(); i++) {
120-
firstAction = possibleSet.get(i);
121-
for (int j = i + 1; j < possibleSet.size(); j++) {
122-
secondAction = possibleSet.get(j);
123-
if (mutexLinks.containsKey(firstAction) && mutexLinks.get(firstAction).contains(secondAction))
124-
validSet = false;
125-
}
126+
if (validSet) {
127+
List<Literal> newGoals = new ArrayList<>();
128+
for (ActionSchema action : possibleSet) {
129+
for (Literal literal : action.getPrecondition())
130+
if (!newGoals.contains(literal))
131+
newGoals.add(literal);
126132
}
127-
if (validSet) {
128-
// This is too simple. Completeness is lost. Search would be required... (RLu)
129-
setToBeTaken = possibleSet;
130-
break;
131-
}
132-
}
133-
if (setToBeTaken == null) {
134-
nogoods.put(level, goalsCurr);
135-
return null;
136-
}
137-
solution.add(setToBeTaken);
138-
goalsCurr.clear();
139-
for (ActionSchema action : setToBeTaken) {
140-
for (Literal literal : action.getPrecondition()) {
141-
if (!goalsCurr.contains(literal)) {
142-
goalsCurr.add(literal);
143-
}
133+
List<List<ActionSchema>> solution = extractSolution(graph, newGoals, level-2, nogoods);
134+
if (solution != null) {
135+
solution.add(possibleSet);
136+
return solution;
144137
}
145138
}
146139
}
147-
return solution;
140+
nogoods.put(level, goals);
141+
return null;
148142
}
149143

150144
/**

aima-core/src/test/java/aima/test/core/unit/logic/planning/GraphPlanAlgorithmTest.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ public void test() {
1919
GraphPlanAlgorithm algorithm = new GraphPlanAlgorithm();
2020
Problem spareTireProblem = PlanningProblemFactory.spareTireProblem();
2121
List<List<ActionSchema>> solution = algorithm.graphPlan(spareTireProblem);
22-
Collections.reverse(solution);
2322
ActionSchema removeSpareTrunk = new ActionSchema("Remove", null,
2423
"At(Spare,Trunk)",
2524
"~At(Spare,Trunk)^At(Spare,Ground)");

0 commit comments

Comments
 (0)