/// <summary> /// Applies backwards the relevant operator effects and operator preconditions to the given target relative state. /// </summary> /// <param name="relativeState">Target relative state to be modified.</param> /// <param name="operatorSubstitution">Variables substitution.</param> /// <returns>Preceding relative states.</returns> public IEnumerable <Planner.IRelativeState> ApplyBackwards(IRelativeState relativeState, ISubstitution operatorSubstitution) { OperatorSubstitution = operatorSubstitution; Effects.GroundEffectsByCurrentOperatorSubstitution(GroundingManager, operatorSubstitution); relativeState = (IRelativeState)relativeState.Clone(); // prepare operator preconditions var operatorPreconditions = (OperatorPreconditions != null) ? GroundingManager.GroundConditions(ClearRigidRelations(OperatorPreconditions), OperatorSubstitution) : null; // remove positively contributing effects from the relative state and insert the operator preconditions ProcessPrimitiveEffects(relativeState); relativeState = ProcessForallEffects(relativeState); foreach (var resultState in ProcessWhenEffects(relativeState)) { if (operatorPreconditions != null) { foreach (var modifiedResultState in ProcessOperatorPreconditions(operatorPreconditions, resultState)) { yield return(modifiedResultState); } } else { yield return(resultState); } } }
/// <summary> /// Applies the operator backwards to the given target relative state. The result is a new relative state (or more relative states, if conditional effects are present). /// </summary> /// <param name="relativeState">Relative state for the application.</param> /// <param name="operatorPreconditions">Operator preconditions.</param> /// <returns>Preceding relative states.</returns> public IEnumerable <IRelativeState> ApplyBackwards(IRelativeState relativeState, ISimpleConditions operatorPreconditions) { IRelativeState result = (IRelativeState)relativeState.Clone(); bool anyConditionalEffect = false; foreach (var effect in this) { if (effect.GetConditions() == null) { result = effect.ApplyBackwards(result); } else { anyConditionalEffect = true; } } foreach (var constraint in operatorPreconditions) { result.SetValue(constraint.GetVariable(), constraint.GetValue()); } if (!anyConditionalEffect) { yield return(result); } else { List <IRelativeState> states = new List <IRelativeState> { result }; foreach (var effect in this) { if (effect.GetConditions() != null) { int statesCount = states.Count; for (int i = 0; i < statesCount; ++i) { var newEffect = effect.ApplyBackwards(states[i]); if (newEffect != null) { states.Add(newEffect); } } } } foreach (var state in states) { yield return(state); } } }
/// <summary> /// Applies the effect backwards to the given relative state. /// </summary> /// <param name="relativeState">Relative state.</param> public override IRelativeState ApplyBackwards(IRelativeState relativeState) { // we explicitly apply the effect for the relative state, if it's relevant if (IsRelevant(relativeState) == EffectRelevance.RELEVANT) { var newState = (IRelativeState)relativeState.Clone(); newState.SetValue(Assignment.GetVariable(), RelativeState.WildCardValue); foreach (var constraint in Conditions) { newState.SetValue(constraint.GetVariable(), constraint.GetValue()); } return(newState); } // the conditional effect was not applied, because it was not relevant return(null); }
/// <summary> /// Generates all possible PDDL relative states meeting given CNF conditions (in the form of a list of conjuncts). Lazy generated recursively via yield return. /// </summary> /// <param name="index">Current index in the conjuncts list.</param> /// <param name="conjuncts">List of conjuncts of the CNF conditions.</param> /// <param name="result">Current relative state being built.</param> /// <returns>All possible PDDL relative states meeting the CNF conditions.</returns> private static IEnumerable <IRelativeState> EnumerateRelativeStatesByCNF(int index, List <IConjunctCNF> conjuncts, IRelativeState result) { if (index == 0) { // the constructed state can have trailing values from the previous unfinished enumeration! result.ClearContent(); } Action <IRelativeState, LiteralCNF> addLiteral = (state, literal) => { // Note: At the moment, there is limited support for object and numeric function assignments. // For example, numeric comparison literals like (< (numFunc) 5) will be omitted in the resulting relative state. PredicateLiteralCNF predicateLiteral = literal as PredicateLiteralCNF; if (predicateLiteral != null) { if (literal.IsNegated) { state.AddNegatedPredicate(predicateLiteral.PredicateAtom.Clone()); } else { state.AddPredicate(predicateLiteral.PredicateAtom.Clone()); } return; } EqualsLiteralCNF equalsLiteral = literal as EqualsLiteralCNF; if (equalsLiteral != null) { var assignment = equalsLiteral.TryGetObjectFunctionAssignment(); if (assignment != null) { if (!literal.IsNegated) { state.AssignObjectFunction(assignment.Item1.FunctionAtom.Clone(), assignment.Item2.NameId); } } return; } NumericCompareLiteralCNF compareLiteral = literal as NumericCompareLiteralCNF; if (compareLiteral != null) { var assignment = compareLiteral.TryGetNumericFunctionAssignment(); if (assignment != null) { if (!compareLiteral.IsNegated) { state.AssignNumericFunction(assignment.Item1.FunctionAtom.Clone(), assignment.Item2.Value); } } } }; Action <IRelativeState, LiteralCNF> removeLiteral = (state, literal) => { PredicateLiteralCNF predicateLiteral = literal as PredicateLiteralCNF; if (predicateLiteral != null) { if (literal.IsNegated) { state.RemoveNegatedPredicate(predicateLiteral.PredicateAtom.Clone()); } else { state.RemovePredicate(predicateLiteral.PredicateAtom.Clone()); } return; } EqualsLiteralCNF equalsLiteral = literal as EqualsLiteralCNF; if (equalsLiteral != null) { var assignment = equalsLiteral.TryGetObjectFunctionAssignment(); if (assignment != null) { if (!literal.IsNegated) { state.AssignObjectFunction(assignment.Item1.FunctionAtom.Clone(), ObjectFunctionTerm.UndefinedValue); } } return; } NumericCompareLiteralCNF compareLiteral = literal as NumericCompareLiteralCNF; if (compareLiteral != null) { var assignment = compareLiteral.TryGetNumericFunctionAssignment(); if (assignment != null) { if (!compareLiteral.IsNegated) { state.AssignNumericFunction(assignment.Item1.FunctionAtom.Clone(), NumericFunction.UndefinedValue); } } } }; if (index >= conjuncts.Count) { yield return((IRelativeState)result.Clone()); } else { var conjunct = conjuncts[index]; ClauseCNF clause = conjunct as ClauseCNF; if (clause != null) { foreach (var literal in clause) { addLiteral(result, literal); foreach (var item in EnumerateRelativeStatesByCNF(index + 1, conjuncts, result)) { yield return(item); } removeLiteral(result, literal); } } else { LiteralCNF literal = conjunct as LiteralCNF; Debug.Assert(literal != null); addLiteral(result, literal); foreach (var item in EnumerateRelativeStatesByCNF(index + 1, conjuncts, result)) { yield return(item); } removeLiteral(result, literal); } } }