/// <summary> /// Gets a collection of all relevant predecessors (backwards transitions) from the specified conditions. Lazy generated via yield return. /// </summary> /// <param name="treeRoot">Root of the operator decision tree to be traversed.</param> /// <param name="conditions">Original conditions.</param> /// <returns>Lazy generated collection of relevant predecessors.</returns> public IEnumerable <IPredecessor> GetPredecessors(IOperatorDecisionTreeNode treeRoot, IConditions conditions) { foreach (var simpleConditions in conditions.GetSimpleConditions()) { foreach (var predecessor in treeRoot.Accept(this, conditions, simpleConditions)) { yield return(predecessor); } } }
/// <summary> /// Gets a collection of all possible successors (forward transitions) from the specified state. Lazy generated via yield return. /// </summary> /// <param name="treeRoot">Root of the operator decision tree to be traversed.</param> /// <param name="state">Reference state.</param> /// <returns>Lazy generated collection of successors.</returns> public IEnumerable <ISuccessor> GetSuccessors(IOperatorDecisionTreeNode treeRoot, IState state) { return(treeRoot.Accept(this, state)); }
/// <summary> /// Constructs a new SAS+ operator decision tree inner node. /// </summary> /// <param name="decisionVariable">Decision variable of the current subtree.</param> /// <param name="operatorsByDecisionVariableValue">Subtrees for all the possible values of the decision variable.</param> /// <param name="operatorsIndependentOnDecisionVariable">Subtree where the decision variable doesn't matter.</param> public OperatorDecisionTreeInnerNode(int decisionVariable, IOperatorDecisionTreeNode[] operatorsByDecisionVariableValue, IOperatorDecisionTreeNode operatorsIndependentOnDecisionVariable) { DecisionVariable = decisionVariable; OperatorsByDecisionVariableValue = operatorsByDecisionVariableValue; OperatorsIndependentOnDecisionVariable = operatorsIndependentOnDecisionVariable; }
/// <summary> /// Builds the operator decision tree from the given operators and decision variables. /// </summary> /// <param name="availableOperators">List of operators to be processed.</param> /// <param name="decisionVariables">List of decision variables to be processed with their corresponding domain range.</param> /// <param name="evaluator">Operator evaluator specifying how to handle operators during the tree building.</param> /// <returns>Operator decision tree node corresponding to the input operators and decision variables.</returns> private static IOperatorDecisionTreeNode BuildTree(List <IOperator> availableOperators, List <Tuple <int, int> > decisionVariables, OperatorEvaluator evaluator) { // if we have no remaining operators, then create an empty leaf node if (availableOperators.Count == 0) { return(new OperatorDecisionTreeEmptyLeafNode()); } // if we have no remaining decision variables, then create a leaf node containing the current operators list if (decisionVariables.Count == 0) { return(new OperatorDecisionTreeLeafNode(availableOperators)); } // find the current decision variable, i.e. available variable with the maximal domain range int decisionVariableDomainRange = decisionVariables.Max(variable => variable.Item2); int decisionVariable = decisionVariables.First(variable => variable.Item2 == decisionVariableDomainRange).Item1; // prepare decision variables modifiers Action removeCurrentDecisionVariable = () => { decisionVariables.RemoveAll(variable => variable.Item1 == decisionVariable); }; Action restoreCurrentDecisionVariable = () => { decisionVariables.Add(Tuple.Create(decisionVariable, decisionVariableDomainRange)); }; // prepare collections for sorting out available operators List <IOperator>[] operatorsByValue = new List <IOperator> [decisionVariableDomainRange]; List <IOperator> nonAffectedOperators = new List <IOperator>(); for (int i = 0; i < operatorsByValue.Length; ++i) { operatorsByValue[i] = new List <IOperator>(); } // sort out the available operators by the current decision variable: if the preconditions of the operator are constrained by the // decision variable (applicability tree), or the decision variable is affected by the operator effects (relevance tree), then put // it into the operatorsByValue collection, otherwise into the nonAffectedOperators collection foreach (var oper in availableOperators) { int value; if (evaluator(oper, decisionVariable, out value)) { operatorsByValue[value].Add(oper); } else { nonAffectedOperators.Add(oper); } } // the decision variable has zero impact -> continue without it if (nonAffectedOperators.Count == availableOperators.Count) { removeCurrentDecisionVariable(); var result = BuildTree(nonAffectedOperators, decisionVariables, evaluator); restoreCurrentDecisionVariable(); return(result); } // prepare a new decision node - create decision subtrees for all the possible values of the current decision variable removeCurrentDecisionVariable(); IOperatorDecisionTreeNode[] childrenByValues = new IOperatorDecisionTreeNode[decisionVariableDomainRange]; for (int i = 0; i < decisionVariableDomainRange; ++i) { childrenByValues[i] = BuildTree(operatorsByValue[i], decisionVariables, evaluator); } IOperatorDecisionTreeNode childIndependentOnDecisionVariable = BuildTree(nonAffectedOperators, decisionVariables, evaluator); restoreCurrentDecisionVariable(); // return the root of the current subtree return(new OperatorDecisionTreeInnerNode(decisionVariable, childrenByValues, childIndependentOnDecisionVariable)); }