/// <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); } } }