Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Adds angelicSearch #412

Open
wants to merge 8 commits into
base: AIMA3e
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package aima.core.logic.planning;

import aima.core.logic.fol.kb.data.Literal;
import aima.core.logic.fol.parsing.ast.Constant;
import aima.core.logic.fol.parsing.ast.Variable;
import aima.core.logic.planning.angelicsearch.AngelicHLA;
import aima.core.logic.planning.hierarchicalsearch.HighLevelAction;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.*;

/**
* A problem factory to generate planning problems.
Expand Down Expand Up @@ -142,4 +142,22 @@ public static HighLevelAction getHlaAct(Problem problem) {
act.addRefinement(new ArrayList<>());
return act;
}

public static Problem getAngelicABProblem(){
return new Problem(new State("~A"),
new State("A^C"),
new HashSet<>());
}

public static List<Object> getAngelicInitialPlan(List<Object> refinements,Problem problem,String goal){
List<HashSet> effects = new ArrayList<>();
AngelicHLA act = new AngelicHLA("act",null,problem.getInitialState().getFluents(),
Utils.angelicParse(goal));
for (Object obj :
refinements) {
act.addRefinement(Arrays.asList(obj, act));
}
act.addRefinement(new ArrayList<>());
return Collections.singletonList(act);
}
}
158 changes: 158 additions & 0 deletions aima-core/src/main/java/aima/core/logic/planning/State.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package aima.core.logic.planning;

import aima.core.logic.fol.kb.data.Literal;
import aima.core.logic.planning.angelicsearch.AngelicHLA;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;

/**
Expand Down Expand Up @@ -83,6 +85,10 @@ public boolean isApplicable(ActionSchema a) {
return this.getFluents().containsAll(a.getPrecondition());
}

public boolean isApplicable(AngelicHLA angelicHLA) {
return this.getFluents().containsAll(angelicHLA.getPrecondition());
}

public List<Literal> getFluents() {
return fluents;
}
Expand All @@ -104,4 +110,156 @@ public int hashCode() {
}
return hashCode;
}

public HashSet<State> optimisticReach(AngelicHLA angelicAction) {
HashSet<State> result = new HashSet<>();
State thisStateCopy = new State(new ArrayList<>(this.getFluents()));
if (!this.isApplicable(angelicAction)) {
result.add(new State(new ArrayList<>(this.getFluents())));
return result;
} else {
for (Literal fluent :
angelicAction.getEffectsNegativeLiterals()) {
Literal tempFluent = new Literal(fluent.getAtomicSentence());
thisStateCopy.fluents.remove(tempFluent);
tempFluent = new Literal(fluent.getAtomicSentence(), true);
if (!thisStateCopy.fluents.contains(tempFluent))
thisStateCopy.fluents.add(tempFluent);
}
for (Literal fluent :
angelicAction.getEffectsPositiveLiterals()) {
Literal tempFluent = new Literal(fluent.getAtomicSentence(), true);
tempFluent = new Literal(tempFluent.getAtomicSentence());
if (!thisStateCopy.fluents.contains(tempFluent)) {
thisStateCopy.fluents.add(tempFluent);
tempFluent = new Literal(tempFluent.getAtomicSentence(), true);
thisStateCopy.fluents.remove(tempFluent);
}
}
result.add(new State(new ArrayList<>(thisStateCopy.getFluents())));
for (Literal literal :
angelicAction.getEffectsMaybePositiveLiterals()) {
List<State> listToAdd = new ArrayList<>();
for (State state :
result) {
State tempCopyState = new State(new ArrayList<>(state.getFluents()));
if (!tempCopyState.getFluents().contains(literal)) {
Literal tempFluent = new Literal(literal.getAtomicSentence(), true);
tempCopyState.fluents.remove(tempFluent);
tempCopyState.getFluents().add(literal);
listToAdd.add(new State(new ArrayList<>(tempCopyState.getFluents())));
}
}
result.addAll(listToAdd);
}
for (Literal literal :
angelicAction.getEffectsMaybeNegativeLiterals()) {
List<State> listToAdd = new ArrayList<>();
for (State state :
result) {
State tempCopyState = new State(new ArrayList<>(state.getFluents()));
Literal tempFluent = new Literal(literal.getAtomicSentence(), true);
if (!tempCopyState.getFluents().contains(tempFluent)) {
tempFluent = new Literal(tempFluent.getAtomicSentence());
tempCopyState.getFluents().remove(tempFluent);
tempFluent = new Literal(tempFluent.getAtomicSentence(), true);
tempCopyState.fluents.add(tempFluent);
listToAdd.add(new State(new ArrayList<>(tempCopyState.getFluents())));
}
}
result.addAll(listToAdd);
}
}
return result;
}

public HashSet<State> pessimisticReach(AngelicHLA angelicAction) {
HashSet<State> result = new HashSet<>();
State thisStateCopy = new State(new ArrayList<>(this.getFluents()));
if (!this.isApplicable(angelicAction)) {
result.add(new State(new ArrayList<>(this.getFluents())));
return result;
} else {
for (Literal fluent :
angelicAction.getEffectsNegativeLiterals()) {
Literal tempFluent = new Literal(fluent.getAtomicSentence());
thisStateCopy.fluents.remove(tempFluent);
tempFluent = new Literal(fluent.getAtomicSentence(), true);
if (!thisStateCopy.fluents.contains(tempFluent))
thisStateCopy.fluents.add(tempFluent);
}
for (Literal fluent :
angelicAction.getEffectsPositiveLiterals()) {
Literal tempFluent = new Literal(fluent.getAtomicSentence(), true);
tempFluent = new Literal(tempFluent.getAtomicSentence());
if (!thisStateCopy.fluents.contains(tempFluent)) {
thisStateCopy.fluents.add(tempFluent);
tempFluent = new Literal(tempFluent.getAtomicSentence(), true);
thisStateCopy.fluents.remove(tempFluent);
}
}
result.add(new State(new ArrayList<>(thisStateCopy.getFluents())));
return result;
}
}

public HashSet<State> optimisticReach(List<Object> plan) {
HashSet<State> result = new HashSet<>();
result.add(new State(this.getFluents()));
if (plan.isEmpty()) {
return result;
}
for (Object action :
plan) {
HashSet<State> currResult = new HashSet<>();
if (action instanceof ActionSchema) {
for (State state :
result) {
currResult.add(state.result((ActionSchema) action));
}
} else if (action instanceof AngelicHLA) {
for (State state :
result) {
currResult.addAll(state.optimisticReach((AngelicHLA) action));
}
}
result = currResult;
}
return result;
}

public HashSet<State> pessimisticReach(List<Object> plan) {
HashSet<State> result = new HashSet<>();
result.add(new State(this.getFluents()));
if (plan.isEmpty()) {
return result;
}
for (Object action :
plan) {
HashSet<State> currResult = new HashSet<>();
if (action instanceof ActionSchema) {
for (State state :
result) {
currResult.add(state.result((ActionSchema) action));
}
} else if (action instanceof AngelicHLA) {
for (State state :
result) {
currResult.addAll(state.pessimisticReach((AngelicHLA) action));
}
}
result = currResult;
}
return result;
}

@Override
public String toString() {
StringBuilder result = new StringBuilder("State:");
for (Literal literal :
this.getFluents()) {
result.append("\n").append(literal.toString());
}
return result.toString();
}
}
62 changes: 62 additions & 0 deletions aima-core/src/main/java/aima/core/logic/planning/Utils.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import aima.core.logic.fol.parsing.ast.Variable;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;

/**
Expand Down Expand Up @@ -50,4 +52,64 @@ public static List<Literal> parse(String s) {
}
return literals;
}

public static List<HashSet<Literal>> angelicParse(String s){
HashSet<Literal> positive = new HashSet<>();
HashSet<Literal> negative = new HashSet<>();
HashSet<Literal> maybePositive = new HashSet<>();
HashSet<Literal> maybeNegative = new HashSet<>();
if (s.isEmpty())
return new ArrayList<>(Arrays.asList(positive,negative,maybePositive,maybeNegative));
s = s.replaceAll("\\s+", "");
String[] tokens = s.split("\\^");
Literal literal;
for (String token :
tokens) {
String[] terms = token.split("[(,)]");
ArrayList<Term> literalTerms = new ArrayList<>();
Term term;
String termString;
for (int i = 1; i < terms.length; i++) {
termString = terms[i];
if (termString.equals(termString.toLowerCase())) {
term = new Variable(termString);
} else {
term = new Constant(termString);
}
literalTerms.add(term);
}

String name = terms[0];
if (name.charAt(0) == '~'){
if (name.charAt(1)=='+'){
if (name.charAt(2)=='-') {
name = name.substring(3);
literal = new Literal(new Predicate(name,literalTerms));
maybeNegative.add(literal);
maybePositive.add(literal);
}
else {
name = name.substring(2);
literal = new Literal(new Predicate(name,literalTerms));
maybePositive.add(literal);
}
}
else if (name.charAt(1)=='-'){
name = name.substring(2);
literal = new Literal(new Predicate(name,literalTerms));
maybeNegative.add(literal);
}
else {
name = name.substring(1);
literal = new Literal(new Predicate(name,literalTerms));
negative.add(literal);
}
}
else {
literal = new Literal(new Predicate(name,literalTerms));
positive.add(literal);
}
}
return new ArrayList<>(Arrays.asList(positive,negative,maybePositive,maybeNegative));
}
}
Loading