mirror of
https://github.com/RAIRLab/Spectra.git
synced 2025-12-22 00:11:24 +00:00
Fixes
This commit is contained in:
parent
e6cfb3e654
commit
fc1cbfb5ab
50 changed files with 377 additions and 155 deletions
206
src/main/java/com/naveensundarg/planner/Action.java
Normal file
206
src/main/java/com/naveensundarg/planner/Action.java
Normal file
|
|
@ -0,0 +1,206 @@
|
|||
package com.naveensundarg.planner;
|
||||
|
||||
import com.naveensundarg.shadow.prover.core.Logic;
|
||||
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;
|
||||
import com.naveensundarg.shadow.prover.utils.Sets;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Created by naveensundarg on 1/13/17.
|
||||
*/
|
||||
public class Action {
|
||||
|
||||
private final Set<Formula> preconditions;
|
||||
private final Set<Formula> additions;
|
||||
private final Set<Formula> deletions;
|
||||
private final List<Variable> freeVariables;
|
||||
|
||||
private final String name;
|
||||
private final Formula precondition;
|
||||
|
||||
private int weight;
|
||||
private final boolean trivial;
|
||||
|
||||
private final Compound shorthand;
|
||||
|
||||
public Action(String name, Set<Formula> preconditions, Set<Formula> additions, Set<Formula> deletions, List<Variable> freeVariables) {
|
||||
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();
|
||||
|
||||
List<Value> valuesList = freeVariables.stream().collect(Collectors.toList());;
|
||||
this.shorthand = new Compound(name, valuesList);
|
||||
|
||||
this.trivial = computeTrivialOrNot();
|
||||
}
|
||||
|
||||
public 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;
|
||||
this.trivial = computeTrivialOrNot();
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static Action buildActionFrom(String name,
|
||||
Set<Formula> preconditions,
|
||||
Set<Formula> additions,
|
||||
Set<Formula> deletions,
|
||||
List<Variable> freeVariables) {
|
||||
|
||||
return new Action(name, preconditions, additions, deletions, freeVariables);
|
||||
|
||||
}
|
||||
|
||||
public int getWeight() {
|
||||
return weight;
|
||||
}
|
||||
|
||||
public Formula getPrecondition() {
|
||||
return precondition;
|
||||
}
|
||||
|
||||
public Set<Formula> getPreconditions() {
|
||||
return preconditions;
|
||||
}
|
||||
|
||||
public Set<Formula> getAdditions() {
|
||||
return additions;
|
||||
}
|
||||
|
||||
public Set<Formula> getDeletions() {
|
||||
return deletions;
|
||||
}
|
||||
|
||||
public List<Variable> openVars() {
|
||||
|
||||
return freeVariables;
|
||||
|
||||
}
|
||||
|
||||
public Set<Formula> instantiateAdditions(Map<Variable, Value> mapping) {
|
||||
|
||||
return additions.stream().map(x -> x.apply(mapping)).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
public Set<Formula> instantiateDeletions(Map<Variable, Value> mapping) {
|
||||
|
||||
return deletions.stream().map(x -> x.apply(mapping)).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
|
||||
public Action instantiate(Map<Variable, Value> binding){
|
||||
|
||||
Set<Formula> newPreconditions = preconditions.stream().map(x->x.apply(binding)).collect(Collectors.toSet());
|
||||
Set<Formula> newAdditions = additions.stream().map(x->x.apply(binding)).collect(Collectors.toSet());
|
||||
Set<Formula> newDeletions = deletions.stream().map(x->x.apply(binding)).collect(Collectors.toSet());
|
||||
|
||||
List<Variable> newFreeVraibles = CollectionUtils.newEmptyList();
|
||||
for(Variable var: freeVariables){
|
||||
|
||||
if(!binding.keySet().contains(var)){
|
||||
newFreeVraibles.add(var);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public boolean isNonTrivial() {
|
||||
return !trivial;
|
||||
}
|
||||
|
||||
public boolean computeTrivialOrNot(){
|
||||
|
||||
boolean case1Trivial = Sets.subset(additions, preconditions) && deletions.isEmpty();
|
||||
|
||||
boolean case2Trivial = additions.isEmpty() && deletions.stream().allMatch(x->preconditions.stream().anyMatch(y->y.equals(Logic.negated(x))));
|
||||
|
||||
boolean trivial = case1Trivial || case2Trivial;
|
||||
|
||||
return trivial;
|
||||
}
|
||||
|
||||
public Compound getShorthand() {
|
||||
return shorthand;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return shorthand.getArguments().length == 0? name: shorthand.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
Action action = (Action) o;
|
||||
|
||||
if (!preconditions.equals(action.preconditions)) return false;
|
||||
if (!additions.equals(action.additions)) return false;
|
||||
if (!deletions.equals(action.deletions)) return false;
|
||||
return name.equals(action.name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = preconditions.hashCode();
|
||||
result = 31 * result + additions.hashCode();
|
||||
result = 31 * result + deletions.hashCode();
|
||||
result = 31 * result + name.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
23
src/main/java/com/naveensundarg/planner/Context.java
Normal file
23
src/main/java/com/naveensundarg/planner/Context.java
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
package com.naveensundarg.planner;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class Context {
|
||||
|
||||
private final List<PlanMethod> planMethods;
|
||||
private final boolean workFromScratch;
|
||||
|
||||
|
||||
public Context(List<PlanMethod> planMethods, boolean workFromScratch) {
|
||||
this.planMethods = planMethods;
|
||||
this.workFromScratch = workFromScratch;
|
||||
}
|
||||
|
||||
public List<PlanMethod> getPlanMethods() {
|
||||
return planMethods;
|
||||
}
|
||||
|
||||
public boolean isWorkFromScratch() {
|
||||
return workFromScratch;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
package com.naveensundarg.planner;
|
||||
|
||||
import com.naveensundarg.planner.utils.PlanningProblem;
|
||||
import com.naveensundarg.shadow.prover.representations.formula.Formula;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
public class ContextNormPlanner implements Planner {
|
||||
|
||||
private static DepthFirstPlanner depthFirstPlanner = new DepthFirstPlanner();
|
||||
@Override
|
||||
public Optional<Set<Plan>> plan(Set<Formula> background, Set<Action> actions, State start, State goal) {
|
||||
return depthFirstPlanner.plan(background, actions, start, goal);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Set<Plan>> plan(PlanningProblem problem, Set<Formula> background, Set<Action> actions, State start, State goal) {
|
||||
|
||||
Optional<Context> contextOpt = problem.getContextOpt();
|
||||
|
||||
if(contextOpt.isPresent()){
|
||||
|
||||
|
||||
depthFirstPlanner.setWORK_FROM_SCRATCH(contextOpt.get().isWorkFromScratch());
|
||||
|
||||
|
||||
return depthFirstPlanner.plan(problem, background, actions, start, goal);
|
||||
|
||||
|
||||
} else{
|
||||
|
||||
return depthFirstPlanner.plan(problem, background, actions, start, goal);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
294
src/main/java/com/naveensundarg/planner/DepthFirstPlanner.java
Normal file
294
src/main/java/com/naveensundarg/planner/DepthFirstPlanner.java
Normal file
|
|
@ -0,0 +1,294 @@
|
|||
package com.naveensundarg.planner;
|
||||
|
||||
import com.naveensundarg.planner.utils.Commons;
|
||||
import com.naveensundarg.planner.utils.PlanningProblem;
|
||||
import com.naveensundarg.planner.utils.Visualizer;
|
||||
import com.naveensundarg.shadow.prover.core.proof.Justification;
|
||||
import com.naveensundarg.shadow.prover.representations.formula.Formula;
|
||||
import com.naveensundarg.shadow.prover.utils.CollectionUtils;
|
||||
import com.naveensundarg.shadow.prover.utils.Pair;
|
||||
import com.naveensundarg.shadow.prover.utils.Sets;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Created by naveensundarg on 1/13/17.
|
||||
*/
|
||||
public class DepthFirstPlanner implements Planner {
|
||||
|
||||
|
||||
private static int MAX_DEPTH = 5;
|
||||
private static boolean EXHAUSTIVE_TILL_MAX_DEPTH = true;
|
||||
|
||||
private boolean USE_METHODS, WORK_FROM_SCRATCH;
|
||||
|
||||
public DepthFirstPlanner(){
|
||||
USE_METHODS = true;
|
||||
WORK_FROM_SCRATCH = true;
|
||||
|
||||
}
|
||||
|
||||
public boolean isWORK_FROM_SCRATCH() {
|
||||
return WORK_FROM_SCRATCH;
|
||||
}
|
||||
|
||||
public void setWORK_FROM_SCRATCH(boolean WORK_FROM_SCRATCH) {
|
||||
this.WORK_FROM_SCRATCH = WORK_FROM_SCRATCH;
|
||||
}
|
||||
|
||||
public static int getMaxDepth() {
|
||||
return MAX_DEPTH;
|
||||
}
|
||||
|
||||
public static boolean isExhaustiveTillMaxDepth() {
|
||||
return EXHAUSTIVE_TILL_MAX_DEPTH;
|
||||
}
|
||||
|
||||
public static void setMaxDepth(int maxDepth) {
|
||||
MAX_DEPTH = maxDepth;
|
||||
}
|
||||
|
||||
public static void setExhaustiveTillMaxDepth(boolean exhaustiveTillMaxDepth) {
|
||||
EXHAUSTIVE_TILL_MAX_DEPTH = exhaustiveTillMaxDepth;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Set<Plan>> plan(Set<Formula> background, Set<Action> actions, State start, State goal) {
|
||||
|
||||
|
||||
if (!EXHAUSTIVE_TILL_MAX_DEPTH) {
|
||||
|
||||
return planInternal(Sets.newSet(), 0, MAX_DEPTH, background, actions, start, goal);
|
||||
|
||||
} else {
|
||||
|
||||
for (int i = 1; i <= MAX_DEPTH; i++) {
|
||||
|
||||
Optional<Set<Plan>> plans = planInternal(Sets.newSet(), 0, i, background, actions, start, goal);
|
||||
|
||||
if (plans.isPresent()) {
|
||||
return plans;
|
||||
}
|
||||
|
||||
}
|
||||
//
|
||||
return Optional.empty();
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Set<Plan>> plan(PlanningProblem problem, Set<Formula> background, Set<Action> actions, State start, State goal) {
|
||||
|
||||
if(USE_METHODS){
|
||||
|
||||
Optional<Set<Plan>> optionalPlansFromMethods = plan(problem, background, actions, start, goal, problem.getPlanMethods());
|
||||
|
||||
if(optionalPlansFromMethods.isPresent()){
|
||||
return optionalPlansFromMethods;
|
||||
}
|
||||
}
|
||||
|
||||
if(!WORK_FROM_SCRATCH){
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
|
||||
if (!EXHAUSTIVE_TILL_MAX_DEPTH) {
|
||||
|
||||
return planInternal(Sets.newSet(), 0, MAX_DEPTH, background, actions, start, goal);
|
||||
|
||||
} else {
|
||||
|
||||
Set<Plan> possiblePlans = Sets.newSet();
|
||||
for (int i = 1; i <= MAX_DEPTH; i++) {
|
||||
|
||||
Optional<Set<Plan>> plansOpt = planInternal(Sets.newSet(), 0, i, background, actions, start, goal);
|
||||
|
||||
if (plansOpt.isPresent()) {
|
||||
|
||||
Set<Plan> complyingPlans = plansOpt.get().stream().
|
||||
filter(plan-> plan.getActions().stream().
|
||||
map(Action::getShorthand).
|
||||
noneMatch(shortHand-> {
|
||||
|
||||
return problem.getAvoidIfPossible().
|
||||
stream().map(Object::toString).
|
||||
collect(Collectors.toSet()).
|
||||
contains(shortHand.getName());
|
||||
|
||||
})).
|
||||
collect(Collectors.toSet());
|
||||
|
||||
|
||||
if(!complyingPlans.isEmpty()){
|
||||
return Optional.of(complyingPlans);
|
||||
}
|
||||
else{
|
||||
|
||||
possiblePlans.addAll(plansOpt.get());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
//
|
||||
if(possiblePlans.isEmpty()){
|
||||
return Optional.empty();
|
||||
|
||||
} else{
|
||||
|
||||
return Optional.of(possiblePlans);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public Optional<Set<Plan>> plan(PlanningProblem problem, Set<Formula> background, Set<Action> actions, State start, State goal, List<PlanMethod> planMethods){
|
||||
|
||||
Set<Plan> plans = Sets.newSet();
|
||||
|
||||
Function<PlanSketch, Optional<Plan>> verifier = (planSketch) -> verify(background, start, goal, planSketch);
|
||||
|
||||
for (PlanMethod planMethod: planMethods){
|
||||
|
||||
Optional<List<PlanSketch>> optionalPlanSketches = planMethod.apply(background, start.getFormulae(), goal.getFormulae(), problem.getActions());
|
||||
|
||||
optionalPlanSketches.ifPresent(planSketches -> planSketches.forEach(planSketch -> verifier.apply(planSketch).ifPresent(plans::add)));
|
||||
|
||||
}
|
||||
|
||||
|
||||
if(!plans.isEmpty()){
|
||||
|
||||
return Optional.of(plans);
|
||||
|
||||
} else {
|
||||
|
||||
return Optional.empty();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public Optional<Plan> verify(Set<Formula> background, State start, State goal, PlanSketch planSketch){
|
||||
|
||||
List<Action> sketchActions = planSketch.getActions();
|
||||
List<State> expectedStates = CollectionUtils.newEmptyList();
|
||||
|
||||
Set<Formula> current = Sets.union(background, start.getFormulae());
|
||||
|
||||
expectedStates.add(State.initializeWith(current));
|
||||
for(Action action: sketchActions){
|
||||
|
||||
Set<Formula> preconditions = action.getPreconditions();
|
||||
Set<Formula> additions = action.getAdditions();
|
||||
Set<Formula> deletions = action.getDeletions();
|
||||
|
||||
Optional<Justification> optPrecond = Operations.proveCached(current, Commons.makeAnd(preconditions));
|
||||
|
||||
if(optPrecond.isPresent()){
|
||||
|
||||
current.addAll(additions);
|
||||
current.removeAll(deletions);
|
||||
expectedStates.add(State.initializeWith(current));
|
||||
|
||||
} else {
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
if(!Operations.proveCached(current, Commons.makeAnd(goal.getFormulae())).isPresent()){
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
return Optional.of(new Plan(sketchActions, expectedStates, background));
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
private Optional<Set<Plan>> planInternal(Set<Pair<State, Action>> history, int currentDepth, int maxDepth, Set<Formula> background, Set<Action> actions, State start, State goal) {
|
||||
|
||||
if (currentDepth >= maxDepth) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
if (Operations.satisfies(background, start, goal)) {
|
||||
//Already satisfied. Do nothing. Return a set with an empty plan.
|
||||
return Optional.of(Sets.with(Plan.newEmptyPlan(start, background)));
|
||||
}
|
||||
|
||||
|
||||
Set<Plan> allPlans = Sets.newSet();
|
||||
boolean atleastOnePlanFound = false;
|
||||
|
||||
for (Action action : actions.stream().filter(Action::isNonTrivial).collect(Collectors.toSet())) {
|
||||
|
||||
Optional<Set<Pair<State, Action>>> nextStateActionPairs = Operations.apply(background, action, start);
|
||||
|
||||
if (nextStateActionPairs.isPresent()) {
|
||||
|
||||
for (Pair<State, Action> stateActionPair : nextStateActionPairs.get()) {
|
||||
|
||||
Visualizer.push();
|
||||
Optional<Set<Plan>> planOpt = planInternal(history, currentDepth + 1, maxDepth, background, actions, stateActionPair.first(), goal);
|
||||
|
||||
Visualizer.pop();
|
||||
|
||||
if (planOpt.isPresent()) {
|
||||
|
||||
atleastOnePlanFound = true;
|
||||
Set<Plan> nextPlans = planOpt.get();
|
||||
|
||||
State nextSate = stateActionPair.first();
|
||||
Action instantiatedAction = stateActionPair.second();
|
||||
|
||||
Set<Plan> augmentedPlans = nextPlans.stream().
|
||||
map(plan -> plan.getPlanByStartingWith(instantiatedAction, nextSate)).
|
||||
collect(Collectors.toSet());
|
||||
|
||||
allPlans.addAll(augmentedPlans);
|
||||
|
||||
// return Optional.of(allPlans);
|
||||
|
||||
//TODO: store different plans and return the best plan.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
if (atleastOnePlanFound) {
|
||||
|
||||
return Optional.of(allPlans);
|
||||
|
||||
} else {
|
||||
|
||||
//No plan found.
|
||||
return Optional.empty();
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
96
src/main/java/com/naveensundarg/planner/Goal.java
Normal file
96
src/main/java/com/naveensundarg/planner/Goal.java
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
package com.naveensundarg.planner;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* Created by naveensundarg on 1/14/17.
|
||||
*/
|
||||
public class Goal {
|
||||
|
||||
private final State goalState;
|
||||
private final double priority;
|
||||
private final String name;
|
||||
private final String description;
|
||||
|
||||
|
||||
private static final AtomicInteger nameCounter;
|
||||
static {
|
||||
nameCounter = new AtomicInteger(0);
|
||||
}
|
||||
private Goal(State goalState, double priority) {
|
||||
this.goalState = goalState;
|
||||
this.priority = priority;
|
||||
this.name = "G" + nameCounter.incrementAndGet();
|
||||
this.description = goalState.toString();
|
||||
|
||||
}
|
||||
|
||||
private Goal(State goalState, double priority, String name) {
|
||||
this.goalState = goalState;
|
||||
this.priority = priority;
|
||||
this.name = name;
|
||||
this.description = goalState.toString();
|
||||
}
|
||||
|
||||
private Goal(State goalState, double priority, String name, String description) {
|
||||
this.goalState = goalState;
|
||||
this.priority = priority;
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
}
|
||||
public static Goal makeGoal(State goalState, double priority){
|
||||
|
||||
return new Goal(goalState, priority);
|
||||
|
||||
}
|
||||
|
||||
public static Goal makeGoal(State goalState, double priority, String name, String description){
|
||||
|
||||
return new Goal(goalState, priority, name, description);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public State getGoalState() {
|
||||
return goalState;
|
||||
}
|
||||
|
||||
public double getPriority() {
|
||||
return priority;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return "(" + name + ": " + description + ": " + priority+ ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
Goal goal = (Goal) o;
|
||||
|
||||
if (Double.compare(goal.priority, priority) != 0) return false;
|
||||
if (goalState != null ? !goalState.equals(goal.goalState) : goal.goalState != null) return false;
|
||||
return name != null ? name.equals(goal.name) : goal.name == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result;
|
||||
long temp;
|
||||
result = goalState != null ? goalState.hashCode() : 0;
|
||||
temp = Double.doubleToLongBits(priority);
|
||||
result = 31 * result + (int) (temp ^ (temp >>> 32));
|
||||
result = 31 * result + (name != null ? name.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
170
src/main/java/com/naveensundarg/planner/GoalTracker.java
Normal file
170
src/main/java/com/naveensundarg/planner/GoalTracker.java
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
package com.naveensundarg.planner;
|
||||
|
||||
import com.naveensundarg.planner.utils.PlanningProblem;
|
||||
import com.naveensundarg.shadow.prover.representations.formula.Formula;
|
||||
import com.naveensundarg.shadow.prover.utils.CollectionUtils;
|
||||
import com.naveensundarg.shadow.prover.utils.Sets;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Created by naveensundarg on 1/14/17.
|
||||
*/
|
||||
public class GoalTracker {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private final Set<Formula> background;
|
||||
private State currentState;
|
||||
private final Set<Goal> currentGoals;
|
||||
private final Planner planner;
|
||||
private final Set<Action> actions;
|
||||
private final PlanningProblem problem;
|
||||
public GoalTracker(PlanningProblem problem, Set<Formula> background, State startState, Set<Action> actions) {
|
||||
this.background = background;
|
||||
this.currentState = startState;
|
||||
this.currentGoals = CollectionUtils.newEmptySet();
|
||||
this.planner = new DepthFirstPlanner();
|
||||
this.actions = actions;
|
||||
|
||||
this.problem = problem;
|
||||
|
||||
Operations.reset();
|
||||
}
|
||||
|
||||
|
||||
public synchronized boolean deleteGoal(Goal goal){
|
||||
|
||||
return currentGoals.remove(goal);
|
||||
|
||||
}
|
||||
|
||||
public synchronized boolean addToBackground(Formula formula){
|
||||
|
||||
return background.add(formula);
|
||||
}
|
||||
|
||||
public synchronized boolean addAllToBackground(Set<Formula> formulae){
|
||||
|
||||
return background.addAll(formulae);
|
||||
}
|
||||
|
||||
public synchronized boolean deleteFromBackground(Formula formula){
|
||||
|
||||
return background.remove(formula);
|
||||
}
|
||||
|
||||
public synchronized boolean removeAllFromBackground(Set<Formula> formulae){
|
||||
|
||||
return background.removeAll(formulae);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public synchronized Optional<Plan> adoptGoal(Goal goal) {
|
||||
|
||||
|
||||
|
||||
Optional<Set<Plan>> possiblePlans = planner.plan(problem, background, actions, currentState, goal.getGoalState());
|
||||
|
||||
if (!possiblePlans.isPresent()) {
|
||||
|
||||
return Optional.empty();
|
||||
|
||||
} else if (possiblePlans.get().isEmpty()) {
|
||||
|
||||
throw new AssertionError("Unexpected condition: possible plans is empty");
|
||||
|
||||
} else {
|
||||
|
||||
Set<Plan> plans = possiblePlans.get();
|
||||
|
||||
Optional<Plan> possibleNoConflictPlan = plans.stream().filter(plan -> plan.noConflicts(currentGoals)).
|
||||
sorted(Comparator.comparing(plan->plan.getActions().size())).findAny();
|
||||
|
||||
|
||||
if (possibleNoConflictPlan.isPresent()) {
|
||||
|
||||
/*
|
||||
* If there is any plan without any goal conflicts, then adopt the goal.
|
||||
*/
|
||||
Plan noConflictPlan = possibleNoConflictPlan.get();
|
||||
currentGoals.add(goal);
|
||||
currentState = noConflictPlan.getExpectedStates().get(noConflictPlan.getExpectedStates().size()-1);
|
||||
return possibleNoConflictPlan;
|
||||
|
||||
} else {
|
||||
|
||||
/*
|
||||
* Find goals to drop.
|
||||
* For each plan, find the sum of the priorities of the goals that conflict.
|
||||
* If any plan exists, where sum of priorities of existing goals is less than the new goal,
|
||||
* add the new goal and remove the conflict goals.
|
||||
* Otherwise return false and don't adopt the new goal.
|
||||
*/
|
||||
|
||||
boolean feasiblePlanExists = false;
|
||||
int bestPlanSize = Integer.MAX_VALUE;
|
||||
double bestPriorityGap = 0;
|
||||
Set<Goal> bestRemovalCandidates = null;
|
||||
Set<Plan> feasiblePlans = Sets.newSet();
|
||||
for (Plan plan : plans) {
|
||||
|
||||
Set<Goal> conflictingGoals = plan.getConflictingGoals(currentGoals);
|
||||
double conflictSum = conflictingGoals.stream().mapToDouble(Goal::getPriority).sum();
|
||||
double gap = goal.getPriority() - conflictSum;
|
||||
|
||||
if(gap > 0 && gap >= bestPriorityGap && plan.getActions().size() <= bestPlanSize){
|
||||
|
||||
feasiblePlanExists = true;
|
||||
bestPriorityGap = gap;
|
||||
bestPlanSize = plan.getActions().size();
|
||||
feasiblePlans.add(plan);
|
||||
bestRemovalCandidates= conflictingGoals;
|
||||
}
|
||||
}
|
||||
|
||||
if(!feasiblePlans.isEmpty()){
|
||||
|
||||
Plan bestPlan = feasiblePlans.stream().
|
||||
min(Comparator.comparing(plan->plan.getActions().stream().mapToInt(Action::getWeight).sum())).get();
|
||||
currentGoals.removeAll(bestRemovalCandidates);
|
||||
currentGoals.add(goal);
|
||||
currentState = bestPlan.getExpectedStates().get(bestPlan.getExpectedStates().size()-1);
|
||||
|
||||
return Optional.of(bestPlan);
|
||||
}
|
||||
else {
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public Set<Formula> getBackground() {
|
||||
return background;
|
||||
}
|
||||
|
||||
public State getCurrentState() {
|
||||
return currentState;
|
||||
}
|
||||
|
||||
public PlanningProblem getProblem() {
|
||||
return problem;
|
||||
}
|
||||
|
||||
public Set<Goal> getCurrentGoals() {
|
||||
return currentGoals;
|
||||
}
|
||||
}
|
||||
12
src/main/java/com/naveensundarg/planner/Inducer.java
Normal file
12
src/main/java/com/naveensundarg/planner/Inducer.java
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
package com.naveensundarg.planner;
|
||||
|
||||
import com.naveensundarg.planner.utils.PlanningProblem;
|
||||
|
||||
/**
|
||||
* Created by naveensundarg on 12/19/17.
|
||||
*/
|
||||
public interface Inducer {
|
||||
|
||||
PlanMethod induce(PlanningProblem planningProblem, State start, Goal goal, Plan plan);
|
||||
|
||||
}
|
||||
319
src/main/java/com/naveensundarg/planner/Operations.java
Normal file
319
src/main/java/com/naveensundarg/planner/Operations.java
Normal file
|
|
@ -0,0 +1,319 @@
|
|||
package com.naveensundarg.planner;
|
||||
|
||||
import com.naveensundarg.planner.utils.Visualizer;
|
||||
import com.naveensundarg.shadow.prover.core.Prover;
|
||||
import com.naveensundarg.shadow.prover.core.SnarkWrapper;
|
||||
import com.naveensundarg.shadow.prover.core.proof.Justification;
|
||||
import com.naveensundarg.shadow.prover.representations.formula.BiConditional;
|
||||
import com.naveensundarg.shadow.prover.representations.formula.Formula;
|
||||
import com.naveensundarg.shadow.prover.representations.formula.Predicate;
|
||||
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.ImmutablePair;
|
||||
import com.naveensundarg.shadow.prover.utils.Pair;
|
||||
|
||||
import com.naveensundarg.shadow.prover.utils.Sets;
|
||||
import org.apache.commons.lang3.tuple.Triple;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Created by naveensundarg on 1/13/17.
|
||||
*/
|
||||
public class Operations {
|
||||
|
||||
private static boolean DEEP_EQUIVALENCE = false;
|
||||
private static boolean THROW_AWAY_EMPTY_BINDINGS = true;
|
||||
private static Prover prover;
|
||||
|
||||
|
||||
private static final Map<Pair<Set<Formula>, Formula>, Optional<Justification>> proverCache = CollectionUtils.newMap();
|
||||
private static final Map<Triple<Set<Formula>, Formula, List<Variable>>, Optional<Set<Map<Variable, Value>>>> proverBindingsCache = CollectionUtils.newMap();
|
||||
private static final Map<Triple<Set<Formula>, Action, State>, Optional<Set<Pair<State, Action>>> > applyCache = CollectionUtils.newMap();
|
||||
|
||||
|
||||
public static void reset(){
|
||||
|
||||
proverCache.clear();
|
||||
proverBindingsCache.clear();
|
||||
applyCache.clear();
|
||||
}
|
||||
static {
|
||||
prover = SnarkWrapper.getInstance();
|
||||
|
||||
|
||||
}
|
||||
|
||||
public static synchronized Optional<Justification> proveCached(Set<Formula> assumptions, Formula goal) {
|
||||
|
||||
Pair<Set<Formula>, Formula> inputPair = ImmutablePair.from(assumptions, goal);
|
||||
|
||||
if (proverCache.containsKey(inputPair)) {
|
||||
|
||||
return proverCache.get(inputPair);
|
||||
|
||||
}
|
||||
|
||||
Optional<Map.Entry<Pair<Set<Formula>, Formula>, Optional<Justification>>> cachedOptionalSuccessful = proverCache.entrySet().stream().filter(pairOptionalEntry -> {
|
||||
|
||||
Set<Formula> cachedAssumptions = pairOptionalEntry.getKey().first();
|
||||
Formula cachedGoal = pairOptionalEntry.getKey().second();
|
||||
|
||||
return cachedGoal.equals(goal) && Sets.subset(cachedAssumptions, assumptions);
|
||||
}).findAny();
|
||||
|
||||
|
||||
if(cachedOptionalSuccessful.isPresent() && cachedOptionalSuccessful.get().getValue().isPresent()){
|
||||
|
||||
return cachedOptionalSuccessful.get().getValue();
|
||||
}
|
||||
|
||||
|
||||
Optional<Map.Entry<Pair<Set<Formula>, Formula>, Optional<Justification>>> cachedOptionalFailed = proverCache.entrySet().stream().filter(pairOptionalEntry -> {
|
||||
|
||||
Set<Formula> cachedAssumptions = pairOptionalEntry.getKey().first();
|
||||
Formula cachedGoal = pairOptionalEntry.getKey().second();
|
||||
|
||||
return cachedGoal.equals(goal) && Sets.subset(assumptions, cachedAssumptions);
|
||||
}).findAny();
|
||||
|
||||
|
||||
if(cachedOptionalFailed.isPresent() && !cachedOptionalFailed.get().getValue().isPresent()){
|
||||
|
||||
return cachedOptionalFailed.get().getValue();
|
||||
}
|
||||
|
||||
if(goal instanceof Predicate && ((Predicate) goal).getName().equals("sameroom")){
|
||||
|
||||
Predicate p = (Predicate) goal;
|
||||
|
||||
Value v1 = p.getArguments()[0];
|
||||
Value v2 = p.getArguments()[1];
|
||||
|
||||
Optional<Formula> inOptv1 = assumptions.stream().filter(x-> x instanceof Predicate &&
|
||||
((Predicate)x).getName().equals("in") && ((Predicate) x).getArguments()[0].equals(v1)).findAny();
|
||||
|
||||
Optional<Formula> inOptv2 = assumptions.stream().filter(x-> x instanceof Predicate &&
|
||||
((Predicate)x).getName().equals("in") && ((Predicate) x).getArguments()[0].equals(v2)).findAny();
|
||||
|
||||
|
||||
if(inOptv1.isPresent() && inOptv2.isPresent()){
|
||||
|
||||
Value room1 = ((Predicate)inOptv1.get()).getArguments()[1];
|
||||
Value room2 = ((Predicate)inOptv2.get()).getArguments()[1];
|
||||
|
||||
if(room1.equals(room2)){
|
||||
|
||||
return Optional.of(Justification.trivial(assumptions, goal));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
Optional<Justification> answer = prover.prove(assumptions, goal);
|
||||
|
||||
proverCache.put(inputPair, answer);
|
||||
|
||||
return answer;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static synchronized Optional<Set<Map<Variable, Value>>> proveAndGetBindingsCached(Set<Formula> givens, Formula goal, List<Variable> variables) {
|
||||
|
||||
|
||||
Triple<Set<Formula>, Formula, List<Variable>> inputTriple = Triple.of(givens, goal, variables);
|
||||
|
||||
if (proverBindingsCache.containsKey(inputTriple)) {
|
||||
|
||||
return proverBindingsCache.get(inputTriple);
|
||||
|
||||
} else {
|
||||
|
||||
Optional<Set<Map<Variable, Value>>> answer = proveAndGetMultipleBindings(givens, goal, variables);
|
||||
|
||||
proverBindingsCache.put(inputTriple, answer);
|
||||
|
||||
return answer;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static synchronized Optional<Map<Variable, Value>> proveAndGetBindings(Set<Formula> givens, Formula goal, List<Variable> variables) {
|
||||
|
||||
Future<Optional<Map<Variable, Value>>> future = new FutureTask<>(() -> {
|
||||
return prover.proveAndGetBindings(givens, goal, variables);
|
||||
|
||||
|
||||
});
|
||||
|
||||
Optional<Map<Variable, Value>> answer;
|
||||
|
||||
try {
|
||||
|
||||
answer = future.get(1, TimeUnit.SECONDS);
|
||||
} catch (InterruptedException | ExecutionException | TimeoutException e) {
|
||||
answer = Optional.empty();
|
||||
}
|
||||
|
||||
return answer;
|
||||
}
|
||||
|
||||
|
||||
public static synchronized Optional<Set<Map<Variable, Value>>> proveAndGetMultipleBindings(Set<Formula> givens, Formula goal, List<Variable> variables) {
|
||||
|
||||
Optional<org.apache.commons.lang3.tuple.Pair<Justification, Set<Map<Variable, Value>>>> ans = prover.proveAndGetMultipleBindings(givens, goal, variables);
|
||||
|
||||
if(ans.isPresent()){
|
||||
|
||||
return Optional.of(ans.get().getRight());
|
||||
|
||||
}else {
|
||||
return Optional.empty();
|
||||
}
|
||||
/* Future<Optional<Set<Map<Variable, Value>>>> future = new FutureTask<>(()-> prover.proveAndGetMultipleBindings(givens, goal, variables));
|
||||
|
||||
Optional<Set<Map<Variable, Value>>> answer;
|
||||
|
||||
try{
|
||||
|
||||
answer = future.get(50, TimeUnit.SECONDS);
|
||||
} catch (InterruptedException | ExecutionException | TimeoutException e ) {
|
||||
answer = Optional.empty();
|
||||
}
|
||||
return answer;
|
||||
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
public static Optional<Set<Pair<State, Action>>> apply(Set<Formula> background, Action action, State state) {
|
||||
|
||||
|
||||
if(applyCache.containsKey(Triple.of(background, action, state))){
|
||||
|
||||
Optional<Set<Pair<State, Action>>> ans = applyCache.get(Triple.of(background, action, state));
|
||||
if(ans.isPresent()){
|
||||
return applyCache.get(Triple.of(background, action, state));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Set<Formula> givens = Sets.union(background, state.getFormulae());
|
||||
|
||||
Optional<Set<Map<Variable, Value>>> bindingsOpt = proveAndGetBindingsCached(givens, action.getPrecondition(), action.openVars());
|
||||
|
||||
State newState;
|
||||
|
||||
if (!bindingsOpt.isPresent()) {
|
||||
|
||||
|
||||
|
||||
applyCache.put(Triple.of(background, action ,state), Optional.empty());
|
||||
return Optional.empty();
|
||||
|
||||
}
|
||||
|
||||
Visualizer.nested(action.getName());
|
||||
|
||||
Set<Pair<State, Action>> nexts = Sets.newSet();
|
||||
for (Map<Variable, Value> binding : bindingsOpt.get()) {
|
||||
|
||||
if (THROW_AWAY_EMPTY_BINDINGS && binding.values().stream().anyMatch(x -> x instanceof Variable)) {
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
Set<Formula> instantiatedDeletions = action.instantiateDeletions(binding);
|
||||
|
||||
Set<Formula> formulaeToRemove = state.getFormulae().stream().
|
||||
filter(f -> instantiatedDeletions.stream().anyMatch(d -> equivalent(Sets.union(background, state.getFormulae()), f, d))).collect(Collectors.toSet());
|
||||
|
||||
Set<Formula> newFormulae = Sets.union(background, state.getFormulae());
|
||||
|
||||
newFormulae = Sets.union(newFormulae, action.instantiateAdditions(binding));
|
||||
|
||||
|
||||
newFormulae = Sets.difference(newFormulae, formulaeToRemove);
|
||||
|
||||
|
||||
newState = State.initializeWith(newFormulae);
|
||||
|
||||
nexts.add(ImmutablePair.from(newState, action.instantiate(binding)));
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (nexts.isEmpty()) {
|
||||
|
||||
Map<Variable, Value> emptyBinding = CollectionUtils.newMap();
|
||||
Set<Formula> instantiatedDeletions = action.instantiateDeletions(emptyBinding);
|
||||
|
||||
Set<Formula> formulaeToRemove = state.getFormulae().stream().
|
||||
filter(f -> instantiatedDeletions.stream().anyMatch(d -> equivalent(background, f, d))).collect(Collectors.toSet());
|
||||
|
||||
Set<Formula> newFormulae = state.getFormulae();
|
||||
|
||||
newFormulae = Sets.union(newFormulae, action.instantiateAdditions(emptyBinding));
|
||||
|
||||
|
||||
newFormulae = Sets.difference(newFormulae, formulaeToRemove);
|
||||
|
||||
|
||||
newState = State.initializeWith(newFormulae);
|
||||
|
||||
nexts.add(ImmutablePair.from(newState, action.instantiate(emptyBinding)));
|
||||
|
||||
|
||||
}
|
||||
|
||||
nexts = nexts.stream().filter(n-> !n.first().getFormulae().equals(state.getFormulae())).collect(Collectors.toSet());;
|
||||
|
||||
|
||||
|
||||
applyCache.put(Triple.of(background, action ,state), Optional.of(nexts));
|
||||
|
||||
return Optional.of(nexts);
|
||||
|
||||
}
|
||||
|
||||
public static boolean equivalent(Set<Formula> background, Formula f1, Formula f2) {
|
||||
|
||||
if (!DEEP_EQUIVALENCE) {
|
||||
return f1.equals(f2);
|
||||
}
|
||||
|
||||
BiConditional biConditional = new BiConditional(f1, f2);
|
||||
return proveCached(background, biConditional).isPresent();
|
||||
}
|
||||
|
||||
public static boolean satisfies(Set<Formula> background, State state, State goal) {
|
||||
|
||||
if ((Sets.union(background, state.getFormulae()).containsAll(goal.getFormulae()))) {
|
||||
|
||||
return true;
|
||||
}
|
||||
return goal.getFormulae().stream().
|
||||
allMatch(x -> proveCached(Sets.union(background, state.getFormulae()), x).isPresent());
|
||||
|
||||
}
|
||||
|
||||
public static boolean conflicts(Set<Formula> background, State state1, State state2) {
|
||||
|
||||
|
||||
return proveCached(Sets.union(background, Sets.union(state1.getFormulae(), state2.getFormulae())), State.FALSE).isPresent();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
109
src/main/java/com/naveensundarg/planner/Plan.java
Normal file
109
src/main/java/com/naveensundarg/planner/Plan.java
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
package com.naveensundarg.planner;
|
||||
|
||||
import com.naveensundarg.planner.utils.Visualizer;
|
||||
import com.naveensundarg.shadow.prover.representations.formula.Formula;
|
||||
import com.naveensundarg.shadow.prover.utils.CollectionUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Created by naveensundarg on 1/14/17.
|
||||
*/
|
||||
public class Plan {
|
||||
|
||||
private final List<Action> actions;
|
||||
private final List<State> expectedStates;
|
||||
private final Set<Formula> background;
|
||||
public static Plan newEmptyPlan(State currentState, Set<Formula> background){
|
||||
List<Action> newActions = CollectionUtils.newEmptyList();
|
||||
List<State> newExpectedStates = CollectionUtils.listOf(currentState);
|
||||
return new Plan(newActions, newExpectedStates, background);
|
||||
}
|
||||
|
||||
public Plan(List<Action> actions, List<State> expectedStates, Set<Formula> background) {
|
||||
this.actions = actions;
|
||||
this.expectedStates = expectedStates;
|
||||
this.background = background;
|
||||
}
|
||||
|
||||
public List<Action> getActions() {
|
||||
return actions;
|
||||
}
|
||||
|
||||
public List<State> getExpectedStates() {
|
||||
return expectedStates;
|
||||
}
|
||||
|
||||
public Plan getPlanByStartingWith(Action action, State state){
|
||||
List<Action> newActions = CollectionUtils.newEmptyList();
|
||||
newActions.addAll(actions);
|
||||
newActions.add(0, action);
|
||||
|
||||
List<State> newExpectedStates = CollectionUtils.newEmptyList();
|
||||
newExpectedStates.addAll(expectedStates);
|
||||
newExpectedStates.add(0, state);
|
||||
|
||||
return new Plan(newActions, newExpectedStates, background);
|
||||
}
|
||||
|
||||
public boolean conflictsWith(Goal goal){
|
||||
|
||||
return expectedStates.stream().anyMatch(state-> Operations.conflicts(background, state,goal.getGoalState()));
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public Set<Goal> getConflictingGoals(Set<Goal> goals){
|
||||
|
||||
return goals.stream().filter(this::conflictsWith).collect(Collectors.toSet());
|
||||
|
||||
}
|
||||
|
||||
public boolean noConflicts(Set<Goal> goals){
|
||||
|
||||
Set<Goal> conflicts = getConflictingGoals(goals);
|
||||
|
||||
if(!conflicts.isEmpty()){
|
||||
|
||||
Visualizer.print(this.toString()) ;
|
||||
Visualizer.printRed(" CONFLICTS WITH ");
|
||||
Visualizer.print(conflicts.stream().map(x-> x.getDescription()).collect(Collectors.toSet()).toString());
|
||||
System.out.println();
|
||||
|
||||
}
|
||||
|
||||
return conflicts.isEmpty();
|
||||
|
||||
}
|
||||
|
||||
public static Plan cleanUp(Plan plan){
|
||||
|
||||
List<Action> actions = plan.getActions();
|
||||
List<State> states = plan.getExpectedStates();
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return actions.stream().map(x-> x.toString() + " ").reduce((x,y) -> x + y).get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
Plan plan = (Plan) o;
|
||||
|
||||
return actions != null ? actions.equals(plan.actions) : plan.actions == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return actions != null ? actions.hashCode() : 0;
|
||||
}
|
||||
}
|
||||
121
src/main/java/com/naveensundarg/planner/PlanMethod.java
Normal file
121
src/main/java/com/naveensundarg/planner/PlanMethod.java
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
package com.naveensundarg.planner;
|
||||
|
||||
import com.naveensundarg.planner.utils.PlanningProblem;
|
||||
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;
|
||||
import com.naveensundarg.shadow.prover.utils.Reader;
|
||||
import com.naveensundarg.shadow.prover.utils.Sets;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Created by naveensundarg on 12/22/17.
|
||||
*/
|
||||
public class PlanMethod {
|
||||
|
||||
private final Set<Formula> backGroundStatePreconditions;
|
||||
private final Set<Formula> goalPreconditions;
|
||||
private final List<Variable> freeVariables;
|
||||
private final List<Compound> actionCompounds;
|
||||
|
||||
|
||||
|
||||
public PlanMethod(Set<Formula> goalPreconditions, Set<Formula> backGroundStatePreconditions, List<Variable> freeVariables, List<Compound> actionCompounds) {
|
||||
this.goalPreconditions = goalPreconditions;
|
||||
this.backGroundStatePreconditions = backGroundStatePreconditions;
|
||||
this.freeVariables = freeVariables;
|
||||
this.actionCompounds = actionCompounds;
|
||||
|
||||
}
|
||||
|
||||
|
||||
public PlanMethod(Set<Formula> goalPreconditions, List<Variable> freeVariables, List<Compound> actionCompounds) {
|
||||
this.goalPreconditions = goalPreconditions;
|
||||
this.backGroundStatePreconditions = Sets.newSet();
|
||||
this.freeVariables = freeVariables;
|
||||
this.actionCompounds = actionCompounds;
|
||||
|
||||
}
|
||||
|
||||
|
||||
public Optional<List<PlanSketch>> apply(Set<Formula> background, Set<Formula> start, Set<Formula> goal, Set<Action> actionSpecs) {
|
||||
|
||||
|
||||
Optional<Set<Map<Variable, Value>>> mappingsOpt = Operations.proveAndGetMultipleBindings(goal, new And(new ArrayList<>(goalPreconditions)), freeVariables);
|
||||
|
||||
if (mappingsOpt.isPresent()) {
|
||||
|
||||
Set<Map<Variable, Value>> mappings = mappingsOpt.get();
|
||||
|
||||
List<PlanSketch> planSketches = CollectionUtils.newEmptyList();
|
||||
|
||||
|
||||
mappings.forEach(mapping ->{
|
||||
|
||||
Formula whileCondition = (new And(new ArrayList<>(backGroundStatePreconditions))).apply(mapping);
|
||||
|
||||
boolean whileHolds = Operations.proveCached(Sets.union(background, start), whileCondition).isPresent();
|
||||
|
||||
|
||||
if(whileHolds){
|
||||
|
||||
List<Compound> instantiatedActionCompounds = actionCompounds.stream().map(compound -> (Compound) compound.apply(mapping)).collect(Collectors.toList());
|
||||
|
||||
|
||||
List<Action> actions = CollectionUtils.newEmptyList();
|
||||
|
||||
for (Compound compound : instantiatedActionCompounds) {
|
||||
|
||||
|
||||
try {
|
||||
|
||||
actions.add(PlanningProblem.readInstantiatedAction(actionSpecs, compound.toString()));
|
||||
|
||||
} catch (Reader.ParsingException e) {
|
||||
|
||||
e.printStackTrace();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
planSketches.add(new PlanSketch(actions, background));
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
return Optional.of(planSketches);
|
||||
|
||||
} else {
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/* (define-method planMethod [?b ?c ?d]
|
||||
{:goal [(In ?b ?c) (In ?c ?d)]
|
||||
:while [(In ?b ?d) (Empty ?c)
|
||||
(< (size ?c) (size ?d))
|
||||
(< (size ?b) (size ?c))]
|
||||
:actions [(removeFrom ?b ?d) (placeInside ?b ?c) (placeInside ?c ?d)]})
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "(define-method planMethod " + freeVariables.toString().replace(",", " ") + "\n" +
|
||||
"\t{:goal " + goalPreconditions.toString().replace(",", " ") + "\n" +
|
||||
"\t:while " + backGroundStatePreconditions.toString().replace(",", " ") + "\n" +
|
||||
"\t:actions " + actionCompounds.toString().replace(",", " ") + "})";
|
||||
}
|
||||
}
|
||||
13
src/main/java/com/naveensundarg/planner/PlanSketch.java
Normal file
13
src/main/java/com/naveensundarg/planner/PlanSketch.java
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
package com.naveensundarg.planner;
|
||||
|
||||
import com.naveensundarg.shadow.prover.representations.formula.Formula;
|
||||
import com.naveensundarg.shadow.prover.utils.CollectionUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class PlanSketch extends Plan{
|
||||
public PlanSketch(List<Action> actions, Set<Formula> background) {
|
||||
super(actions, CollectionUtils.newEmptyList(), background);
|
||||
}
|
||||
}
|
||||
20
src/main/java/com/naveensundarg/planner/Planner.java
Normal file
20
src/main/java/com/naveensundarg/planner/Planner.java
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
package com.naveensundarg.planner;
|
||||
|
||||
import com.naveensundarg.planner.utils.PlanningProblem;
|
||||
import com.naveensundarg.shadow.prover.representations.formula.Formula;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Created by naveensundarg on 1/13/17.
|
||||
*/
|
||||
public interface Planner {
|
||||
|
||||
Optional<Set<Plan>> plan(Set<Formula> background, Set<Action> actions, State start, State goal);
|
||||
Optional<Set<Plan>> plan(PlanningProblem problem, Set<Formula> background, Set<Action> actions, State start, State goal);
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
80
src/main/java/com/naveensundarg/planner/State.java
Normal file
80
src/main/java/com/naveensundarg/planner/State.java
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
package com.naveensundarg.planner;
|
||||
|
||||
import com.naveensundarg.shadow.prover.core.Prover;
|
||||
import com.naveensundarg.shadow.prover.core.SnarkWrapper;
|
||||
import com.naveensundarg.shadow.prover.representations.formula.Formula;
|
||||
import com.naveensundarg.shadow.prover.utils.CollectionUtils;
|
||||
import com.naveensundarg.shadow.prover.utils.Reader;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Created by naveensundarg on 1/13/17.
|
||||
*/
|
||||
public class State {
|
||||
|
||||
final Set<Formula> formulae;
|
||||
private static final Prover prover = SnarkWrapper.getInstance();
|
||||
static Formula FALSE;
|
||||
|
||||
static{
|
||||
|
||||
try {
|
||||
FALSE = Reader.readFormulaFromString("(and P (not P))");
|
||||
} catch (Reader.ParsingException e) {
|
||||
e.printStackTrace();
|
||||
FALSE = null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private State(Set<Formula> formulae){
|
||||
|
||||
this.formulae = formulae;
|
||||
}
|
||||
|
||||
public static State initializeWith(Set<Formula> formulae){
|
||||
|
||||
State newState = new State(formulae);
|
||||
return newState;
|
||||
}
|
||||
|
||||
|
||||
public void add(Set<Formula> formulae){
|
||||
|
||||
this.formulae.addAll(formulae);
|
||||
}
|
||||
|
||||
public void remove(Set<Formula> formulae){
|
||||
|
||||
this.formulae.removeAll(formulae);
|
||||
|
||||
}
|
||||
|
||||
public Set<Formula> getFormulae() {
|
||||
return CollectionUtils.setFrom(formulae);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "State{" +
|
||||
"formulae=" + formulae +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
State state = (State) o;
|
||||
|
||||
return formulae.equals(state.formulae);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return formulae.hashCode();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
package com.naveensundarg.planner.inducers;
|
||||
|
||||
import com.naveensundarg.planner.*;
|
||||
import com.naveensundarg.planner.utils.Commons;
|
||||
import com.naveensundarg.planner.utils.PlanningProblem;
|
||||
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.Sets;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Created by naveensundarg on 12/19/17.
|
||||
*/
|
||||
|
||||
public class SimpleInducer implements Inducer {
|
||||
|
||||
@Override
|
||||
public PlanMethod induce(PlanningProblem planningProblem, State start, Goal goal, Plan plan) {
|
||||
|
||||
|
||||
List<Action> actionList = plan.getActions();
|
||||
List<Compound> actionCompounds = actionList.stream().map(Action::getShorthand).collect(Collectors.toList());
|
||||
|
||||
|
||||
Set<Formula> backgroundFormula = planningProblem.getBackground().stream().collect(Collectors.toSet());
|
||||
Set<Formula> initFormula = start.getFormulae().stream().collect(Collectors.toSet());
|
||||
Set<Formula> goalFormula = goal.getGoalState().getFormulae().stream().collect(Collectors.toSet());
|
||||
|
||||
Set<Value> values = actionCompounds.stream().
|
||||
map(Compound::getArguments).map(Arrays::stream).map(x->x.collect(Collectors.toSet()))
|
||||
.reduce(Sets.newSet(), Sets::union)
|
||||
.stream().filter(Value::isConstant).collect(Collectors.toSet());
|
||||
|
||||
|
||||
Map<Value, Variable> valueVariableMap = Commons.makeVariables(values);
|
||||
|
||||
Function<Set<Formula>,Set<Formula>> getRelevantFormula = formulae -> {
|
||||
|
||||
return formulae.stream().
|
||||
filter(formula -> Sets.difference(formula.valuesPresent().stream().filter(Value::isConstant).collect(Collectors.toSet()),
|
||||
values).isEmpty() &&
|
||||
!Sets.intersection(values, formula.valuesPresent()).isEmpty()).
|
||||
collect(Collectors.toSet());
|
||||
};
|
||||
|
||||
Set<Formula> relevantBackgroundFormula = getRelevantFormula.apply(backgroundFormula);
|
||||
Set<Formula> relevantInitFormula = getRelevantFormula.apply(initFormula);
|
||||
Set<Formula> relevantGoalFormula = getRelevantFormula.apply(goalFormula);
|
||||
|
||||
|
||||
Commons.generalize(valueVariableMap, relevantBackgroundFormula);
|
||||
Commons.generalize(valueVariableMap, relevantInitFormula);
|
||||
Commons.generalize(valueVariableMap, relevantGoalFormula);
|
||||
|
||||
System.out.println(relevantBackgroundFormula);
|
||||
System.out.println(relevantInitFormula);
|
||||
System.out.println(relevantGoalFormula);
|
||||
|
||||
//PlanMethod(Set<Formula> goalPreconditions, Set<Formula> backGroundStatePreconditions, List<Variable> freeVariables, List<Compound> actionCompounds
|
||||
|
||||
|
||||
return new PlanMethod(Commons.generalize(valueVariableMap, relevantGoalFormula),
|
||||
Sets.union(Commons.generalize(valueVariableMap, relevantBackgroundFormula),
|
||||
Commons.generalize(valueVariableMap, relevantInitFormula)),
|
||||
new ArrayList<>(valueVariableMap.values()), actionCompounds.stream().map(x-> (Compound) x.generalize(valueVariableMap)).
|
||||
collect(Collectors.toList()));
|
||||
|
||||
}
|
||||
}
|
||||
107
src/main/java/com/naveensundarg/planner/utils/Commons.java
Normal file
107
src/main/java/com/naveensundarg/planner/utils/Commons.java
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
package com.naveensundarg.planner.utils;
|
||||
|
||||
import com.diogonunes.jcdp.color.ColoredPrinter;
|
||||
import com.diogonunes.jcdp.color.api.Ansi;
|
||||
import com.naveensundarg.shadow.prover.representations.formula.And;
|
||||
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 java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Created by naveensundarg on 1/15/17.
|
||||
*/
|
||||
public class Commons {
|
||||
|
||||
|
||||
public static Map<Value, Variable> makeVariables(Set<Value> values){
|
||||
|
||||
|
||||
return makeVariables(values, 1);
|
||||
|
||||
}
|
||||
|
||||
public static Map<Value, Variable> makeVariables(Set<Value> values, int startValue){
|
||||
int n = startValue;
|
||||
|
||||
Map<Value, Variable> valueVariableMap = CollectionUtils.newMap();
|
||||
|
||||
for(Value value: values){
|
||||
|
||||
Variable variable = new Variable("?" +value);
|
||||
valueVariableMap.put(value, variable);
|
||||
n = n +1;
|
||||
|
||||
|
||||
}
|
||||
|
||||
return valueVariableMap;
|
||||
}
|
||||
|
||||
public static Set<Formula> generalize(Map<Value, Variable> universalValueVariableMap, Set<Formula> formulae){
|
||||
|
||||
|
||||
return formulae.stream().map(x->x.generalize(universalValueVariableMap)).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
public static <U, V> Map<V, U> reverse(Map<U, V> map){
|
||||
|
||||
Map<V, U> reverseMap = CollectionUtils.newMap();
|
||||
|
||||
map.forEach((u, v) -> reverseMap.put(v, u));
|
||||
|
||||
return reverseMap;
|
||||
}
|
||||
|
||||
public static <U, V> Map<U, V> combine(Map<U, V> map1, Map<U, V> map2){
|
||||
|
||||
Map<U, V> combinedMap = CollectionUtils.newMap();
|
||||
|
||||
map1.forEach(combinedMap::put);
|
||||
map2.forEach(combinedMap::put);
|
||||
|
||||
return combinedMap;
|
||||
}
|
||||
|
||||
static ColoredPrinter cp = new ColoredPrinter.Builder(1, false).build();
|
||||
|
||||
public static<U, V, W> Object runAndTime(BiFunction<U, V, W> function, U u, V v, String message){
|
||||
|
||||
cp.setAttribute(Ansi.Attribute.BOLD);
|
||||
|
||||
long start, end;
|
||||
|
||||
start = System.currentTimeMillis();
|
||||
|
||||
Object w = function.apply(u, v);
|
||||
|
||||
end = System.currentTimeMillis();
|
||||
|
||||
|
||||
cp.println("Timing for: " + message + (end - start)/1000 + " s");
|
||||
|
||||
if(w!=null){
|
||||
cp.println(w);
|
||||
|
||||
} else {
|
||||
|
||||
cp.setForegroundColor(Ansi.FColor.RED);
|
||||
cp.println("COULD NOT PLAN");
|
||||
}
|
||||
|
||||
cp.clear();
|
||||
return w;
|
||||
}
|
||||
|
||||
public static And makeAnd(Set<Formula> formulae){
|
||||
|
||||
return new And(new ArrayList<>(formulae));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package com.naveensundarg.planner.utils;
|
||||
|
||||
import com.diogonunes.jcdp.color.ColoredPrinter;
|
||||
import com.diogonunes.jcdp.color.api.AbstractColoredPrinter;
|
||||
|
||||
/**
|
||||
* Created by naveensundarg on 9/29/17.
|
||||
*/
|
||||
public class FrozenPrinter extends ColoredPrinter {
|
||||
|
||||
|
||||
public FrozenPrinter(Builder b) {
|
||||
super(b);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
package com.naveensundarg.planner.utils;
|
||||
|
||||
import com.naveensundarg.shadow.prover.representations.formula.Formula;
|
||||
import com.naveensundarg.shadow.prover.utils.CollectionUtils;
|
||||
import com.naveensundarg.shadow.prover.utils.Reader;
|
||||
import com.naveensundarg.planner.Goal;
|
||||
import com.naveensundarg.planner.PlanMethod;
|
||||
import com.naveensundarg.planner.State;
|
||||
import us.bpsm.edn.Keyword;
|
||||
import us.bpsm.edn.parser.Parseable;
|
||||
import us.bpsm.edn.parser.Parser;
|
||||
import us.bpsm.edn.parser.Parsers;
|
||||
import us.bpsm.edn.parser.Token;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.*;
|
||||
|
||||
import static com.naveensundarg.planner.utils.Reader.readPlanMethodsFrom;
|
||||
|
||||
/**
|
||||
* Created by naveensundarg on 1/13/17.
|
||||
*/
|
||||
public class GoalTrackingProblem {
|
||||
|
||||
private final PlanningProblem planningProblem;
|
||||
private final Set<Goal> goals;
|
||||
private final Map<String, Goal> goalNameMap;
|
||||
|
||||
private static final Keyword DEFINITIONS = Keyword.newKeyword("definitions");
|
||||
private static final Keyword GOALS = Keyword.newKeyword("goals");
|
||||
private static final Keyword DESCRIPTION = Keyword.newKeyword("description");
|
||||
|
||||
private static final Keyword PRIORITY = Keyword.newKeyword("priority");
|
||||
private static final Keyword STATE = Keyword.newKeyword("state");
|
||||
|
||||
|
||||
public GoalTrackingProblem(PlanningProblem planningProblem, Set<Goal> goals) {
|
||||
this.planningProblem = planningProblem;
|
||||
this.goals = goals;
|
||||
this.goalNameMap = CollectionUtils.newMap();
|
||||
|
||||
for(Goal g: goals){
|
||||
goalNameMap.put(g.getName(), g);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public static List<GoalTrackingProblem> readFromFiles(InputStream definitionInputStream, InputStream methodsInputStream) throws Reader.ParsingException {
|
||||
|
||||
List<GoalTrackingProblem> goalTrackingProblems = readFromFile(definitionInputStream);
|
||||
|
||||
List<PlanMethod> planMethods = readPlanMethodsFrom(methodsInputStream);
|
||||
|
||||
goalTrackingProblems.stream().map(GoalTrackingProblem::getPlanningProblem).forEach(x->x.addToPlanMethods(planMethods));
|
||||
|
||||
return goalTrackingProblems;
|
||||
}
|
||||
|
||||
|
||||
public static List<GoalTrackingProblem> readFromFile(InputStream inputStream) throws Reader.ParsingException {
|
||||
|
||||
Parseable parseable = Parsers.newParseable(new InputStreamReader(inputStream));
|
||||
Parser parser = Parsers.newParser(Parsers.defaultConfiguration());
|
||||
|
||||
List<GoalTrackingProblem> goalTrackingProblems = CollectionUtils.newEmptyList();
|
||||
|
||||
Object nextValue = parser.nextValue(parseable);
|
||||
|
||||
Set<Goal> goals = CollectionUtils.newEmptySet();
|
||||
while (!nextValue.equals(Token.END_OF_INPUT)) {
|
||||
Map<?, ?> goalTrackingProblemSpec = (Map<?, ?>) nextValue;
|
||||
|
||||
PlanningProblem planningProblem = PlanningProblem.readFromObject(goalTrackingProblemSpec.get(DEFINITIONS));
|
||||
|
||||
|
||||
Map<?, ?> goalSpecs = (Map<?,?>) goalTrackingProblemSpec.get(GOALS);
|
||||
|
||||
for(Map.Entry<?,?> entry : goalSpecs.entrySet()){
|
||||
|
||||
String name = entry.getKey().toString();
|
||||
Map<?, ?> goalSpec = (Map<?,?>)entry.getValue();
|
||||
|
||||
double priority = ((Double) goalSpec.get(PRIORITY));
|
||||
Set<Formula> stateFormulae = PlanningProblem.readFrom((List<?>) goalSpec.get(STATE));
|
||||
|
||||
String description = goalSpec.get(DESCRIPTION)!=null? goalSpec.get(DESCRIPTION).toString(): stateFormulae.toString();
|
||||
goals.add(Goal.makeGoal(State.initializeWith(stateFormulae), priority, name, description));
|
||||
|
||||
}
|
||||
|
||||
goalTrackingProblems.add(new GoalTrackingProblem(planningProblem, goals));
|
||||
nextValue = parser.nextValue(parseable);
|
||||
|
||||
|
||||
}
|
||||
|
||||
return goalTrackingProblems;
|
||||
}
|
||||
|
||||
public PlanningProblem getPlanningProblem() {
|
||||
return planningProblem;
|
||||
}
|
||||
|
||||
public Set<Goal> getGoals() {
|
||||
return goals;
|
||||
}
|
||||
|
||||
public Goal getGoalNamed(String goalName) {
|
||||
return goalNameMap.get(goalName);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
package com.naveensundarg.planner.utils;
|
||||
|
||||
import com.naveensundarg.planner.Action;
|
||||
import com.naveensundarg.shadow.prover.representations.formula.Formula;
|
||||
import com.naveensundarg.shadow.prover.representations.value.Variable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class IndefiniteAction extends Action {
|
||||
|
||||
private IndefiniteAction(String name, Set<Formula> preconditions, Set<Formula> additions, Set<Formula> deletions, List<Variable> freeVariables) {
|
||||
super(name, preconditions, additions, deletions, freeVariables);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
package com.naveensundarg.planner.utils;
|
||||
|
||||
import com.diogonunes.jcdp.color.ColoredPrinter;
|
||||
import com.naveensundarg.planner.DepthFirstPlanner;
|
||||
import com.naveensundarg.planner.GoalTracker;
|
||||
import com.naveensundarg.planner.Plan;
|
||||
import com.naveensundarg.planner.Planner;
|
||||
import com.naveensundarg.shadow.prover.utils.Reader;
|
||||
import org.apache.commons.lang3.tuple.Triple;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
/**
|
||||
* Created by naveensundarg on 1/15/17.
|
||||
*/
|
||||
public class LearningSystem {
|
||||
|
||||
static ColoredPrinter cp = new ColoredPrinter.Builder(1, false).build();
|
||||
|
||||
|
||||
static List<Triple<BiConsumer<String, String>, String, String>> printQueue = new ArrayList<>();
|
||||
|
||||
|
||||
public static void main(String[] args) throws Reader.ParsingException, InterruptedException {
|
||||
|
||||
|
||||
System.out.println();
|
||||
|
||||
RunDemo.planningProblemWarmUp();
|
||||
|
||||
Visualizer.setShouldVisualize(true);
|
||||
|
||||
List<GoalTrackingProblem> goalTrackingProblemList1 = (GoalTrackingProblem.readFromFiles(Sandbox.class.getResourceAsStream("../problems/seriated/seriated_challenge_1.clj"),
|
||||
Sandbox.class.getResourceAsStream("../problems/seriated/methods.clj")));
|
||||
List<GoalTrackingProblem> goalTrackingProblemList2 = (GoalTrackingProblem.readFromFiles(Sandbox.class.getResourceAsStream("../problems/seriated/seriated_challenge_2.clj"),
|
||||
Sandbox.class.getResourceAsStream("../problems/seriated/methods.clj")));
|
||||
|
||||
|
||||
GoalTrackingProblem goalTrackingProblem1 = goalTrackingProblemList1.get(0);
|
||||
GoalTrackingProblem goalTrackingProblem2 = goalTrackingProblemList2.get(0);
|
||||
|
||||
|
||||
PlanningProblem planningProblem1 = goalTrackingProblem1.getPlanningProblem();
|
||||
PlanningProblem planningProblem2 = goalTrackingProblem2.getPlanningProblem();
|
||||
|
||||
Planner planner = new DepthFirstPlanner();
|
||||
|
||||
// GoalTracker(PlanningProblem problem, Set<Formula> background, State startState, Set<Action> actions)
|
||||
|
||||
GoalTracker goalTracker1 = new GoalTracker(planningProblem1, planningProblem1.getBackground(), planningProblem1.getStart(), planningProblem1.getActions());
|
||||
GoalTracker goalTracker2 = new GoalTracker(planningProblem2, planningProblem2.getBackground(), planningProblem2.getStart(), planningProblem2.getActions());
|
||||
|
||||
|
||||
long start, end;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Plan plan1 = goalTracker1.adoptGoal(goalTrackingProblem1.getGoalNamed("G1")).get();
|
||||
//Plan plan2 = goalTracker2.adoptGoal(goalTrackingProblem2.getGoalNamed("G1")).get();
|
||||
|
||||
BiFunction<GoalTracker, GoalTrackingProblem, Plan> run = (goalTracker, goalTrackingProblem) -> {
|
||||
Optional<Plan> planOptional = goalTracker.adoptGoal(goalTrackingProblem.getGoalNamed("G1"));
|
||||
|
||||
if(planOptional.isPresent()){
|
||||
return planOptional.get();
|
||||
}
|
||||
else {
|
||||
|
||||
System.out.println("Could not find a plan");
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
// Object plan1 = (Commons.runAndTime(run, goalTracker1, goalTrackingProblem1, "Problem 1"));
|
||||
|
||||
Object plan2 = (Commons.runAndTime(run, goalTracker2, goalTrackingProblem2, "Problem 2"));
|
||||
|
||||
|
||||
Visualizer.unspool(10);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,438 @@
|
|||
package com.naveensundarg.planner.utils;
|
||||
|
||||
import com.naveensundarg.planner.Context;
|
||||
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;
|
||||
import com.naveensundarg.shadow.prover.utils.Sets;
|
||||
import com.naveensundarg.planner.Action;
|
||||
import com.naveensundarg.planner.PlanMethod;
|
||||
import com.naveensundarg.planner.State;
|
||||
import us.bpsm.edn.Keyword;
|
||||
import us.bpsm.edn.Symbol;
|
||||
import us.bpsm.edn.parser.Parseable;
|
||||
import us.bpsm.edn.parser.Parser;
|
||||
import us.bpsm.edn.parser.Parsers;
|
||||
import us.bpsm.edn.parser.Token;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.StringReader;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.naveensundarg.planner.utils.Reader.readPlanMethodFrom;
|
||||
|
||||
/**
|
||||
* Created by naveensundarg on 1/13/17.
|
||||
*/
|
||||
public class PlanningProblem {
|
||||
|
||||
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 Set<Value> avoidIfPossible;
|
||||
private final List<PlanMethod> planMethods;
|
||||
|
||||
private final Optional<Context> contextOpt;
|
||||
|
||||
private static final Keyword CONTEXT = Keyword.newKeyword("context");
|
||||
private static final Keyword WORK_FROM_SCRATCH = Keyword.newKeyword("work-from-scratch");
|
||||
private static final Keyword PLAN_METHODS = Keyword.newKeyword("plan-methods");
|
||||
|
||||
|
||||
private static final Keyword BACKGROUND = Keyword.newKeyword("background");
|
||||
private static final Keyword START = Keyword.newKeyword("start");
|
||||
private static final Keyword GOAL = Keyword.newKeyword("goal");
|
||||
private static final Keyword NAME = Keyword.newKeyword("name");
|
||||
private static final Keyword ACTION = Keyword.newKeyword("actions");
|
||||
private static final Keyword AVOID_IF_POSSIBLE = Keyword.newKeyword("avoid-if-possible");
|
||||
|
||||
private static final Keyword PRECONDITIONS = Keyword.newKeyword("preconditions");
|
||||
private static final Keyword ADDITIONS = Keyword.newKeyword("additions");
|
||||
private static final Keyword DELETIONS = Keyword.newKeyword("deletions");
|
||||
|
||||
private static final Symbol ACTION_DEFINER = Symbol.newSymbol("define-action");
|
||||
|
||||
private static final Keyword EXPECTED_PLANS = Keyword.newKeyword("expected-plans");
|
||||
|
||||
private PlanningProblem(String name, Set<Formula> background, State start, State goal, Set<Action> actions, Set<Value> avoidIfPossible) {
|
||||
|
||||
this.background = background;
|
||||
this.start = start;
|
||||
this.actions = actions;
|
||||
this.goal = goal;
|
||||
this.name = name;
|
||||
this.actionMap = CollectionUtils.newMap();
|
||||
this.avoidIfPossible = avoidIfPossible;
|
||||
this.planMethods = CollectionUtils.newEmptyList();
|
||||
this.expectedActionSequencesOpt = Optional.empty();
|
||||
this.contextOpt = Optional.empty();
|
||||
|
||||
}
|
||||
|
||||
private PlanningProblem(Optional<Context> contextOpt, String name, Set<Formula> background, State start, State goal, Set<Action> actions, Set<Value> avoidIfPossible) {
|
||||
|
||||
this.background = background;
|
||||
this.start = start;
|
||||
this.actions = actions;
|
||||
this.goal = goal;
|
||||
this.name = name;
|
||||
this.actionMap = CollectionUtils.newMap();
|
||||
this.avoidIfPossible = avoidIfPossible;
|
||||
this.planMethods = CollectionUtils.newEmptyList();
|
||||
this.expectedActionSequencesOpt = Optional.empty();
|
||||
this.contextOpt = contextOpt;
|
||||
|
||||
}
|
||||
|
||||
private PlanningProblem(String name, Set<Formula> background, State start, State goal, Set<Action> actions, Set<Value> avoidIfPossible, Set<List<Action>>expectedActionSequences) {
|
||||
|
||||
this.background = background;
|
||||
this.start = start;
|
||||
this.actions = actions;
|
||||
this.goal = goal;
|
||||
this.name = name;
|
||||
this.actionMap = CollectionUtils.newMap();
|
||||
this.avoidIfPossible = avoidIfPossible;
|
||||
this.planMethods = CollectionUtils.newEmptyList();
|
||||
|
||||
this.expectedActionSequencesOpt = Optional.of(expectedActionSequences);
|
||||
|
||||
this.contextOpt = Optional.empty();
|
||||
|
||||
}
|
||||
|
||||
public static List<PlanningProblem> readFromString(String input) throws Reader.ParsingException {
|
||||
|
||||
|
||||
Parseable parseable = Parsers.newParseable(new StringReader(input));
|
||||
Parser parser = Parsers.newParser(Parsers.defaultConfiguration());
|
||||
|
||||
List<PlanningProblem> planningProblems = CollectionUtils.newEmptyList();
|
||||
|
||||
Object nextValue = parser.nextValue(parseable);
|
||||
|
||||
while (!nextValue.equals(Token.END_OF_INPUT)) {
|
||||
|
||||
planningProblems.add(readFromObject(nextValue));
|
||||
|
||||
|
||||
|
||||
nextValue = parser.nextValue(parseable);
|
||||
}
|
||||
|
||||
return planningProblems;
|
||||
}
|
||||
|
||||
public static List<PlanningProblem> readFromFile(InputStream inputStream) throws Reader.ParsingException {
|
||||
|
||||
Parseable parseable = Parsers.newParseable(new InputStreamReader(inputStream));
|
||||
Parser parser = Parsers.newParser(Parsers.defaultConfiguration());
|
||||
|
||||
List<PlanningProblem> planningProblems = CollectionUtils.newEmptyList();
|
||||
|
||||
Object nextValue = parser.nextValue(parseable);
|
||||
|
||||
while (!nextValue.equals(Token.END_OF_INPUT)) {
|
||||
|
||||
planningProblems.add(readFromObject(nextValue));
|
||||
|
||||
|
||||
|
||||
nextValue = parser.nextValue(parseable);
|
||||
}
|
||||
|
||||
return planningProblems;
|
||||
|
||||
}
|
||||
|
||||
public static PlanningProblem readFromObject(Object nextValue) throws Reader.ParsingException {
|
||||
Map<?, ?> planningProblemSpec = (Map<?,?>)nextValue;
|
||||
|
||||
Set<Formula> background = readFrom((List<?>) planningProblemSpec.get(BACKGROUND));
|
||||
Set<Formula> start = readFrom((List<?>) planningProblemSpec.get(START));
|
||||
|
||||
|
||||
Set<Formula> goal = readFrom((List<?>) planningProblemSpec.get(GOAL));
|
||||
Set<Value> avoidIfPossible = readValuesFrom((List<?>) planningProblemSpec.get(AVOID_IF_POSSIBLE));
|
||||
|
||||
List<?> actionDefinitions = (List<?>) planningProblemSpec.get(ACTION);
|
||||
|
||||
System.out.println(planningProblemSpec.get(NAME));
|
||||
String name = planningProblemSpec.get(NAME).toString();
|
||||
|
||||
Set<Action> actions = readActionsFrom(actionDefinitions);
|
||||
Map<String, Action> actionMap = CollectionUtils.newMap();
|
||||
|
||||
actions.stream().forEach(action->{
|
||||
actionMap.put(action.getName(), action);
|
||||
});
|
||||
|
||||
|
||||
Optional<Context> contextOpt = Optional.empty();
|
||||
if(planningProblemSpec.containsKey(CONTEXT)){
|
||||
Map<?, ?> contextSpec = (Map<?, ?>) planningProblemSpec.get(CONTEXT);
|
||||
boolean workFromScratch = contextSpec.get(WORK_FROM_SCRATCH).toString().equals("true");
|
||||
List<?> planMethodSpecs = (List<?> )contextSpec.get(PLAN_METHODS);
|
||||
List<PlanMethod> planMethods = CollectionUtils.newEmptyList();
|
||||
|
||||
if(planMethodSpecs!=null){
|
||||
|
||||
for(Object planMethodSpec: (List<?>) planMethodSpecs){
|
||||
planMethods.add(readPlanMethodFrom((List<?>) planMethodSpec));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
contextOpt = Optional.of(new Context(planMethods, workFromScratch));
|
||||
|
||||
}
|
||||
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());
|
||||
|
||||
|
||||
|
||||
return new PlanningProblem(name, background, State.initializeWith(start),
|
||||
State.initializeWith(goal), actions, avoidIfPossible, expectedActions);
|
||||
} else {
|
||||
|
||||
return new PlanningProblem(contextOpt, name, background, State.initializeWith(start),
|
||||
State.initializeWith(goal),actions, avoidIfPossible);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static Action readInstantiatedAction(Set<Action> actions, String instantiatedActionSpecString) throws Reader.ParsingException {
|
||||
|
||||
|
||||
Parseable parseable = Parsers.newParseable(new StringReader(instantiatedActionSpecString));
|
||||
Parser parser = Parsers.newParser(Parsers.defaultConfiguration());
|
||||
|
||||
Object instantiatedActionSpec = parser.nextValue(parseable);
|
||||
|
||||
Map<String, Action> actionMap = CollectionUtils.newMap();
|
||||
|
||||
actions.stream().forEach(action->{
|
||||
actionMap.put(action.getName(), action);
|
||||
});
|
||||
|
||||
return readInstantiatedAction(actionMap, instantiatedActionSpec);
|
||||
|
||||
}
|
||||
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 -> {
|
||||
List<?> specBody = (List<?>) spec;
|
||||
if(!specBody.get(0).equals(ACTION_DEFINER)){
|
||||
|
||||
return null;
|
||||
}
|
||||
String name = specBody.get(1).toString();
|
||||
List<Variable> vars = ((List<?>)specBody.get(2)).stream().map(x -> {
|
||||
try {
|
||||
return Reader.readLogicValue(x);
|
||||
} catch (Reader.ParsingException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}).map(x->(Variable)x).collect(Collectors.toList());
|
||||
|
||||
if(vars.stream().anyMatch(Objects::isNull)){
|
||||
return null;
|
||||
}
|
||||
Map<?, ?> actionSpec = (Map<?, ?>) specBody.get(3);
|
||||
try {
|
||||
|
||||
|
||||
Set<Formula> preconditions = readFrom((List<?>) actionSpec.get(PRECONDITIONS));
|
||||
Set<Formula> additions = readFrom((List<?>) actionSpec.get(ADDITIONS));
|
||||
Set<Formula> deletions = readFrom((List<?>) actionSpec.get(DELETIONS));
|
||||
|
||||
return Action.buildActionFrom(name, preconditions, additions, deletions, vars);
|
||||
|
||||
|
||||
} catch (Reader.ParsingException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}).collect(Collectors.toSet());
|
||||
|
||||
if (actions.stream().anyMatch(Objects::isNull)) {
|
||||
|
||||
throw new Reader.ParsingException("Couldn't read actions: " + actionSpecs);
|
||||
}
|
||||
|
||||
return actions;
|
||||
|
||||
}
|
||||
|
||||
public static Set<Formula> readFrom(List<?> objects) throws Reader.ParsingException {
|
||||
|
||||
if(objects==null){
|
||||
|
||||
return Sets.newSet();
|
||||
}
|
||||
Set<Formula> formulae = objects.stream().map(x -> {
|
||||
try {
|
||||
return Reader.readFormula(x);
|
||||
} catch (Reader.ParsingException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}).collect(Collectors.toSet());
|
||||
|
||||
|
||||
if (formulae.stream().anyMatch(Objects::isNull)) {
|
||||
|
||||
throw new Reader.ParsingException("Couldn't read formulae: " + objects);
|
||||
}
|
||||
|
||||
return formulae;
|
||||
|
||||
|
||||
}
|
||||
|
||||
public static Set<Value> readValuesFrom(List<?> objects) throws Reader.ParsingException {
|
||||
|
||||
if(objects==null){
|
||||
|
||||
return Sets.newSet();
|
||||
}
|
||||
Set<Value> values = objects.stream().map(x -> {
|
||||
try {
|
||||
return Reader.readLogicValue(x);
|
||||
} catch (Reader.ParsingException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}).collect(Collectors.toSet());
|
||||
|
||||
|
||||
if (values.stream().anyMatch(Objects::isNull)) {
|
||||
|
||||
throw new Reader.ParsingException("Couldn't read formulae: " + objects);
|
||||
}
|
||||
|
||||
return values;
|
||||
|
||||
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
public Set<Value> getAvoidIfPossible() {
|
||||
return avoidIfPossible;
|
||||
}
|
||||
|
||||
public Optional<Context> getContextOpt() {
|
||||
return contextOpt;
|
||||
}
|
||||
|
||||
public List<PlanMethod> getPlanMethods() {
|
||||
return planMethods;
|
||||
}
|
||||
|
||||
public void addToPlanMethods(List<PlanMethod> methods){
|
||||
|
||||
planMethods.addAll(methods);
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PlanningProblem{" +
|
||||
"name='" + name + '\'' +
|
||||
", background=" + background +
|
||||
", actions=" + actions +
|
||||
", start=" + start +
|
||||
", goal=" + goal +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
package com.naveensundarg.planner.utils;
|
||||
|
||||
import com.naveensundarg.shadow.prover.representations.formula.Formula;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Created by naveensundarg on 1/26/17.
|
||||
*/
|
||||
public interface ProceduralAttachment {
|
||||
|
||||
Optional<Boolean> satisfies(Set<Formula> base, Formula goal);
|
||||
}
|
||||
111
src/main/java/com/naveensundarg/planner/utils/Reader.java
Normal file
111
src/main/java/com/naveensundarg/planner/utils/Reader.java
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
package com.naveensundarg.planner.utils;
|
||||
|
||||
import com.naveensundarg.shadow.prover.representations.formula.Formula;
|
||||
import com.naveensundarg.shadow.prover.representations.value.Compound;
|
||||
import com.naveensundarg.shadow.prover.representations.value.Variable;
|
||||
import com.naveensundarg.shadow.prover.utils.CollectionUtils;
|
||||
import com.naveensundarg.planner.PlanMethod;
|
||||
import us.bpsm.edn.Keyword;
|
||||
import us.bpsm.edn.Symbol;
|
||||
import us.bpsm.edn.parser.Parseable;
|
||||
import us.bpsm.edn.parser.Parser;
|
||||
import us.bpsm.edn.parser.Parsers;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.StringReader;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class Reader {
|
||||
|
||||
|
||||
private static final Keyword GOAL = Keyword.newKeyword("goal");
|
||||
private static final Keyword ACTIONS = Keyword.newKeyword("actions");
|
||||
private static final Keyword WHILE = Keyword.newKeyword("while");
|
||||
|
||||
public static List<PlanMethod> readPlanMethodsFrom(InputStream inputStream) throws com.naveensundarg.shadow.prover.utils.Reader.ParsingException {
|
||||
|
||||
Parseable parseable = Parsers.newParseable(new InputStreamReader(inputStream));
|
||||
Parser parser = Parsers.newParser(Parsers.defaultConfiguration());
|
||||
|
||||
|
||||
|
||||
List<PlanMethod> planMethods = CollectionUtils.newEmptyList();
|
||||
|
||||
|
||||
Object current = parser.nextValue(parseable);
|
||||
while(current!=Parser.END_OF_INPUT){
|
||||
|
||||
planMethods.add(readPlanMethodFrom((List<?>) current));
|
||||
current = parser.nextValue(parseable);
|
||||
}
|
||||
|
||||
return planMethods;
|
||||
}
|
||||
|
||||
|
||||
// (def planMethod [?x ?y ?z] {:goal [...] :action [....])
|
||||
public static PlanMethod readPlanMethodFromString(String stringSpec) throws com.naveensundarg.shadow.prover.utils.Reader.ParsingException {
|
||||
|
||||
Parseable parseable = Parsers.newParseable(new StringReader(stringSpec));
|
||||
Parser parser = Parsers.newParser(Parsers.defaultConfiguration());
|
||||
|
||||
Object specObj = parser.nextValue(parseable);
|
||||
return readPlanMethodFrom((List<?>) specObj);
|
||||
}
|
||||
|
||||
// (def planMethod [?x ?y ?z] {:goal [...] :action [....])
|
||||
public static PlanMethod readPlanMethodFrom(List<?> planMethodSpec) throws com.naveensundarg.shadow.prover.utils.Reader.ParsingException {
|
||||
|
||||
Object command = planMethodSpec.get(0);
|
||||
|
||||
if(!command.toString().equals("define-method")){
|
||||
throw new AssertionError("Malformed method definition. Was expecting a 'define-method' but got "+ command);
|
||||
}
|
||||
Object name = planMethodSpec.get(1);
|
||||
List<Symbol> variableObjs = (List<Symbol>) planMethodSpec.get(2);
|
||||
|
||||
List<Variable> variables = CollectionUtils.newEmptyList();
|
||||
for(Symbol varSym : variableObjs){
|
||||
|
||||
variables.add((Variable) com.naveensundarg.shadow.prover.utils.Reader.readLogicValueFromString(varSym.toString()));
|
||||
|
||||
}
|
||||
|
||||
Map<?, ? > body = (Map<?, ?>) planMethodSpec.get(3);
|
||||
|
||||
Set<Formula> goalPreconds = CollectionUtils.newEmptySet();
|
||||
Set<Formula> whilePreconds = CollectionUtils.newEmptySet();
|
||||
|
||||
List<Compound> actionCompounds = CollectionUtils.newEmptyList();
|
||||
|
||||
List<?> goalPrecondSpecs = (List<?>) body.get(GOAL);
|
||||
|
||||
for(Object goalPrecondSpec : goalPrecondSpecs){
|
||||
|
||||
goalPreconds.add(com.naveensundarg.shadow.prover.utils.Reader.readFormula(goalPrecondSpec));
|
||||
}
|
||||
|
||||
|
||||
List<?> whilePrecondSpecs = (List<?>) body.get(WHILE);
|
||||
|
||||
for(Object whilePrecondSpec : whilePrecondSpecs){
|
||||
|
||||
whilePreconds.add(com.naveensundarg.shadow.prover.utils.Reader.readFormula(whilePrecondSpec));
|
||||
}
|
||||
|
||||
|
||||
|
||||
List<?> actionPrecondSpecs = (List<?>) body.get(ACTIONS);
|
||||
|
||||
for(Object actionPrecondSpec : actionPrecondSpecs){
|
||||
|
||||
actionCompounds.add((Compound) com.naveensundarg.shadow.prover.utils.Reader.readLogicValue(actionPrecondSpec));
|
||||
}
|
||||
|
||||
return new PlanMethod(goalPreconds, whilePreconds, variables, actionCompounds);
|
||||
}
|
||||
|
||||
}
|
||||
329
src/main/java/com/naveensundarg/planner/utils/RunDemo.java
Normal file
329
src/main/java/com/naveensundarg/planner/utils/RunDemo.java
Normal file
|
|
@ -0,0 +1,329 @@
|
|||
package com.naveensundarg.planner.utils;
|
||||
|
||||
import com.diogonunes.jcdp.color.ColoredPrinter;
|
||||
import com.diogonunes.jcdp.color.api.Ansi;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.naveensundarg.planner.Goal;
|
||||
import com.naveensundarg.planner.GoalTracker;
|
||||
import com.naveensundarg.planner.Inducer;
|
||||
import com.naveensundarg.planner.Plan;
|
||||
import com.naveensundarg.shadow.prover.core.Prover;
|
||||
import com.naveensundarg.shadow.prover.core.SnarkWrapper;
|
||||
import com.naveensundarg.shadow.prover.utils.Reader;
|
||||
import com.naveensundarg.planner.inducers.SimpleInducer;
|
||||
import org.apache.commons.lang3.tuple.Triple;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Created by naveensundarg on 1/15/17.
|
||||
*/
|
||||
public class RunDemo {
|
||||
|
||||
static ColoredPrinter cp = new ColoredPrinter.Builder(1, false).build();
|
||||
|
||||
|
||||
static List<Triple<BiConsumer<String, String>, String, String>> printQueue = new ArrayList<>();
|
||||
|
||||
static {
|
||||
|
||||
Prover prover = SnarkWrapper.getInstance();
|
||||
/* try {
|
||||
List<Problem> problems = ProblemReader.readFrom(Sandbox.class.getResourceAsStream("../firstorder-completness-tests.clj"));
|
||||
|
||||
problems.forEach(problem -> {
|
||||
for (int i = 0; i < 100; i++) {
|
||||
prover.prove(problem.getAssumptions(), problem.getGoal());
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
planningProblemWarmUp();
|
||||
System.out.println("\nWARM UP DONE");
|
||||
} catch (Reader.ParsingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
*/
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Reader.ParsingException, InterruptedException {
|
||||
planningProblemWarmUp();
|
||||
|
||||
System.out.println();
|
||||
|
||||
Visualizer.setShouldVisualize(false);
|
||||
|
||||
runProblem("../problems/heroism/setup.clj");
|
||||
// runProblem("seriated_challenge_2.clj");
|
||||
|
||||
|
||||
}
|
||||
|
||||
private static void runProblem(String name) throws Reader.ParsingException {
|
||||
List<GoalTrackingProblem> goalTrackingProblemList = (GoalTrackingProblem.readFromFile(Sandbox.class.getResourceAsStream(name)));
|
||||
|
||||
|
||||
GoalTrackingProblem goalTrackingProblem = goalTrackingProblemList.get(0);
|
||||
|
||||
GoalTracker goalTracker = new GoalTracker(goalTrackingProblem.getPlanningProblem(), goalTrackingProblem.getPlanningProblem().getBackground(),
|
||||
goalTrackingProblem.getPlanningProblem().getStart(),
|
||||
goalTrackingProblem.getPlanningProblem().getActions());
|
||||
|
||||
long start = System.currentTimeMillis();
|
||||
|
||||
Goal g1 = goalTrackingProblem.getGoalNamed("G1");
|
||||
Goal g2 = goalTrackingProblem.getGoalNamed("G2");
|
||||
|
||||
|
||||
tryAndAddGoal(g1, goalTracker);
|
||||
tryAndAddGoal(g2, goalTracker);
|
||||
|
||||
|
||||
long end = System.currentTimeMillis();
|
||||
|
||||
|
||||
System.out.println("***************************");
|
||||
cp.setAttribute(Ansi.Attribute.BOLD);
|
||||
cp.println("AVAILABLE GOALS AND CONSTRAINTS");
|
||||
cp.clear();
|
||||
System.out.println("------------------------------");
|
||||
|
||||
goalTrackingProblem.getGoals().forEach(goal->{
|
||||
System.out.println(goal);
|
||||
|
||||
});
|
||||
|
||||
System.out.println("***************************");
|
||||
|
||||
Visualizer.unspool(200);
|
||||
for (int i = 0; i < printQueue.size(); i++) {
|
||||
|
||||
Triple<BiConsumer<String, String>, String, String> task = printQueue.get(i);
|
||||
|
||||
task.getLeft().accept(task.getMiddle(), task.getRight());
|
||||
|
||||
}
|
||||
|
||||
cp.println("--------------------------");
|
||||
cp.setForegroundColor(Ansi.FColor.CYAN);
|
||||
|
||||
cp.print("Time Taken:");
|
||||
cp.clear();
|
||||
cp.print(" ");
|
||||
cp.setAttribute(Ansi.Attribute.BOLD);
|
||||
cp.print((end - start) / 1000.0 + "s");
|
||||
cp.println(" ");
|
||||
|
||||
cp.println("--------------------------");
|
||||
cp.println(" ");
|
||||
cp.println(" ");
|
||||
cp.println(" ");
|
||||
}
|
||||
|
||||
public static void planningProblemWarmUp() throws Reader.ParsingException {
|
||||
|
||||
|
||||
for (int i = 0; i < 1; i++) {
|
||||
|
||||
|
||||
List<GoalTrackingProblem> goalTrackingProblemList = (GoalTrackingProblem.readFromFile(Sandbox.class.getResourceAsStream("../problems/prisoner/goal_management_1.clj")));
|
||||
|
||||
|
||||
GoalTrackingProblem goalTrackingProblem = goalTrackingProblemList.get(0);
|
||||
|
||||
GoalTracker goalTracker = new GoalTracker(goalTrackingProblem.getPlanningProblem(), goalTrackingProblem.getPlanningProblem().getBackground(),
|
||||
goalTrackingProblem.getPlanningProblem().getStart(),
|
||||
goalTrackingProblem.getPlanningProblem().getActions());
|
||||
|
||||
long start = System.currentTimeMillis();
|
||||
|
||||
Goal g1 = goalTrackingProblem.getGoalNamed("G1");
|
||||
Goal g2 = goalTrackingProblem.getGoalNamed("G2");
|
||||
Goal g3 = goalTrackingProblem.getGoalNamed("G3");
|
||||
Goal g4 = goalTrackingProblem.getGoalNamed("G4");
|
||||
Goal g5 = goalTrackingProblem.getGoalNamed("G5");
|
||||
|
||||
|
||||
goalTracker.adoptGoal(g1);
|
||||
|
||||
goalTracker.adoptGoal(g2);
|
||||
|
||||
|
||||
goalTracker.adoptGoal(g3);
|
||||
|
||||
|
||||
goalTracker.adoptGoal(g4);
|
||||
|
||||
|
||||
goalTracker.adoptGoal(g5);
|
||||
|
||||
System.out.print(".");
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void tryAndAddGoal(Goal g, GoalTracker goalTracker) {
|
||||
|
||||
Inducer simpleInducer = new SimpleInducer();
|
||||
|
||||
System.out.println("========================");
|
||||
printInfoLater("Trying to Add Goal or Constraint:", "");
|
||||
printInfoLater(" ", g.toString());
|
||||
|
||||
Set<Goal> oldGoals = goalTracker.getCurrentGoals().stream().collect(Collectors.toSet());
|
||||
Optional<Plan> possibleGoalPlan = goalTracker.adoptGoal(g);
|
||||
if (possibleGoalPlan.isPresent()) {
|
||||
|
||||
System.out.println(simpleInducer.induce(goalTracker.getProblem(), goalTracker.getProblem().getStart(), g, possibleGoalPlan.get()));
|
||||
|
||||
printSuccessLater("Successfully added:", g.getName());
|
||||
printDebug1Later("Current Goals and Constraint:", "\n" + goalTracker.getCurrentGoals().stream().collect(Collectors.toSet()).toString());
|
||||
|
||||
Set<Goal> newGoals = goalTracker.getCurrentGoals().stream().collect(Collectors.toSet());
|
||||
|
||||
if (!Sets.difference(oldGoals, newGoals).isEmpty()) {
|
||||
printDroppedLater("", "Dropped Goals and Contraints:" + Sets.difference(oldGoals, newGoals));
|
||||
|
||||
}
|
||||
Plan plan = possibleGoalPlan.get();
|
||||
printDebug2Later("Plan:", plan.getActions().isEmpty() ? "No plan needed. Already satisfied." : "\n" + plan.toString());
|
||||
|
||||
} else {
|
||||
|
||||
printFailureLater("", "Could not add " + g);
|
||||
|
||||
printDebug1Later("Current Goals and Contraints: ", goalTracker.getCurrentGoals().stream().map(Goal::getName).collect(Collectors.toSet()).toString());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void printInfoLater(String header, String message) {
|
||||
|
||||
|
||||
printQueue.add(Triple.of((x, y) -> RunDemo.printInfo(x, y), header, message));
|
||||
|
||||
}
|
||||
|
||||
static void printInfo(String header, String message) {
|
||||
|
||||
cp.setForegroundColor(Ansi.FColor.WHITE);
|
||||
cp.setBackgroundColor(Ansi.BColor.BLUE); //setting format
|
||||
cp.print(header);
|
||||
cp.clear();
|
||||
cp.print(" ");
|
||||
cp.setAttribute(Ansi.Attribute.BOLD);
|
||||
cp.print(message);
|
||||
cp.println("");
|
||||
cp.clear();
|
||||
}
|
||||
|
||||
static void printSuccessLater(String header, String message) {
|
||||
|
||||
|
||||
printQueue.add(Triple.of((x, y) -> RunDemo.printSuccess(x, y), header, message));
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void printSuccess(String header, String message) {
|
||||
|
||||
cp.setForegroundColor(Ansi.FColor.BLACK);
|
||||
cp.setBackgroundColor(Ansi.BColor.GREEN); //setting format
|
||||
cp.print(header);
|
||||
cp.clear();
|
||||
cp.print(" ");
|
||||
cp.setAttribute(Ansi.Attribute.BOLD);
|
||||
cp.print(message);
|
||||
cp.println("");
|
||||
cp.clear();
|
||||
}
|
||||
|
||||
|
||||
static void printDebug1Later(String header, String message) {
|
||||
|
||||
|
||||
printQueue.add(Triple.of((x, y) -> RunDemo.printDebug1(x, y), header, message));
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void printDebug1(String header, String message) {
|
||||
|
||||
cp.setForegroundColor(Ansi.FColor.BLACK);
|
||||
cp.setBackgroundColor(Ansi.BColor.YELLOW); //setting format
|
||||
cp.print(header);
|
||||
cp.clear();
|
||||
cp.print(" ");
|
||||
cp.setAttribute(Ansi.Attribute.BOLD);
|
||||
cp.print(message);
|
||||
cp.println("");
|
||||
cp.clear();
|
||||
}
|
||||
|
||||
static void printDebug2Later(String header, String message) {
|
||||
|
||||
|
||||
printQueue.add(Triple.of((x, y) -> RunDemo.printDebug2(x, y), header, message));
|
||||
|
||||
}
|
||||
|
||||
static void printDebug2(String header, String message) {
|
||||
|
||||
cp.setForegroundColor(Ansi.FColor.BLACK);
|
||||
cp.setBackgroundColor(Ansi.BColor.MAGENTA); //setting format
|
||||
cp.print(header);
|
||||
cp.clear();
|
||||
cp.print(" ");
|
||||
cp.setAttribute(Ansi.Attribute.BOLD);
|
||||
cp.print(message);
|
||||
cp.println("");
|
||||
cp.clear();
|
||||
}
|
||||
|
||||
static void printFailureLater(String header, String message) {
|
||||
|
||||
|
||||
printQueue.add(Triple.of((x, y) -> RunDemo.printFailure(x, y), header, message));
|
||||
|
||||
}
|
||||
|
||||
static void printFailure(String header, String message) {
|
||||
|
||||
cp.setForegroundColor(Ansi.FColor.WHITE);
|
||||
cp.setBackgroundColor(Ansi.BColor.RED); //setting format
|
||||
cp.print(message);
|
||||
cp.clear();
|
||||
cp.println("");
|
||||
cp.clear();
|
||||
}
|
||||
|
||||
|
||||
static void printDroppedLater(String header, String message) {
|
||||
|
||||
|
||||
printQueue.add(Triple.of((x, y) -> RunDemo.printDropped(x, y), header, message));
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void printDropped(String header, String message) {
|
||||
|
||||
cp.setForegroundColor(Ansi.FColor.WHITE);
|
||||
cp.setBackgroundColor(Ansi.BColor.RED); //setting format
|
||||
cp.print("Dropped Goals:");
|
||||
cp.clear();
|
||||
cp.print(" ");
|
||||
cp.setAttribute(Ansi.Attribute.BOLD);
|
||||
cp.print(message);
|
||||
cp.println("");
|
||||
cp.clear();
|
||||
}
|
||||
}
|
||||
40
src/main/java/com/naveensundarg/planner/utils/Sandbox.java
Normal file
40
src/main/java/com/naveensundarg/planner/utils/Sandbox.java
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
package com.naveensundarg.planner.utils;
|
||||
|
||||
import com.naveensundarg.planner.PlanMethod;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by naveensundarg on 12/22/17.
|
||||
*/
|
||||
public class Sandbox {
|
||||
|
||||
public static void main(String[] args) throws com.naveensundarg.shadow.prover.utils.Reader.ParsingException {
|
||||
|
||||
PlanMethod seriatedPlanMethod = (Reader.readPlanMethodsFrom(Sandbox.class.getResourceAsStream("../problems/seriated/methods.clj"))).get(0);
|
||||
|
||||
|
||||
List<GoalTrackingProblem> goalTrackingProblemList1 = (GoalTrackingProblem.readFromFile(Sandbox.class.getResourceAsStream("../problems/seriated/seriated_challenge_1.clj")));
|
||||
|
||||
List<GoalTrackingProblem> goalTrackingProblemList2 = (GoalTrackingProblem.readFromFile(Sandbox.class.getResourceAsStream("../problems/seriated/seriated_challenge_2.clj")));
|
||||
|
||||
System.out.println(seriatedPlanMethod.apply(goalTrackingProblemList1.get(0).getPlanningProblem().getBackground(),
|
||||
goalTrackingProblemList1.get(0).getPlanningProblem().getStart().getFormulae(),
|
||||
goalTrackingProblemList1.get(0).getGoalNamed("G1").getGoalState().getFormulae(),
|
||||
goalTrackingProblemList1.get(0).getPlanningProblem().getActions()
|
||||
|
||||
));
|
||||
|
||||
|
||||
System.out.println(seriatedPlanMethod.apply(goalTrackingProblemList2.get(0).getPlanningProblem().getBackground(),
|
||||
goalTrackingProblemList2.get(0).getPlanningProblem().getStart().getFormulae(),
|
||||
goalTrackingProblemList2.get(0).getGoalNamed("G1").getGoalState().getFormulae(),
|
||||
goalTrackingProblemList2.get(0).getPlanningProblem().getActions()
|
||||
|
||||
));
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
177
src/main/java/com/naveensundarg/planner/utils/Visualizer.java
Normal file
177
src/main/java/com/naveensundarg/planner/utils/Visualizer.java
Normal file
|
|
@ -0,0 +1,177 @@
|
|||
package com.naveensundarg.planner.utils;
|
||||
|
||||
import com.diogonunes.jcdp.color.ColoredPrinter;
|
||||
import com.diogonunes.jcdp.color.api.Ansi;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
* Created by naveensundarg on 9/29/17.
|
||||
*/
|
||||
public class Visualizer {
|
||||
|
||||
|
||||
private Visualizer(){
|
||||
throw new AssertionError("Cannot instantiate the Visualizer");
|
||||
|
||||
|
||||
}
|
||||
static ColoredPrinter cp = new ColoredPrinter.Builder(1, false).build();
|
||||
|
||||
|
||||
static Queue<String> spool = new ArrayDeque<>();
|
||||
private static final AtomicBoolean shouldVisualize;
|
||||
private static int depth = 0;
|
||||
static {
|
||||
shouldVisualize = new AtomicBoolean(true);
|
||||
}
|
||||
|
||||
public static boolean getShouldVisualize() {
|
||||
return shouldVisualize.get();
|
||||
}
|
||||
|
||||
public static void setShouldVisualize(boolean visualize) {
|
||||
shouldVisualize.set(visualize);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static void nested(String name){
|
||||
|
||||
StringBuffer stringBuffer = new StringBuffer("");
|
||||
if(shouldVisualize.get()){
|
||||
for(int i = 0; i<depth+1; i++){
|
||||
|
||||
stringBuffer.append(" ▶ ");
|
||||
}
|
||||
|
||||
stringBuffer.append(name);
|
||||
|
||||
}
|
||||
|
||||
|
||||
spool.add(stringBuffer.toString());
|
||||
}
|
||||
|
||||
public static void unspool(long delay){
|
||||
|
||||
spool.forEach(x->{
|
||||
// try {
|
||||
// Thread.sleep(delay);
|
||||
cp.println(x);
|
||||
/* } catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}*/
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
public static void push(){
|
||||
|
||||
depth = depth + 1;
|
||||
}
|
||||
|
||||
public static void pop(){
|
||||
|
||||
depth = depth - 1;
|
||||
}
|
||||
|
||||
public static void reset(){
|
||||
|
||||
depth = 0;
|
||||
}
|
||||
|
||||
|
||||
public static void print(String message) {
|
||||
cp.print(message);
|
||||
cp.clear();
|
||||
}
|
||||
|
||||
|
||||
public static void printRed(String message) {
|
||||
|
||||
cp.setForegroundColor(Ansi.FColor.RED);
|
||||
cp.setAttribute(Ansi.Attribute.BOLD);
|
||||
cp.print(message);
|
||||
cp.clear();
|
||||
}
|
||||
|
||||
public static void printInfo(String header, String message) {
|
||||
|
||||
cp.setForegroundColor(Ansi.FColor.WHITE);
|
||||
cp.setBackgroundColor(Ansi.BColor.BLUE); //setting format
|
||||
cp.print(header);
|
||||
cp.clear();
|
||||
cp.print(" ");
|
||||
cp.setAttribute(Ansi.Attribute.BOLD);
|
||||
cp.print(message);
|
||||
cp.println("");
|
||||
cp.clear();
|
||||
}
|
||||
|
||||
public static void printSuccess(String header, String message) {
|
||||
|
||||
cp.setForegroundColor(Ansi.FColor.BLACK);
|
||||
cp.setBackgroundColor(Ansi.BColor.GREEN); //setting format
|
||||
cp.print(header);
|
||||
cp.clear();
|
||||
cp.print(" ");
|
||||
cp.setAttribute(Ansi.Attribute.BOLD);
|
||||
cp.print(message);
|
||||
cp.println("");
|
||||
cp.clear();
|
||||
}
|
||||
|
||||
|
||||
public static void printDebug1(String header, String message) {
|
||||
|
||||
cp.setForegroundColor(Ansi.FColor.BLACK);
|
||||
cp.setBackgroundColor(Ansi.BColor.YELLOW); //setting format
|
||||
cp.print(header);
|
||||
cp.clear();
|
||||
cp.print(" ");
|
||||
cp.setAttribute(Ansi.Attribute.BOLD);
|
||||
cp.print(message);
|
||||
cp.println("");
|
||||
cp.clear();
|
||||
}
|
||||
|
||||
public static void printDebug2(String header, String message) {
|
||||
|
||||
cp.setForegroundColor(Ansi.FColor.BLACK);
|
||||
cp.setBackgroundColor(Ansi.BColor.MAGENTA); //setting format
|
||||
cp.print(header);
|
||||
cp.clear();
|
||||
cp.print(" ");
|
||||
cp.setAttribute(Ansi.Attribute.BOLD);
|
||||
cp.print(message);
|
||||
cp.println("");
|
||||
cp.clear();
|
||||
}
|
||||
|
||||
public static void printFailure(String message) {
|
||||
|
||||
cp.setForegroundColor(Ansi.FColor.WHITE);
|
||||
cp.setBackgroundColor(Ansi.BColor.RED); //setting format
|
||||
cp.print(message);
|
||||
cp.clear();
|
||||
cp.println("");
|
||||
cp.clear();
|
||||
}
|
||||
|
||||
public static void printDropped(String message) {
|
||||
|
||||
cp.setForegroundColor(Ansi.FColor.WHITE);
|
||||
cp.setBackgroundColor(Ansi.BColor.RED); //setting format
|
||||
cp.print("Dropped Goals:");
|
||||
cp.clear();
|
||||
cp.print(" ");
|
||||
cp.setAttribute(Ansi.Attribute.BOLD);
|
||||
cp.print(message);
|
||||
cp.println("");
|
||||
cp.clear();
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue