private static IStringEvaluator combineTokens(List <IToken> tokens) { var valStack = new Stack <IStringEvaluator>(); var opeStack = new Stack <OperatorEvaluator>(); bool valueLasted = false; Action <OperatorEvaluator> fnResolveOperator = (OperatorEvaluator ope) => { ope.Right = valStack.Pop(); ope.Left = valStack.Pop(); valStack.Push(ope); }; foreach (var token in tokens) { IStringEvaluator evaluator = token.getEvaluator(); if (evaluator is ValueEvaluator) { if (valueLasted) { throw new FormatException("Value expression duplicated."); } valStack.Push(evaluator); valueLasted = true; } else if (evaluator is OperatorEvaluator) { OperatorEvaluator ope = (OperatorEvaluator)evaluator; if (!valueLasted) { throw new FormatException("Operator expression duplicated."); } if (opeStack.Count > 0) { if (opeStack.Last().getPriority() <= ope.getPriority()) { fnResolveOperator(opeStack.Pop()); } } opeStack.Push(ope); valueLasted = false; } } while (opeStack.Count > 0) { fnResolveOperator(opeStack.Pop()); } if (valStack.Count == 0) { throw new FormatException("Operator expression is none."); } return(valStack.Last()); }
/// <summary> /// Builds the operator decision tree for the evaluation of operators relevance in the SAS+ planning problem. /// </summary> /// <param name="operators">Operators of the SAS+ planning problem.</param> /// <param name="variables">Variables data of the SAS+ planning problem.</param> /// <returns>Operator decision tree of operators relevance.</returns> public static IOperatorDecisionTreeNode BuildRelevanceTree(Operators operators, Variables variables) { OperatorEvaluator evaluator = (IOperator oper, int variable, out int value) => oper.GetEffects().IsVariableAffected(variable, out value); return(BuildTree(new List <IOperator>(operators), GetAllDecisionVariables(variables), evaluator)); }
/// <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)); }
/// <summary> /// Builds the operator decision tree for the evaluation of operators applicability in the SAS+ planning problem. /// </summary> /// <param name="operators">Operators of the SAS+ planning problem.</param> /// <param name="variables">Variables data of the SAS+ planning problem.</param> /// <returns>Operator decision tree of operators applicability.</returns> public static IOperatorDecisionTreeNode BuildApplicabilityTree(Operators operators, Variables variables) { OperatorEvaluator evaluator = (IOperator oper, int variable, out int value) => oper.GetPreconditions().IsVariableConstrained(variable, out value); return(BuildTree(new List <IOperator>(operators), GetAllDecisionVariables(variables), evaluator)); }