Beispiel #1
0
        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));
        }