/// <summary> /// Generates all possible PDDL states meeting conditions specified by the given constraint function. Lazy generated recursively via yield return. /// </summary> /// <param name="index">Current index in the predicates list.</param> /// <param name="predicates">List of all grounded predicates.</param> /// <param name="result">Current state being built.</param> /// <param name="predicateConstraint">Predicate constraint function (returns true for positively constrained predicate, false for negatively constrained /// predicate, or null for not constrained).</param> /// <returns>All possible PDDL states meeting the conditions.</returns> private static IEnumerable <IState> EnumerateStatesByPredicates(int index, List <IAtom> predicates, IState result, Func <IAtom, bool?> predicateConstraint) { if (index >= predicates.Count) { yield return((IState)result.Clone()); } else { var predicate = predicates[index]; // predicate can be positively constrained, negatively constrained (not), or not constrained at all var constraint = predicateConstraint(predicate); if (constraint != null) { if (constraint.Value) { result.AddPredicate(predicate); } foreach (var item in EnumerateStatesByPredicates(index + 1, predicates, result, predicateConstraint)) { yield return(item); } if (constraint.Value) { result.RemovePredicate(predicate); } } else { // the predicate won't be contained foreach (var item in EnumerateStatesByPredicates(index + 1, predicates, result, predicateConstraint)) { yield return(item); } // the predicate will be contained result.AddPredicate(predicate); foreach (var item in EnumerateStatesByPredicates(index + 1, predicates, result, predicateConstraint)) { yield return(item); } result.RemovePredicate(predicate); } } }