|
1 | 1 | package aima.core.logic.planning; |
2 | 2 |
|
| 3 | +import aima.core.agent.Action; |
| 4 | +import aima.core.logic.fol.kb.data.Literal; |
| 5 | + |
3 | 6 | import java.util.ArrayList; |
| 7 | +import java.util.Collections; |
| 8 | +import java.util.HashMap; |
4 | 9 | import java.util.List; |
5 | 10 |
|
6 | 11 | /** |
|
12 | 17 | * followed by A i ; until we reach a termination condition. |
13 | 18 | * |
14 | 19 | * @author samagra |
| 20 | + * @author Ruediger Lunde |
15 | 21 | */ |
16 | 22 | public class Graph { |
17 | | - private ArrayList<Level> levels;// Levels |
18 | | - private List<ActionSchema> propositionalisedActions; |
| 23 | + private final List<Level<Literal, ActionSchema>> literalLevels; |
| 24 | + private final List<Level<ActionSchema, Literal>> actionLevels; |
19 | 25 |
|
20 | 26 | public Graph(Problem problem) { |
21 | | - levels = new ArrayList<>(); |
22 | | - levels.add(new Level(null, problem)); |
23 | | - propositionalisedActions = problem.getPropositionalisedActions(); |
| 27 | + literalLevels = new ArrayList<>(); |
| 28 | + literalLevels.add(createLiteralLevel(null, problem)); |
| 29 | + actionLevels = new ArrayList<>(); |
24 | 30 | } |
25 | 31 |
|
26 | | - public Level getLevel(int i) { |
27 | | - return levels.get(i); |
| 32 | + public Level<Literal, ActionSchema> getLiteralLevel(int i) { |
| 33 | + return literalLevels.get(i); |
28 | 34 | } |
29 | 35 |
|
30 | | - public int numLevels() { |
31 | | - return levels.size(); |
| 36 | + public Level<ActionSchema, Literal> getActionLevel(int i) { |
| 37 | + return actionLevels.get(i); |
32 | 38 | } |
33 | 39 |
|
34 | | - public ArrayList<Level> getLevels() { |
35 | | - return levels; |
| 40 | + public List<Level<Literal, ActionSchema>> getLiteralLevels() { |
| 41 | + return literalLevels; |
36 | 42 | } |
37 | 43 |
|
38 | | - public List<ActionSchema> getPropositionalisedActions() { |
39 | | - return propositionalisedActions; |
| 44 | + public int numLevels() { |
| 45 | + return literalLevels.size(); |
40 | 46 | } |
41 | 47 |
|
42 | 48 | /** |
43 | | - * This method adds levels (an action and a state level) for a new state |
| 49 | + * This method adds a level (an action and a state level) for a new state |
44 | 50 | * to the planning graph. |
45 | 51 | */ |
46 | 52 | 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); |
| 53 | + Level<Literal, ActionSchema> litLevelCurr = literalLevels.get(numLevels() - 1); |
| 54 | + Level<ActionSchema, Literal> actLevelNext = createActionLevel(litLevelCurr, problem); |
| 55 | + Level<Literal, ActionSchema> litLevelNext = createLiteralLevel(actLevelNext, problem); |
| 56 | + actionLevels.add(actLevelNext); |
| 57 | + literalLevels.add(litLevelNext); |
| 58 | + } |
| 59 | + |
| 60 | + private Level<ActionSchema, Literal> createActionLevel(Level<Literal, ActionSchema> prevLevel, Problem problem) { |
| 61 | + Level<ActionSchema, Literal> result = new Level<>(prevLevel, problem); |
| 62 | + // add actions with empty precondition |
| 63 | + for (ActionSchema action : problem.getPropositionalisedActions()) { |
| 64 | + if (action.getPrecondition().size()==0) |
| 65 | + result.getLevelObjects().add(action); |
| 66 | + } |
| 67 | + // set next links |
| 68 | + for (ActionSchema action : result.getLevelObjects()) |
| 69 | + result.putToNextLinks(action, new ArrayList<>(action.getEffects())); |
| 70 | + calculateMutexLinksForActionLevel(result); |
| 71 | + return result; |
| 72 | + } |
| 73 | + |
| 74 | + // prevLevel can be null |
| 75 | + private Level<Literal, ActionSchema> createLiteralLevel(Level<ActionSchema, Literal> prevLevel, Problem problem) { |
| 76 | + Level<Literal, ActionSchema> result = (prevLevel == null) |
| 77 | + ? new Level<>(problem.getInitialState().getFluents(), problem) |
| 78 | + : new Level<>(prevLevel, problem); |
| 79 | + calculateNextLinks(result, problem); |
| 80 | + calculateMutexLinksForLiteralLevel(result); |
| 81 | + return result; |
| 82 | + } |
| 83 | + |
| 84 | + private void calculateNextLinks(Level<Literal, ActionSchema> level, Problem problem) { |
| 85 | + // add applicable actions: |
| 86 | + for (ActionSchema action : problem.getPropositionalisedActions()) { |
| 87 | + if (level.getLevelObjects().containsAll(action.getPrecondition())) |
| 88 | + for (Literal literal : action.getPrecondition()) |
| 89 | + level.addToNextLinks(literal, action); |
| 90 | + } |
| 91 | + // add persistence actions: |
| 92 | + for (Literal literal : level.getLevelObjects()) { |
| 93 | + ActionSchema action = new ActionSchema(ActionSchema.NO_OP, null, |
| 94 | + Collections.singletonList(literal), |
| 95 | + Collections.singletonList(literal)); |
| 96 | + level.addToNextLinks(literal, action); |
| 97 | + } |
| 98 | + } |
| 99 | + |
| 100 | + private void calculateMutexLinksForActionLevel(Level<ActionSchema, Literal> level) { |
| 101 | + List<ActionSchema> actions = level.getLevelObjects(); |
| 102 | + ActionSchema firstAction, secondAction; |
| 103 | + boolean checkMutex; |
| 104 | + |
| 105 | + for (int i = 0; i < actions.size(); i++) { |
| 106 | + firstAction = actions.get(i); |
| 107 | + List<Literal> firstActionEffects = firstAction.getEffects(); |
| 108 | + List<Literal> firstActionPositiveEffects = firstAction.getEffectsPositiveLiterals(); |
| 109 | + List<Literal> firstActionPreconditions = firstAction.getPrecondition(); |
| 110 | + for (int j = i + 1; j < actions.size(); j++) { |
| 111 | + checkMutex = false; |
| 112 | + secondAction = actions.get(j); |
| 113 | + List<Literal> secondActionEffects = secondAction.getEffects(); |
| 114 | + List<Literal> secondActionNegatedLiterals = secondAction.getEffectsNegativeLiterals(); |
| 115 | + List<Literal> secondActionPreconditions = secondAction.getPrecondition(); |
| 116 | + for (Literal posLiteral : firstActionPositiveEffects) { |
| 117 | + for (Literal negatedLit : secondActionNegatedLiterals) |
| 118 | + if (posLiteral.equals(new Literal(negatedLit.getAtomicSentence(), false))) |
| 119 | + checkMutex = true; |
| 120 | + } |
| 121 | + if (!checkMutex) { |
| 122 | + if (checkInterference(secondActionPreconditions, firstActionEffects)) |
| 123 | + checkMutex = true; |
| 124 | + if (checkInterference(firstActionPreconditions, secondActionEffects)) |
| 125 | + checkMutex = true; |
| 126 | + } |
| 127 | + if (!checkMutex) { |
| 128 | + HashMap<Literal, List<Literal>> prevMutex = level.getPrevLevel().getMutexLinks(); |
| 129 | + if (prevMutex != null) { |
| 130 | + for (Literal firstActionPrecondition : firstActionPreconditions) |
| 131 | + for (Literal secondActionPrecondition : secondActionPreconditions) |
| 132 | + if (prevMutex.get(firstActionPrecondition) != null |
| 133 | + && prevMutex.get(firstActionPrecondition).contains |
| 134 | + (secondActionPrecondition)) |
| 135 | + checkMutex = true; |
| 136 | + } |
| 137 | + } |
| 138 | + if (checkMutex) { |
| 139 | + level.addToMutexLinks(firstAction, secondAction); |
| 140 | + level.addToMutexLinks(secondAction, firstAction); |
| 141 | + } |
| 142 | + } |
| 143 | + } |
| 144 | + } |
| 145 | + |
| 146 | + private boolean checkInterference(List<Literal> firstActionPreconditions, List<Literal> secondActionEffects) { |
| 147 | + boolean checkMutex = false; |
| 148 | + for (Literal secondActionEffect : secondActionEffects) { |
| 149 | + for (Literal firstActionPrecondition : firstActionPreconditions) { |
| 150 | + if (secondActionEffect.equals(new Literal(firstActionPrecondition.getAtomicSentence(), |
| 151 | + firstActionPrecondition.isPositiveLiteral()))) { |
| 152 | + checkMutex = true; |
| 153 | + } |
| 154 | + } |
| 155 | + } |
| 156 | + return checkMutex; |
| 157 | + } |
| 158 | + |
| 159 | + private void calculateMutexLinksForLiteralLevel(Level<Literal, ActionSchema> level) { |
| 160 | + Level<ActionSchema, Literal> prevLevel = level.getPrevLevel(); |
| 161 | + if (prevLevel == null) |
| 162 | + return; |
| 163 | + List<Literal> literals = level.getLevelObjects(); |
| 164 | + Literal firstLiteral, secondLiteral; |
| 165 | + List<ActionSchema> possibleActionsFirst, possibleActionsSecond; |
| 166 | + for (int i = 0; i < literals.size(); i++) { |
| 167 | + firstLiteral = literals.get(i); |
| 168 | + possibleActionsFirst = level.getPrevLinks().get(firstLiteral); |
| 169 | + for (int j = i; j < literals.size(); j++) { |
| 170 | + secondLiteral = literals.get(j); |
| 171 | + possibleActionsSecond = level.getPrevLinks().get(secondLiteral); |
| 172 | + if (firstLiteral.getAtomicSentence().getSymbolicName().equals |
| 173 | + (secondLiteral.getAtomicSentence().getSymbolicName()) && |
| 174 | + ((firstLiteral.isNegativeLiteral() && secondLiteral.isPositiveLiteral()) || |
| 175 | + firstLiteral.isPositiveLiteral() && secondLiteral.isNegativeLiteral())) { |
| 176 | + level.addToMutexLinks(firstLiteral, secondLiteral); |
| 177 | + level.addToMutexLinks(secondLiteral, firstLiteral); |
| 178 | + } else { |
| 179 | + boolean eachPossiblePairExclusive = true; |
| 180 | + HashMap<ActionSchema, List<ActionSchema>> prevMutexes = prevLevel.getMutexLinks(); |
| 181 | + for (ActionSchema firstAction : possibleActionsFirst) { |
| 182 | + for (ActionSchema secondAction : possibleActionsSecond) { |
| 183 | + if ((!prevMutexes.containsKey(firstAction)) |
| 184 | + || (!prevMutexes.get(firstAction).contains(secondAction))) { |
| 185 | + eachPossiblePairExclusive = false; |
| 186 | + } |
| 187 | + } |
| 188 | + } |
| 189 | + if (eachPossiblePairExclusive) { |
| 190 | + level.addToMutexLinks(firstLiteral, secondLiteral); |
| 191 | + level.addToMutexLinks(secondLiteral, firstLiteral); |
| 192 | + } |
| 193 | + } |
| 194 | + } |
| 195 | + } |
52 | 196 | } |
53 | 197 | } |
0 commit comments