ai.libs.jaicore.planning.hierarchical.algorithms.forwarddecomposition.graphgenerators.ceoctfd.CEOCTFDGraphGenerator Maven / Gradle / Ivy
package ai.libs.jaicore.planning.hierarchical.algorithms.forwarddecomposition.graphgenerators.ceoctfd;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ai.libs.jaicore.basic.sets.SetUtil;
import ai.libs.jaicore.logic.fol.structure.ConstantParam;
import ai.libs.jaicore.logic.fol.structure.Literal;
import ai.libs.jaicore.logic.fol.structure.Monom;
import ai.libs.jaicore.planning.core.Action;
import ai.libs.jaicore.planning.hierarchical.algorithms.forwarddecomposition.graphgenerators.tfd.TFDGraphGenerator;
import ai.libs.jaicore.planning.hierarchical.algorithms.forwarddecomposition.graphgenerators.tfd.TFDNode;
import ai.libs.jaicore.planning.hierarchical.problems.ceocstn.CEOCSTNPlanningProblem;
import ai.libs.jaicore.planning.hierarchical.problems.stn.MethodInstance;
public class CEOCTFDGraphGenerator extends TFDGraphGenerator {
private static final Logger logger = LoggerFactory.getLogger(CEOCTFDGraphGenerator.class);
public CEOCTFDGraphGenerator(final CEOCSTNPlanningProblem problem) {
super(problem);
}
@Override
protected TFDNode postProcessPrimitiveTaskNode(final TFDNode node) {
Monom state = node.getState();
state.getParameters().stream().filter(p -> p.getName().startsWith("newVar") && !state.contains(new Literal("def('" + p.getName() + "')")))
.forEach(p -> state.add(new Literal("def('" + p.getName() + "')")));
return node;
}
@Override
public boolean isPathSemanticallySubsumed(final List path, final List compl) throws InterruptedException {
if (compl.size() < path.size()) {
logger.debug("Ignoring this partial path, because its completion is shorter than the path we already have.");
return false;
}
if (path.equals(compl)) {
logger.debug("Return true, because the paths are even equal.");
return true;
}
Map map = new HashMap<>();
boolean allUnifiable = true;
for (int i = 0; i < path.size(); i++) {
TFDNode current = path.get(i);
TFDNode partner = compl.get(i);
/* check whether the chosen method or operation is the same */
final Action a1 = current.getAppliedAction();
final Action a2 = partner.getAppliedAction();
if ((a1 == null) != (a2 == null)) {
allUnifiable = false;
logger.trace("Not unifiable because one node applies an action and the other not (either it applies nothing or a method instance).");
break;
}
if (a1 != null && !a1.getOperation().equals(a2.getOperation())) {
allUnifiable = false;
logger.trace("Not unifiable because operations {} and {} of a1 and a2 respectively deviate", a1.getOperation(), a2.getOperation());
break;
}
if (a1 == null) {
final MethodInstance mi1 = current.getAppliedMethodInstance();
final MethodInstance mi2 = partner.getAppliedMethodInstance();
/* the nodes just don't do anything (should be the root) */
if (mi1 == null && mi2 == null) {
continue;
}
if ((mi1 == null) != (mi2 == null)) {
allUnifiable = false;
logger.trace("Not unifiable because one node applies a method instance and the other not (either an action or nothing)");
break;
}
if (!mi1.getMethod().equals(mi2.getMethod())) {
allUnifiable = false;
logger.trace("Not unifiable because methods {} and {} of m1 and m2 respectively deviate", mi1.getMethod(), mi2.getMethod());
break;
}
}
/* compute substitutions of new vars */
Collection varsInCurrent = new HashSet<>(current.getState().getConstantParams());
for (Literal l : current.getRemainingTasks()) {
varsInCurrent.addAll(l.getConstantParams());
}
Collection varsInPartner = new HashSet<>(partner.getState().getConstantParams());
for (Literal l : partner.getRemainingTasks()) {
varsInPartner.addAll(l.getConstantParams());
}
Collection unboundVars = SetUtil.difference(varsInCurrent, map.keySet());
Collection possibleTargets = SetUtil.difference(varsInPartner, map.values());
for (ConstantParam p : new ArrayList<>(unboundVars)) {
if (possibleTargets.contains(p)) {
map.put(p, p);
unboundVars.remove(p);
possibleTargets.remove(p);
}
}
/* if the relation between vars in the nodes is completely known, we can easily decide whether they are unifiable */
if (unboundVars.isEmpty()) {
if (this.getRenamedState(current.getState(), map).equals(partner.getState())
&& this.getRenamedRemainingList(current.getRemainingTasks(), map).equals(partner.getRemainingTasks())) {
continue;
} else {
allUnifiable = false;
break;
}
}
/* otherwise, we must check possible mappings between the still unbound vars */
boolean unified = false;
Collection