better toString for actions and some more tests.

This commit is contained in:
Naveen Sundar Govindarajulu 2017-01-15 09:10:48 -05:00
parent 8c78a2f8e5
commit 598f9b3dff
10 changed files with 307 additions and 44 deletions

View file

@ -2,6 +2,7 @@ package edu.rpi.rair;
import com.naveensundarg.shadow.prover.representations.formula.And;
import com.naveensundarg.shadow.prover.representations.formula.Formula;
import com.naveensundarg.shadow.prover.representations.value.Compound;
import com.naveensundarg.shadow.prover.representations.value.Value;
import com.naveensundarg.shadow.prover.representations.value.Variable;
import com.naveensundarg.shadow.prover.utils.CollectionUtils;
@ -27,6 +28,8 @@ public class Action {
private int weight;
private final Compound shorthand;
private Action(String name, Set<Formula> preconditions, Set<Formula> additions, Set<Formula> deletions, List<Variable> freeVariables) {
this.name = name;
this.preconditions = preconditions;
@ -46,6 +49,35 @@ public class Action {
this.weight = preconditions.stream().mapToInt(Formula::getWeight).sum() +
additions.stream().mapToInt(Formula::getWeight).sum() +
deletions.stream().mapToInt(Formula::getWeight).sum();
List<Value> valuesList = freeVariables.stream().collect(Collectors.toList());;
this.shorthand = new Compound(name, valuesList);
}
private Action(String name, Set<Formula> preconditions, Set<Formula> additions,
Set<Formula> deletions, List<Variable> freeVariables,
Compound shorthand
) {
this.name = name;
this.preconditions = preconditions;
this.additions = additions;
this.deletions = deletions;
List<Variable> computedFreeVariables = preconditions.
stream().
map(x -> Sets.difference(x.variablesPresent(), x.boundVariablesPresent())).
reduce(Sets.newSet(), Sets::union).
stream().sorted().collect(Collectors.toList());
this.freeVariables = freeVariables;
this.precondition = new And(preconditions.stream().collect(Collectors.toList()));
this.weight = preconditions.stream().mapToInt(Formula::getWeight).sum() +
additions.stream().mapToInt(Formula::getWeight).sum() +
deletions.stream().mapToInt(Formula::getWeight).sum();
this.shorthand = shorthand;
}
@ -97,16 +129,20 @@ public class Action {
newFreeVraibles.add(var);
}
}
return new Action(name, newPreconditions, newAdditions, newDeletions, newFreeVraibles);
List<Value> valuesList = freeVariables.stream().collect(Collectors.toList());;
Compound shorthand = (Compound)(new Compound(name, valuesList)).apply(binding);
return new Action(name, newPreconditions, newAdditions, newDeletions, newFreeVraibles, shorthand);
}
public String getName() {
return name;
}
@Override
public String toString() {
return "Action{" +
"preconditions=" + preconditions +
", additions=" + additions +
", deletions=" + deletions +
", name='" + name + '\'' +
'}';
return shorthand.getArguments().length == 0? name: shorthand.toString();
}
@Override

View file

@ -0,0 +1,12 @@
package edu.rpi.rair.utils;
import edu.rpi.rair.State;
import us.bpsm.edn.parser.Parseable;
/**
* Created by naveensundarg on 1/15/17.
*/
public class Commons {
}

View file

@ -2,6 +2,7 @@ package edu.rpi.rair.utils;
import clojure.lang.Obj;
import com.naveensundarg.shadow.prover.representations.formula.Formula;
import com.naveensundarg.shadow.prover.representations.value.Value;
import com.naveensundarg.shadow.prover.representations.value.Variable;
import com.naveensundarg.shadow.prover.utils.CollectionUtils;
import com.naveensundarg.shadow.prover.utils.Reader;
@ -16,10 +17,8 @@ import us.bpsm.edn.parser.Token;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.security.Key;
import java.util.*;
import java.util.stream.Collectors;
/**
@ -27,11 +26,13 @@ import java.util.stream.Collectors;
*/
public class PlanningProblem {
public Set<Formula> background;
public Set<Action> actions;
public State start;
public State goal;
public String name;
private Set<Formula> background;
private Set<Action> actions;
private State start;
private State goal;
private String name;
private Optional<Set<List<Action>>> expectedActionSequencesOpt;
private Map<String, Action> actionMap;
private static final Keyword BACKGROUND = Keyword.newKeyword("background");
private static final Keyword START = Keyword.newKeyword("start");
@ -45,6 +46,7 @@ public class PlanningProblem {
private static final Symbol ACTION_DEFINER = Symbol.newSymbol("define-action");
private static final Keyword EXPECTED_PLANS = Keyword.newKeyword("expected-plans");
public PlanningProblem(String name, Set<Formula> background, State start, State goal, Set<Action> actions) {
@ -53,6 +55,19 @@ public class PlanningProblem {
this.actions = actions;
this.goal = goal;
this.name = name;
this.actionMap = CollectionUtils.newMap();
this.expectedActionSequencesOpt = Optional.empty();
}
public PlanningProblem(String name, Set<Formula> background, State start, State goal, Set<Action> actions, Set<List<Action>> expectedActionSequences) {
this.background = background;
this.start = start;
this.actions = actions;
this.goal = goal;
this.name = name;
this.actionMap = CollectionUtils.newMap();
this.expectedActionSequencesOpt = Optional.of(expectedActionSequences);
}
public static List<PlanningProblem> readFromFile(InputStream inputStream) throws Reader.ParsingException {
@ -76,9 +91,44 @@ public class PlanningProblem {
String name = planningProblemSpec.get(NAME).toString();
Set<Action> actions = readActionsFrom(actionDefinitions);
Map<String, Action> actionMap = CollectionUtils.newMap();
planningProblems.add(new PlanningProblem(name, background, State.initializeWith(start),
actions.stream().forEach(action->{
actionMap.put(action.getName(), action);
});
if(planningProblemSpec.containsKey(EXPECTED_PLANS)){
List<?> plans = (List<?>) planningProblemSpec.get(EXPECTED_PLANS);
Set<List<Action>> expectedActions = plans.stream().map(plan->{
List<?> instantActionList = (List<?>) plan;
List<Action> actionsList = instantActionList.stream().map(x -> {
try {
return readInstantiatedAction(actionMap, x);
} catch (Reader.ParsingException e) {
return null;
}
}).collect(Collectors.toList());
if(actionsList.stream().anyMatch(Objects::isNull)){
return null;
} else {
return actionsList;
}
}).collect(Collectors.toSet());
planningProblems.add(new PlanningProblem(name, background, State.initializeWith(start),
State.initializeWith(goal), actions, expectedActions));
} else {
planningProblems.add(new PlanningProblem(name, background, State.initializeWith(start),
State.initializeWith(goal), actions));
}
nextValue = parser.nextValue(parseable);
}
@ -87,6 +137,44 @@ public class PlanningProblem {
}
private static Action readInstantiatedAction(Map<String, Action> actionMap, Object instantiatedActionSpec) throws Reader.ParsingException {
if(instantiatedActionSpec instanceof List<?>){
List<?> instActionList = (List<?>) instantiatedActionSpec;
String name = instActionList.get(0).toString();
Action general = actionMap.get(name);
List<Variable> variables = general.openVars();
if(variables.size()!=instActionList.size()-1){
throw new AssertionError("Not a proper instantiation of "+ name);
}
Map<Variable, Value> binding = CollectionUtils.newMap();
for(int i = 1; i<instActionList.size(); i++){
binding.put(variables.get(i-1), Reader.readLogicValue(instActionList.get(i)));
}
return general.instantiate(binding);
} else {
String name = instantiatedActionSpec.toString();
if(actionMap.containsKey(name)){
return actionMap.get(name);
}
else{
return null;
}
}
}
private static Set<Action> readActionsFrom(List<?> actionSpecs) throws Reader.ParsingException {
Set<Action> actions = actionSpecs.stream().map(spec -> {
@ -156,6 +244,34 @@ public class PlanningProblem {
}
public Set<Formula> getBackground() {
return background;
}
public Set<Action> getActions() {
return actions;
}
public State getStart() {
return start;
}
public State getGoal() {
return goal;
}
public String getName() {
return name;
}
public Optional<Set<List<Action>>> getExpectedActionSequencesOpt() {
return expectedActionSequencesOpt;
}
public Map<String, Action> getActionMap() {
return actionMap;
}
@Override
public String toString() {
return "PlanningProblem{" +

View file

@ -8,7 +8,7 @@
:additions [R]
:deletions [Q]})]
:expected-plan [a1]
:expected-plans ([a1])
}
@ -119,4 +119,54 @@
[(define-action post-new-bid (?number)
{:preconditions [(bid ?number)]
:additions [(bid ($$sum 1 ?number))]
:deletions [(bid ?number)]})]}
:deletions [(bid ?number)]})]
:expected-plans ([(post-new-bid 0)
(post-new-bid 1)
(post-new-bid 2)
(post-new-bid 3)
(post-new-bid 4)])}
{:name "Moving Between Rooms"
:background [ (not (= room1 room2))]
:start [(In self room1)
(In commander room2)
(In prisoner room1)
(Open (door room2))
(not (Open (door room1))) ]
:goal [(In prisoner room2)]
:actions
[(define-action open-door [?room]
{:preconditions [(not (Open (door ?room)))]
:additions [(Open (door ?room))]
:deletions [(not (Open (door ?room)))]})
(define-action move-thing-from-to [?thing ?room1 ?room2]
{:preconditions [(not (= ?room1 ?room2))
(In ?thing ?room1)
(Open (door ?room1))
(Open (door ?room2))]
:additions [(In ?thing ?room2)]
:deletions [(In ?thing ?room1)
(In self ?room1)]})
(define-action accompany-from-to [?thing ?room1 ?room2]
{:preconditions [(not (= ?room1 ?room2))
(In self ?room1)
(In ?thing ?room1)
(Open (door ?room1))
(Open (door ?room2))]
:additions [(In ?thing ?room2)
(In ?self ?room2)]
:deletions [(In ?thing ?room1)
(In self ?room1)]})]
:expected-plans ([(open-door room1)
(accompany-from-to prisoner room1 room2)]
[(open-door room1)
(move-thing-from-to prisoner room1 room2)])
}

View file

@ -0,0 +1 @@

View file

@ -1,27 +1,30 @@
{
:name "test 1"
:background [ (forall (?x ?y ?room1 ?room2)
(if (and (Interrogates ?x ?y)
(In ?x ?room1)
(In ?y ?room2))
(= ?room1 ?room2)))
{:name "Sim"
:background []
:start [(In self room1)
(In commander room2)
()
]
:start [Be_In_Room
(Closed (door room1))
(Accompany self prisoner)]
(In prisoner room1)
(Open (door room2))
(not (Open (door room1))) ]
:goalSequence [
[G1 1 [(In prisoner1 room1)]]
[G2 1 [(Closed (door room1))]]
[G3 1 [(Accompany self prisoner)]]
:actions [(define-action open-door [?room]
{:preconditions [(not (Open (door ?room)))]
:additions [(Open (door ?room))]
:deletions [(not (Open (door ?room)))]})
[G4 2 [(Interrogates command robot)]]
[G5 2 []]
]
(define-action accompany-from-to [?thing ?room1 ?room2]
{:preconditions [(In self ?room1)
(In ?thing ?room1)
(Open (door ?room1))
(Open (door ?room2))]
:additions [(In ?thing ?room2)
(In ?self ?room2)]
:deletions [(In ?thing ?room1)
(In self ?room1)]})]
:expected-plans ([(open-door room1)
(accompany-from-to prisoner room1 room2)])
}

View file

@ -10,6 +10,7 @@ import org.testng.annotations.Test;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import static org.testng.Assert.*;
@ -33,7 +34,7 @@ public class DepthFirstPlannerTest {
Planner depthFirstPlanner = new DepthFirstPlanner();
PlanningProblem planningProblem = planningProblemList.get(2);
System.out.println(depthFirstPlanner.plan(planningProblem.background, planningProblem.actions, planningProblem.start, planningProblem.goal));
System.out.println(depthFirstPlanner.plan(planningProblem.getBackground(), planningProblem.getActions(), planningProblem.getStart(), planningProblem.getGoal()));
}
@DataProvider
@ -55,16 +56,29 @@ public class DepthFirstPlannerTest {
}
@Test(dataProvider = "testCompletenessDataProvider")
public void testCompletness(PlanningProblem planningProblem) throws Exception {
Optional<Set<Plan>> possiblePlans = depthFirstPlanner.plan(
planningProblem.background,
planningProblem.actions,
planningProblem.start,
planningProblem.goal);
planningProblem.getBackground(),
planningProblem.getActions(),
planningProblem.getStart(),
planningProblem.getGoal());
Assert.assertTrue(possiblePlans.isPresent());
Set<Plan> plans = possiblePlans.get();
if(planningProblem.getExpectedActionSequencesOpt().isPresent()){
Set<List<Action>> actionSequences = plans.stream().map(Plan::getActions).collect(Collectors.toSet());
Set<List<Action>> expectedActionSequences = planningProblem.getExpectedActionSequencesOpt().get();
Assert.assertEquals(actionSequences, expectedActionSequences);
}
}
}

View file

@ -0,0 +1 @@

View file

@ -0,0 +1,30 @@
{:name "Sim"
:background []
:start [(In self room1)
(In commander room2)
(In prisoner room1)
(Open (door room2))
(not (Open (door room1))) ]
:actions [(define-action open-door [?room]
{:preconditions [(not (Open (door ?room)))]
:additions [(Open (door ?room))]
:deletions [(not (Open (door ?room)))]})
(define-action accompany-from-to [?thing ?room1 ?room2]
{:preconditions [(In self ?room1)
(In ?thing ?room1)
(Open (door ?room1))
(Open (door ?room2))]
:additions [(In ?thing ?room2)
(In ?self ?room2)]
:deletions [(In ?thing ?room1)
(In self ?room1)]})]
:expected-plans ([(open-door room1)
(accompany-from-to prisoner room1 room2)])
}

Binary file not shown.