Skip to content

Commit e578677

Browse files
committed
Code cleaned up.
1 parent 2c6acd9 commit e578677

File tree

5 files changed

+81
-139
lines changed

5 files changed

+81
-139
lines changed

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

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,19 @@
1414
* @author samagra
1515
*/
1616
public class Graph {
17-
ArrayList<Level> levels;// Levels
18-
Problem problem;// The planning problem
19-
List<ActionSchema> propositionalisedActions;
17+
private ArrayList<Level> levels;// Levels
18+
private List<ActionSchema> propositionalisedActions;
2019

21-
public Graph(Problem problem, Level initialLevel) {
22-
this.problem = problem;
20+
public Graph(Problem problem) {
2321
levels = new ArrayList<>();
24-
levels.add(initialLevel);
22+
levels.add(new Level(null, problem));
2523
propositionalisedActions = problem.getPropositionalisedActions();
2624
}
2725

26+
public Level getLevel(int i) {
27+
return levels.get(i);
28+
}
29+
2830
public int numLevels() {
2931
return levels.size();
3032
}
@@ -33,18 +35,19 @@ public ArrayList<Level> getLevels() {
3335
return levels;
3436
}
3537

36-
public Problem getProblem() {
37-
return problem;
38-
}
39-
4038
public List<ActionSchema> getPropositionalisedActions() {
4139
return propositionalisedActions;
4240
}
4341

44-
public Graph addLevel() {
45-
Level lastLevel = levels.get(levels.size() - 1);
46-
Level level = new Level(lastLevel, this.problem);
47-
levels.add(level);
48-
return this;
42+
/**
43+
* This method adds levels (an action and a state level) for a new state
44+
* to the planning graph.
45+
*/
46+
public void expand(Problem problem) {
47+
Level level0 = levels.get(levels.size() - 1);
48+
Level level1 = new Level(level0, problem); // new action level
49+
Level level2 = new Level(level1, problem); // new state level
50+
levels.add(level1);
51+
levels.add(level2);
4952
}
5053
}

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

Lines changed: 22 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,9 @@ public class GraphPlanAlgorithm {
4242
*/
4343
public List<List<ActionSchema>> graphPlan(Problem problem) {
4444
// graph ← INITIAL-PLANNING-GRAPH(problem)
45-
Graph graph = initialPlanningGraph(problem);
45+
Graph graph = new Graph(problem);
4646
// goals ← CONJUNCTS(problem.GOAL)
47-
List<Literal> goals = conjuncts(problem.getGoalState());
47+
List<Literal> goals = problem.getGoalState().getFluents();
4848
// nogoods ← an empty hash table
4949
Hashtable<Integer, List<Literal>> nogoods = new Hashtable<>();
5050
Level state;
@@ -64,7 +64,7 @@ public List<List<ActionSchema>> graphPlan(Problem problem) {
6464
if (levelledOff(graph) && leveledOff(nogoods))
6565
return null;
6666
// graph ← EXPAND-GRAPH(graph, problem)
67-
graph = expandGraph(graph);
67+
graph.expand(problem);
6868
}
6969
}
7070

@@ -129,6 +129,7 @@ private List<List<ActionSchema>> extractSolution(Graph graph, List<Literal> goal
129129
if (!newGoals.contains(literal))
130130
newGoals.add(literal);
131131
}
132+
newGoals.sort(Comparator.comparing(Literal::hashCode)); // defined order necessary for nogood test
132133
List<List<ActionSchema>> solution = extractSolution(graph, newGoals, level-2, nogoods);
133134
if (solution != null) {
134135
solution.add(possibleSet);
@@ -141,10 +142,9 @@ private List<List<ActionSchema>> extractSolution(Graph graph, List<Literal> goal
141142
}
142143

143144
public List<ActionSchema> asFlatList(List<List<ActionSchema>> solution) {
144-
List<ActionSchema> result = solution.stream().flatMap(Collection::stream)
145+
return solution.stream().flatMap(Collection::stream)
145146
.filter(actionSchema -> !ActionSchema.NO_OP.equals(actionSchema.getName()))
146147
.collect(Collectors.toList());
147-
return result;
148148
}
149149

150150
/**
@@ -174,20 +174,9 @@ private boolean checkAllGoalsNonMutex(Level level, List<Literal> goals) {
174174
return (!mutexCheck);
175175
}
176176

177-
/**
178-
* This method adds a new state (a state level and an action level both) to the planning graph.
179-
*
180-
* @param graph The planning graph.
181-
* @return The expanded graph.
182-
*/
183-
private Graph expandGraph(Graph graph) {
184-
return graph.addLevel().addLevel();
185-
}
186-
187177
/**
188178
* A graph is said to be levelled off if two consecutive levels are identical.
189179
*
190-
* @param nogoods
191180
* @return Boolean stating if the hashtable is levelled off.
192181
*/
193182
private boolean leveledOff(Hashtable<Integer, List<Literal>> nogoods) {
@@ -199,34 +188,30 @@ private boolean leveledOff(Hashtable<Integer, List<Literal>> nogoods) {
199188
/**
200189
* A graph is said to be levelled off if two consecutive levels are identical.
201190
*
202-
* @param graph
203191
* @return Boolean stating if the graph is levelled off.
204192
*/
205193
private boolean levelledOff(Graph graph) {
206194
if (graph.numLevels() < 2)
207195
return false;
208-
return graph.levels.get(graph.numLevels() - 1).equals(graph.levels.get(graph.numLevels() - 2));
196+
return graph.getLevel(graph.numLevels() - 1).equals(graph.getLevel(graph.numLevels() - 2));
209197
}
210198

211-
/**
212-
* Returns a list of literals in a state.
213-
*
214-
* @param goalState
215-
* @return List of literals.
216-
*/
217-
private List<Literal> conjuncts(State goalState) {
218-
return goalState.getFluents();
219-
}
220-
221-
/**
222-
* This method initialises the planning graph for a particular problem.
223-
*
224-
* @param problem The planning problem.
225-
* @return Graph for the planning problem.
226-
*/
227-
private Graph initialPlanningGraph(Problem problem) {
228-
Level initialLevel = new Level(null, problem);
229-
return new Graph(problem, initialLevel);
199+
public List<List<ActionSchema>> generateCombinations(List<List<ActionSchema>> actionLists) {
200+
List<List<ActionSchema>> result = new ArrayList<>();
201+
if (actionLists.size() == 1) {
202+
result.add(actionLists.get(0));
203+
} else if (actionLists.size() > 1) {
204+
result = combineTwoLists(actionLists.get(0), actionLists.get(1));
205+
if (actionLists.size() > 2) {
206+
for (int i = 2; i < actionLists.size(); i++)
207+
result = combineExtraList(result, actionLists.get(i));
208+
}
209+
}
210+
// sorting by increasing number of actions might reduce execution costs of first found solution.
211+
result = result.stream().sorted
212+
(Comparator.comparing(x -> x.stream().filter(y -> !ActionSchema.NO_OP.equals(y.getName())).count()))
213+
.collect(Collectors.toList());
214+
return result;
230215
}
231216

232217
// Helper methods for combinations and permutations.
@@ -251,21 +236,4 @@ public List<List<ActionSchema>> combineExtraList(List<List<ActionSchema>> combin
251236
}
252237
return result;
253238
}
254-
255-
public List<List<ActionSchema>> generateCombinations(List<List<ActionSchema>> actionLists) {
256-
List<List<ActionSchema>> result = new ArrayList<>();
257-
if (actionLists.size() == 1) {
258-
result.add(actionLists.get(0));
259-
return result;
260-
}
261-
if (actionLists.size() == 2) {
262-
return combineTwoLists(actionLists.get(0), actionLists.get(1));
263-
} else {
264-
result = combineTwoLists(actionLists.get(0), actionLists.get(1));
265-
for (int i = 2; i < actionLists.size(); i++) {
266-
result = combineExtraList(result, actionLists.get(i));
267-
}
268-
return result;
269-
}
270-
}
271239
}

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

Lines changed: 36 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -8,27 +8,24 @@
88
* The data structure for calculating and holding the levels of a planning graph.
99
*
1010
* @author samagra
11+
* @author Ruediger Lunde
1112
*/
1213
public class Level {
1314
List<Object> levelObjects;
14-
HashMap<Object, List<Object>> mutexLinks;//can be planned alternatively
15+
HashMap<Object, List<Object>> mutexLinks; //can be planned alternatively
1516
HashMap<Object, List<Object>> nextLinks;
1617
HashMap<Object, List<Object>> prevLinks;
17-
Problem problem;
1818
Level prevLevel;
1919

2020
public Level(Level prevLevel, Problem problem) {
21-
this.prevLevel = prevLevel;
22-
this.problem = problem;
21+
levelObjects = new ArrayList<>();
22+
prevLinks = new HashMap<>();
2323
if (prevLevel != null) {
24+
this.prevLevel = prevLevel;
2425
HashMap<Object, List<Object>> linksFromPreviousLevel = prevLevel.getNextLinks();
25-
this.problem = problem;
26-
levelObjects = new ArrayList<>();
27-
prevLinks = new HashMap<>();
2826
for (Object node : linksFromPreviousLevel.keySet()) {
2927
List<Object> thisLevelObjects = linksFromPreviousLevel.get(node);
30-
for (Object nextNode :
31-
thisLevelObjects) {
28+
for (Object nextNode : thisLevelObjects) {
3229
if (levelObjects.contains(nextNode)) {
3330
List<Object> tempPrevLink = prevLinks.get(nextNode);
3431
tempPrevLink.add(node);
@@ -37,38 +34,27 @@ public Level(Level prevLevel, Problem problem) {
3734
levelObjects.add(nextNode);
3835
prevLinks.put(nextNode, new ArrayList<>(Collections.singletonList(node)));
3936
}
40-
4137
}
42-
4338
}
44-
addNoPrecondActions();
45-
calculateNextLinks();
46-
calculateMutexLinks(prevLevel);
4739
} else {
48-
levelObjects = new ArrayList<>();
49-
prevLinks = new HashMap<>();
5040
levelObjects.addAll(problem.getInitialState().getFluents());
51-
for (Object obj : levelObjects) {
41+
for (Object obj : levelObjects)
5242
prevLinks.put(obj, new ArrayList<>());
53-
}
54-
addNoPrecondActions();
55-
calculateNextLinks();
56-
calculateMutexLinks(null);
5743
}
44+
addNoPrecondActions(problem);
45+
calculateNextLinks(problem);
46+
calculateMutexLinks(prevLevel);
5847
addPersistenceActions();
5948
}
6049

50+
// for testing only...
6151
public Level(Level prevLevel, Problem problem, String extraLiterals) {
6252
this(prevLevel, problem);
63-
this.addExtraLiterals(extraLiterals);
64-
}
65-
66-
public void addExtraLiterals(String s) {
67-
for (Literal literal : Utils.parse(s)) {
53+
for (Literal literal : Utils.parse(extraLiterals)) {
6854
if(!levelObjects.contains(literal))
6955
levelObjects.add(literal);
7056
}
71-
calculateNextLinks();
57+
calculateNextLinks(problem);
7258
calculateMutexLinks(getPrevLevel());
7359
addPersistenceActions();
7460
}
@@ -89,35 +75,34 @@ public HashMap<Object, List<Object>> getPrevLinks() {
8975
return prevLinks;
9076
}
9177

92-
public Problem getProblem() {
93-
return problem;
94-
}
95-
96-
private void addPersistenceActions() {
97-
if(getLevelObjects().get(0) instanceof Literal) {
98-
for (Object literal : getLevelObjects()) {
99-
ActionSchema action = new ActionSchema(ActionSchema.NO_OP, null,
100-
Collections.singletonList((Literal) literal),
101-
Collections.singletonList((Literal) literal));
102-
addToHashMap(literal, action, nextLinks);
103-
}
104-
}
78+
public Level getPrevLevel() {
79+
return prevLevel;
10580
}
10681

107-
public void addNoPrecondActions(){
108-
if(getLevelObjects().get(0) instanceof ActionSchema) {
82+
private void addNoPrecondActions(Problem problem) {
83+
if(levelObjects.get(0) instanceof ActionSchema) {
10984
for (ActionSchema action : problem.getPropositionalisedActions()) {
11085
if (action.getPrecondition().size()==0)
11186
levelObjects.add(action);
11287
}
11388
}
11489
}
11590

116-
91+
private void addPersistenceActions() {
92+
if(levelObjects.get(0) instanceof Literal) {
93+
for (Object literal : getLevelObjects()) {
94+
ActionSchema action = new ActionSchema(ActionSchema.NO_OP, null,
95+
Collections.singletonList((Literal) literal),
96+
Collections.singletonList((Literal) literal));
97+
addToHashMap(literal, action, nextLinks);
98+
}
99+
}
100+
}
117101

118102
private void calculateMutexLinks(Level prevLevel) {
119103
mutexLinks = new HashMap<>();
120-
if(prevLevel == null) return;
104+
if (prevLevel == null)
105+
return;
121106
if (levelObjects.get(0) instanceof Literal) {
122107
Literal firstLiteral, secondLiteral;
123108
List<Object> possibleActionsFirst, possibleActionsSecond;
@@ -221,18 +206,7 @@ private boolean checkInterference(List<Literal> firstActionPreconditions, List<L
221206
return checkMutex;
222207
}
223208

224-
private void addToHashMap(Object firstObject, Object secondObject, HashMap<Object, List<Object>> map) {
225-
List<Object> tempList;
226-
if (map.containsKey(firstObject)) {
227-
tempList = map.get(firstObject);
228-
tempList.add(secondObject);
229-
map.put(firstObject, tempList);
230-
} else {
231-
map.put(firstObject, new ArrayList<>(Collections.singletonList(secondObject)));
232-
}
233-
}
234-
235-
private void calculateNextLinks() {
209+
private void calculateNextLinks(Problem problem) {
236210
nextLinks = new HashMap<>();
237211
if (levelObjects.get(0) instanceof Literal) {
238212
for (ActionSchema action : problem.getPropositionalisedActions()) {
@@ -252,20 +226,20 @@ private void calculateNextLinks() {
252226
}
253227
} else if (levelObjects.get(0) instanceof ActionSchema) {
254228
for (Object action : levelObjects) {
255-
Object[] effects = ((ActionSchema) action).getEffects().toArray();
256-
nextLinks.put(action, new ArrayList<>(Arrays.asList(effects)));
229+
List<Literal> effects = ((ActionSchema) action).getEffects();
230+
nextLinks.put(action, new ArrayList<>(new ArrayList<Object>(effects)));
257231
}
258232
}
259-
260233
}
261234

262-
public Level getPrevLevel() {
263-
return prevLevel;
235+
private void addToHashMap(Object firstObject, Object secondObject, HashMap<Object, List<Object>> map) {
236+
List<Object> list = map.computeIfAbsent(firstObject, k -> new ArrayList<>());
237+
list.add(secondObject);
264238
}
265239

266240
@Override
267241
public boolean equals(Object obj) {
268-
if (!(obj instanceof Level))
242+
if (obj == null || getClass() != obj.getClass())
269243
return false;
270244
return this.levelObjects.containsAll(((Level) obj).levelObjects)
271245
&& ((Level) obj).levelObjects.containsAll(this.levelObjects)

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

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
/**
1212
* @author samagra
13+
* @author Ruediger Lunde
1314
*/
1415
public class GraphTest {
1516
Problem problem;
@@ -18,17 +19,12 @@ public class GraphTest {
1819
@Before
1920
public void setup() {
2021
problem = PlanningProblemFactory.spareTireProblem();
21-
firstLevel = new Level(null, problem, "At(Spare,Trunk)^At(Flat,Axle) ^~At(Spare,Axle)^~At(Flat,Ground)^~At(Spare,Ground)");
22-
secondLevel = new Level(firstLevel, problem);
23-
thirdLevel = new Level(thirdLevel, problem);
2422
}
2523

2624
@Test
27-
public void addLevelTest() {
28-
Graph graph = new Graph(problem, firstLevel);
29-
graph.addLevel();
30-
Assert.assertEquals(2, graph.getLevels().size());
31-
graph.addLevel();
25+
public void expandTest() {
26+
Graph graph = new Graph(problem);
27+
graph.expand(problem);
3228
Assert.assertEquals(3, graph.getLevels().size());
3329
}
3430
}

0 commit comments

Comments
 (0)