Beispiel #1
0
        /// <summary>
        /// Checks whether the operator effects are relevant to the given target relative state.
        /// </summary>
        /// <param name="relativeState">Relative state for the application.</param>
        /// <param name="operatorPreconditions">Operator preconditions.</param>
        /// <returns>True if the operator effects are relevant to the given relative state, false otherwise.</returns>
        public bool IsRelevant(IRelativeState relativeState, ISimpleConditions operatorPreconditions)
        {
            CashedVariablesCollector.Clear();

            bool anyRelevant = false;

            foreach (var effect in this)
            {
                var relevance = effect.IsRelevant(relativeState);
                switch (relevance)
                {
                case EffectRelevance.ANTI_RELEVANT:
                {
                    return(false);
                }

                case EffectRelevance.RELEVANT:
                {
                    anyRelevant = true;
                    CashedVariablesCollector.Add(effect.GetAssignment().GetVariable());
                    break;
                }

                case EffectRelevance.IRRELEVANT:
                {
                    if (effect.GetConditions() != null)
                    {
                        CashedVariablesCollector.Add(effect.GetAssignment().GetVariable());
                    }
                    break;
                }
                }
            }

            if (!anyRelevant)
            {
                return(false);
            }

            // additionally, the relative state has to be checked against operator preconditions ("hidden effects")
            foreach (var constraint in operatorPreconditions)
            {
                int variable = constraint.GetVariable();
                if (!CashedVariablesCollector.Contains(variable))
                {
                    int value = relativeState.GetValue(variable);
                    if (value == RelativeState.WildCardValue)
                    {
                        continue;
                    }

                    if (value != constraint.GetValue())
                    {
                        return(false);
                    }
                }
            }

            return(true);
        }
Beispiel #2
0
        /// <summary>
        /// Checks whether the operator effects are relevant to the given target conditions.
        /// </summary>
        /// <param name="conditions">Conditions for the application.</param>
        /// <param name="operatorPreconditions">Operator preconditions.</param>
        /// <returns>True if the operator effects are relevant to the given conditions, false otherwise.</returns>
        public bool IsRelevant(IConditions conditions, ISimpleConditions operatorPreconditions)
        {
            // Besides the effects relevance, we need to check whether the operator preconditions are not in conflict with the resulting
            // conditions (after backward-apply). This can be done via affected variables: if some effect is relevant, then it modifies a
            // variable, and a constraint corresponding to this variable can be removed from the preconditions. At the end, we check the
            // modified precondition constraints with the target conditions and if there are conflicts, we consider the operator not
            // relevant. This approach works even for conditional-effects, because we take the worst case scenario.

            IConditions nonAffectedPreconditions = (IConditions)operatorPreconditions.Clone();

            bool anyRelevant = false;

            foreach (var effect in this)
            {
                var relevance = effect.IsRelevant(conditions);
                if (relevance == EffectRelevance.ANTI_RELEVANT)
                {
                    return(false);
                }
                else if (relevance == EffectRelevance.RELEVANT)
                {
                    anyRelevant = true;
                    nonAffectedPreconditions.RemoveConstraint(effect.GetAssignment());
                }
            }

            return(anyRelevant && !nonAffectedPreconditions.IsConflictedWith(conditions));
        }
Beispiel #3
0
        /// <summary>
        /// Applies the operator backwards to the given target conditions. The result is a new set of conditions.
        /// </summary>
        /// <param name="conditions">Conditions for the application.</param>
        /// <param name="operatorPreconditions">Operator preconditions.</param>
        /// <returns>Preceding conditions.</returns>
        public IConditions ApplyBackwards(IConditions conditions, ISimpleConditions operatorPreconditions)
        {
            IConditions newConditions = (IConditions)conditions.Clone();

            foreach (var effect in this)
            {
                newConditions = effect.ApplyBackwards(newConditions);
            }
            newConditions = newConditions.ConjunctionWith(operatorPreconditions);

            return(newConditions);
        }
Beispiel #4
0
        /// <summary>
        /// Generates all possible SAS+ states meeting conditions specified by the given conditions. Lazy generated via yield return.
        /// </summary>
        /// <param name="conditions">Reference conditions.</param>
        /// <param name="variables">Variables of the planning problem.</param>
        /// <returns>All possible SAS+ states meeting the conditions.</returns>
        public static IEnumerable <IState> EnumerateStates(ISimpleConditions conditions, Variables variables)
        {
            Func <int, int> checker = (variable) =>
            {
                int value;
                if (conditions.IsVariableConstrained(variable, out value))
                {
                    return(value);
                }
                return(-1);
            };

            return(EnumerateStates(0, new State(new int[variables.Count]), checker, variables));
        }
Beispiel #5
0
        /// <summary>
        /// Gets the corresponding SAS+ relative state meeting specified conditions. Lazy generated via yield return.
        /// </summary>
        /// <param name="conditions">Reference conditions.</param>
        /// <param name="variables">Variables of the planning problem.</param>
        /// <returns>Corresponding SAS+ relative state meeting the conditions.</returns>
        private static IRelativeState GetCorrespondingRelativeState(ISimpleConditions conditions, Variables variables)
        {
            int[] initWildCards = new int[variables.Count];
            for (int i = 0; i < variables.Count; ++i)
            {
                initWildCards[i] = -1;
            }

            IRelativeState newRelativeState = new RelativeState(initWildCards);

            foreach (var constraint in conditions)
            {
                newRelativeState.SetValue(constraint);
            }

            return(newRelativeState);
        }
Beispiel #6
0
        /// <summary>
        /// Computes the distances to the goals for the specified pattern.
        /// </summary>
        /// <param name="pattern">Pattern (i.e. variables of the pattern) to process.</param>
        private PatternValuesDistances ComputePatternDistances(int[] pattern)
        {
            IHeap <double, ISimpleConditions> fringe = new LeftistHeap <ISimpleConditions>();

            InsertPatternConditions(fringe, (Conditions)Problem.GoalConditions, 0, pattern);

            PatternValuesDistances patternValuesDistances = new PatternValuesDistances();

            while (fringe.GetSize() > 0)
            {
                double            distance   = fringe.GetMinKey();
                ISimpleConditions conditions = fringe.RemoveMin();

                int[] patternValues = conditions.GetAssignedValues();

                Debug.Assert(pattern.Length == conditions.GetSize());
                Debug.Assert(pattern.Length == patternValues.Length);

                if (patternValuesDistances.ContainsKey(patternValues))
                {
                    // already processed with a lower cost
                    continue;
                }

                patternValuesDistances.Add(patternValues, distance);

                foreach (var predecessor in Problem.GetPredecessors(conditions))
                {
                    IConditions predecessorConditions = (IConditions)predecessor.GetPredecessorConditions();
                    IOperator   predecessorOperator   = (IOperator)predecessor.GetAppliedOperator();

                    foreach (var predecessorSimpleConditions in predecessorConditions.GetSimpleConditions())
                    {
                        double cost = distance + predecessorOperator.GetCost();
                        InsertPatternConditions(fringe, predecessorSimpleConditions, cost, pattern);
                    }
                }
            }

            return(patternValuesDistances);
        }
Beispiel #7
0
        /// <summary>
        /// Inserts all goal conditions of the corresponding pattern to fringe. I.e. fixes the goal values and generates all combinations
        /// for the rest of variables by the method divide-and-conquer.
        /// </summary>
        /// <param name="fringe">Fringe.</param>
        /// <param name="goalConditions">Goal conditions.</param>
        /// <param name="cost">Current cost.</param>
        /// <param name="pattern">Requested pattern.</param>
        /// <param name="currentVariableIndex">Current variable index.</param>
        /// <param name="values">Generated values.</param>
        private void InsertPatternConditions(IHeap <double, ISimpleConditions> fringe, ISimpleConditions goalConditions, double cost, int[] pattern, int currentVariableIndex, List <int> values)
        {
            if (values.Count == pattern.Length)
            {
                Conditions conditions = new Conditions();
                int        i          = 0;

                foreach (var item in pattern)
                {
                    conditions.Add(new Assignment(item, values[i]));
                    i++;
                }

                fringe.Add(cost, conditions);
                return;
            }

            int currentVariable = pattern[currentVariableIndex];

            int constrainedGoalValue;

            if (goalConditions.IsVariableConstrained(currentVariable, out constrainedGoalValue))
            {
                values.Add(constrainedGoalValue);
                InsertPatternConditions(fringe, goalConditions, cost, pattern, currentVariableIndex + 1, values);
                values.RemoveAt(values.Count - 1);
            }
            else
            {
                for (int i = 0; i < Problem.Variables[currentVariable].GetDomainRange(); ++i)
                {
                    values.Add(i);
                    InsertPatternConditions(fringe, goalConditions, cost, pattern, currentVariableIndex + 1, values);
                    values.RemoveAt(values.Count - 1);
                }
            }
        }
Beispiel #8
0
 /// <summary>
 /// Inserts all conditions of the specified pattern satisfying the given goals to fringe (with the given cost).
 /// </summary>
 /// <param name="fringe">Fringe.</param>
 /// <param name="goalConditions">Current goal conditions.</param>
 /// <param name="cost">New conditions cost.</param>
 /// <param name="pattern">Requested pattern.</param>
 private void InsertPatternConditions(IHeap <double, ISimpleConditions> fringe, ISimpleConditions goalConditions, double cost, int[] pattern)
 {
     InsertPatternConditions(fringe, goalConditions, cost, pattern, 0, new List <int>());
 }
Beispiel #9
0
 /// <summary>
 /// Constructs the SAS+ operator conditional effect.
 /// </summary>
 /// <param name="conditions">Conditions.</param>
 /// <param name="assignment">Effect assignment.</param>
 public ConditionalEffect(ISimpleConditions conditions, IAssignment assignment) : base(assignment)
 {
     Conditions = conditions;
 }
Beispiel #10
0
 /// <summary>
 /// Constructs the SAS+ operator conditional effect from the input data.
 /// </summary>
 /// <param name="inputData">Input data.</param>
 public ConditionalEffect(InputData.SAS.Effect inputData) : base(inputData)
 {
     Conditions = new Conditions(inputData.Conditions);
 }
 /// <summary>
 /// Visits the leaf node of the SAS+ operator decision tree.
 /// </summary>
 /// <param name="treeNode">Leaf node of the tree.</param>
 /// <param name="sourceConditions">Source conditions being evaluated.</param>
 /// <param name="currentSubConditions">Currently evaluated sub-conditions.</param>
 /// <returns>List of predecessors.</returns>
 public IEnumerable <IPredecessor> Visit(OperatorDecisionTreeLeafNode treeNode, IConditions sourceConditions, ISimpleConditions currentSubConditions)
 {
     foreach (var oper in treeNode.Operators)
     {
         // relevant operator candidates need to be double-checked for the relevance with the original conditions, because there can be additional
         // conflicts with the operator preconditions, conditional effects constraints, and/or incompatibility with the mutex constraints
         if (oper.IsRelevant(sourceConditions))
         {
             yield return(new Predecessor(sourceConditions, oper));
         }
     }
 }
        /// <summary>
        /// Visits the inner node of the SAS+ operator decision tree.
        /// </summary>
        /// <param name="treeNode">Inner node of the tree.</param>
        /// <param name="sourceConditions">Source conditions being evaluated.</param>
        /// <param name="currentSubConditions">Currently evaluated sub-conditions.</param>
        /// <returns>List of predecessors.</returns>
        public IEnumerable <IPredecessor> Visit(OperatorDecisionTreeInnerNode treeNode, IConditions sourceConditions, ISimpleConditions currentSubConditions)
        {
            int value;

            if (currentSubConditions.IsVariableConstrained(treeNode.DecisionVariable, out value))
            {
                // if constrained, collect the operators only in the corresponding subtree
                foreach (var predecessor in treeNode.OperatorsByDecisionVariableValue[value].Accept(this, sourceConditions, currentSubConditions))
                {
                    yield return(predecessor);
                }
            }
            else
            {
                // if not constrained, collect operators from all the subtrees
                foreach (var subTree in treeNode.OperatorsByDecisionVariableValue)
                {
                    foreach (var predecessor in subTree.Accept(this, sourceConditions, currentSubConditions))
                    {
                        yield return(predecessor);
                    }
                }
            }

            // always search in the subtree with the value-independent operators
            foreach (var successor in treeNode.OperatorsIndependentOnDecisionVariable.Accept(this, sourceConditions, currentSubConditions))
            {
                yield return(successor);
            }
        }
 /// <summary>
 /// Accepts relevance evaluation visitor.
 /// </summary>
 /// <param name="visitor">Evaluating visitor.</param>
 /// <param name="sourceConditions">Source conditions being evaluated.</param>
 /// <param name="currentSubConditions">Currently evaluated sub-conditions.</param>
 /// <returns>List of predecessors.</returns>
 public IEnumerable <IPredecessor> Accept(IOperatorDecisionTreeRelevanceVisitor visitor, IConditions sourceConditions, ISimpleConditions currentSubConditions)
 {
     return(visitor.Visit(this, sourceConditions, currentSubConditions));
 }
 /// <summary>
 /// Accepts relevance evaluation visitor.
 /// </summary>
 /// <param name="visitor">Evaluating visitor.</param>
 /// <param name="sourceConditions">Source conditions being evaluated.</param>
 /// <param name="currentSubConditions">Currently evaluated sub-conditions.</param>
 /// <returns>List of predecessors.</returns>
 public IEnumerable <IPredecessor> Accept(IOperatorDecisionTreeRelevanceVisitor visitor, IConditions sourceConditions, ISimpleConditions currentSubConditions)
 {
     yield break;
 }
Beispiel #15
0
        /// <summary>
        /// Applies the operator backwards to the given target relative state. The result is a new relative state (or more relative states, if conditional effects are present).
        /// </summary>
        /// <param name="relativeState">Relative state for the application.</param>
        /// <param name="operatorPreconditions">Operator preconditions.</param>
        /// <returns>Preceding relative states.</returns>
        public IEnumerable <IRelativeState> ApplyBackwards(IRelativeState relativeState, ISimpleConditions operatorPreconditions)
        {
            IRelativeState result = (IRelativeState)relativeState.Clone();

            bool anyConditionalEffect = false;

            foreach (var effect in this)
            {
                if (effect.GetConditions() == null)
                {
                    result = effect.ApplyBackwards(result);
                }
                else
                {
                    anyConditionalEffect = true;
                }
            }

            foreach (var constraint in operatorPreconditions)
            {
                result.SetValue(constraint.GetVariable(), constraint.GetValue());
            }

            if (!anyConditionalEffect)
            {
                yield return(result);
            }
            else
            {
                List <IRelativeState> states = new List <IRelativeState> {
                    result
                };

                foreach (var effect in this)
                {
                    if (effect.GetConditions() != null)
                    {
                        int statesCount = states.Count;
                        for (int i = 0; i < statesCount; ++i)
                        {
                            var newEffect = effect.ApplyBackwards(states[i]);
                            if (newEffect != null)
                            {
                                states.Add(newEffect);
                            }
                        }
                    }
                }

                foreach (var state in states)
                {
                    yield return(state);
                }
            }
        }