All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
ai.libs.jaicore.planning.hierarchical.algorithms.forwarddecomposition.graphgenerators.tfd.TFDGraphGenerator Maven / Gradle / Ivy
package ai.libs.jaicore.planning.hierarchical.algorithms.forwarddecomposition.graphgenerators.tfd;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ai.libs.jaicore.logging.ToJSONStringUtil;
import ai.libs.jaicore.logic.fol.structure.Literal;
import ai.libs.jaicore.logic.fol.structure.Monom;
import ai.libs.jaicore.planning.classical.algorithms.strips.forward.StripsUtil;
import ai.libs.jaicore.planning.classical.problems.strips.Operation;
import ai.libs.jaicore.planning.core.Action;
import ai.libs.jaicore.planning.hierarchical.algorithms.forwarddecomposition.graphgenerators.TaskPlannerUtil;
import ai.libs.jaicore.planning.hierarchical.problems.htn.IHTNPlanningProblem;
import ai.libs.jaicore.planning.hierarchical.problems.stn.Method;
import ai.libs.jaicore.planning.hierarchical.problems.stn.MethodInstance;
import ai.libs.jaicore.search.core.interfaces.GraphGenerator;
import ai.libs.jaicore.search.core.interfaces.PathUnifyingGraphGenerator;
import ai.libs.jaicore.search.model.travesaltree.NodeExpansionDescription;
import ai.libs.jaicore.search.model.travesaltree.NodeType;
import ai.libs.jaicore.search.structure.graphgenerator.NodeGoalTester;
import ai.libs.jaicore.search.structure.graphgenerator.SingleRootGenerator;
import ai.libs.jaicore.search.structure.graphgenerator.SuccessorGenerator;
public class TFDGraphGenerator implements GraphGenerator, PathUnifyingGraphGenerator {
private static Logger logger = LoggerFactory.getLogger(TFDGraphGenerator.class);
protected TaskPlannerUtil util = new TaskPlannerUtil(null);
protected final IHTNPlanningProblem problem;
protected final Map primitiveTasks = new HashMap<>();
public TFDGraphGenerator(final IHTNPlanningProblem problem) {
this.problem = problem;
for (Operation op : problem.getDomain().getOperations()) {
this.primitiveTasks.put(op.getName(), op);
}
}
protected Collection getSuccessorsResultingFromResolvingPrimitiveTask(final Monom state, final Literal taskToBeResolved, final List remainingOtherTasks) throws InterruptedException {
Collection successors = new ArrayList<>();
for (Action applicableAction : this.util.getActionsForPrimitiveTaskThatAreApplicableInState(null, this.primitiveTasks.get(taskToBeResolved.getPropertyName()), taskToBeResolved, state)) {
Monom stateCopy = new Monom(state);
StripsUtil.updateState(stateCopy, applicableAction);
successors.add(this.postProcessPrimitiveTaskNode(new TFDNode(stateCopy, remainingOtherTasks, null, applicableAction)));
}
return successors;
}
protected Collection getSuccessorsResultingFromResolvingComplexTask(final Monom state, final Literal taskToBeResolved, final List remainingOtherTasks) throws InterruptedException {
Collection successors = new ArrayList<>();
Collection applicableMethodInstances = this.util.getMethodInstancesForTaskThatAreApplicableInState(null, this.problem.getDomain().getMethods(), taskToBeResolved, state, remainingOtherTasks);
assert this.areLonelyMethodsContainedAtMostOnce(applicableMethodInstances);
for (MethodInstance instance : applicableMethodInstances) {
/* derive remaining network for this instance */
List remainingTasks = this.stripTNPrefixes(this.util.getTaskChainOfTotallyOrderedNetwork(instance.getNetwork()));
remainingTasks.addAll(remainingOtherTasks);
successors.add(this.postProcessComplexTaskNode(new TFDNode(state, remainingTasks, instance, null)));
}
return successors;
}
private boolean areLonelyMethodsContainedAtMostOnce(final Collection instances) {
List usedMethods = new ArrayList<>();
for (MethodInstance mi : instances) {
if (!mi.getMethod().isLonely()) {
continue;
}
boolean doubleUseDetected = usedMethods.contains(mi.getMethod());
assert !doubleUseDetected : "Lonely method " + mi.getMethod() + " has been generated several times as being applicable!";
usedMethods.add(mi.getMethod());
}
return true;
}
protected List stripTNPrefixes(final List taskList) {
return taskList.stream().map(l -> {
String taskName = l.getPropertyName().substring(l.getPropertyName().indexOf('-') + 1, l.getPropertyName().length());
return new Literal(taskName, l.getParameters(), l.isPositive());
}).collect(Collectors.toList());
}
/**
* A hook for extending classes that can be used to change the nodes before they are attached
*
* @param node
* @return
*/
protected TFDNode postProcessPrimitiveTaskNode(final TFDNode node) {
return node;
}
/**
* A hook for extending classes that can be used to change the nodes before they are attached
*
* @param node
* @return
*/
protected TFDNode postProcessComplexTaskNode(final TFDNode node) {
return node;
}
@Override
public SingleRootGenerator getRootGenerator() {
return () -> new TFDNode(this.problem.getInit(), this.stripTNPrefixes(new TaskPlannerUtil(null).getTaskChainOfTotallyOrderedNetwork(this.problem.getNetwork())));
}
@Override
public SuccessorGenerator getSuccessorGenerator() {
return l -> {
Monom state = l.getState();
List currentlyRemainingTasks = new ArrayList<>(l.getRemainingTasks());
if (currentlyRemainingTasks.isEmpty()) {
return new ArrayList<>();
}
Literal nextTaskTmp = currentlyRemainingTasks.get(0);
currentlyRemainingTasks.remove(0);
String nextTaskName = nextTaskTmp.getPropertyName();
Literal nextTask = new Literal(nextTaskName, nextTaskTmp.getParameters());
/* get the child nodes */
long creationStartTime = System.currentTimeMillis();
Collection successors = this.primitiveTasks.containsKey(nextTask.getPropertyName()) ? this.getSuccessorsResultingFromResolvingPrimitiveTask(state, nextTask, currentlyRemainingTasks)
: this.getSuccessorsResultingFromResolvingComplexTask(state, nextTask, currentlyRemainingTasks);
logger.info("Node generation finished and took {}ms", System.currentTimeMillis() - creationStartTime);
/* change order in remaining tasks based on numbered prefixes */
successors = successors.stream().map(this::orderRemainingTasksByPriority).collect(Collectors.toList());
/* derive successor descriptions from the nodes */
return successors.stream().map(n -> new NodeExpansionDescription(l, n, n.getAppliedAction() != null ? n.getAppliedAction().getEncoding() : n.getAppliedMethodInstance().getEncoding(), NodeType.OR)).collect(Collectors.toList());
};
}
public TFDNode orderRemainingTasksByPriority(final TFDNode node) {
/* determine order of tasks based on the prefixes */
Pattern p = Pattern.compile("(\\d+)_");
List unorderedLiterals = new ArrayList<>();
Map> orderedLiterals = new HashMap<>();
node.getRemainingTasks().forEach(t -> {
Matcher m = p.matcher(t.getPropertyName());
if (m.find()) {
int order = Integer.parseInt(m.group(1));
if (!orderedLiterals.containsKey(order)) {
orderedLiterals.put(order, new ArrayList<>());
}
List tasksWithorder = orderedLiterals.get(order);
tasksWithorder.add(t);
} else {
unorderedLiterals.add(t);
}
});
/* reorganize task network */
List newLiteralList = new ArrayList<>();
orderedLiterals.keySet().stream().sorted().forEach(order -> newLiteralList.addAll(orderedLiterals.get(order)));
newLiteralList.addAll(unorderedLiterals);
return new TFDNode(node.getState(), newLiteralList, node.getAppliedMethodInstance(), node.getAppliedAction());
}
@Override
public NodeGoalTester getGoalTester() {
return l -> l.getRemainingTasks().isEmpty();
}
@Override
public boolean isSelfContained() {
return false;
}
@Override
public void setNodeNumbering(final boolean nodenumbering) {
throw new UnsupportedOperationException();
}
@Override
public boolean isPathSemanticallySubsumed(final List path, final List potentialSuperPath) throws InterruptedException {
int n = path.size();
for (int i = 0; i < n; i++) {
if (!path.get(i).equals(potentialSuperPath.get(i))) {
return false;
}
}
return true;
}
@Override
public String toString() {
Map fields = new HashMap<>();
fields.put("util", this.util);
fields.put("problem", this.problem);
fields.put("primitiveTasks", this.primitiveTasks);
return ToJSONStringUtil.toJSONString(this.getClass().getSimpleName(), fields);
}
}