/// <summary> /// Computes the forward cost heuristics for the given state in the relaxed planning graph. /// </summary> /// <param name="state">Starting state.</param> /// <param name="goalConditions">Goal conditions.</param> /// <param name="evaluationStrategy">Evaluation strategy.</param> /// <returns>Forward cost heuristic value from the specified state.</returns> private double ComputeForwardCost(IState state, IConditions goalConditions, ForwardCostEvaluationStrategy evaluationStrategy) { IStateLayer previousStateLayer = null; IStateLayer stateLayer = CreateLabeledStateLayer(state.GetRelaxedState()); ActionLayer actionLayer = new ActionLayer(); while (!stateLayer.Equals(previousStateLayer)) { // check goal conditions if (goalConditions.Evaluate(stateLayer.GetState())) { return(goalConditions.EvaluateOperatorPlanningGraphLabel(stateLayer.GetStateLabels(), evaluationStrategy)); } // build new action layer actionLayer.Clear(); foreach (var successor in RelaxedProblem.GetSuccessors(stateLayer.GetState())) { IOperator appliedOperator = successor.GetAppliedOperator(); double label = appliedOperator.ComputePlanningGraphLabel(stateLayer.GetStateLabels(), evaluationStrategy); actionLayer.Add(new ActionNode(appliedOperator, label + appliedOperator.GetCost())); } // build new state layer previousStateLayer = stateLayer; stateLayer = CreateLabeledStateLayer(stateLayer, actionLayer); } // failure, solution cannot be found from the specified state return(int.MaxValue); }
public GraphNode(IState currentstate, GraphNode parentnode, IOperator currentOperator) { this.currentstate = currentstate; this.parentnode = parentnode; this.currentOperator = currentOperator; cost = currentOperator == null ? 0 : currentOperator.GetCost(parentnode.currentstate) + parentnode.cost; totalCost = cost + currentstate.Heuristics; }
/// <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); }
/// <summary> /// Processes the transitions from the specified search node. /// </summary> /// <param name="node">Search node to be processed.</param> /// <param name="gValue">Distance of the node from the initial node.</param> protected virtual void ProcessTransitionsFromNode(ISearchNode node, int gValue) { MaxGValue = Math.Max(MaxGValue, gValue); foreach (var transition in Problem.GetTransitions(node)) { IOperator appliedOperator = transition.GetAppliedOperator(); int gValueNew = gValue + (appliedOperator?.GetCost() ?? 0); if (!transition.IsComplexTransition()) { ISearchNode newNode = transition.GetTransitionResult(); AddToOpenNodes(newNode, gValueNew, node, appliedOperator); } else { foreach (var newNode in transition.GetComplexTransitionResults()) { AddToOpenNodes(newNode, gValueNew, node, appliedOperator); } } } }
/// <summary> /// Starts the search procedure. /// </summary> /// <param name="type">Type of search.</param> /// <returns>Result of the search.</returns> public override ResultStatus Start(SearchType type = SearchType.Forward) { InitSearch(type); List <IOperator> transitionCandidates = new List <IOperator>(); ISearchNode currentNode = GetInitialNode(); while (!Problem.IsGoalNode(currentNode)) { if (IsTimeLimitExceeded()) { return(FinishSearch(ResultStatus.TimeLimitExceeded)); } if (IsMemoryLimitExceeded()) { return(FinishSearch(ResultStatus.MemoryLimitExceeded)); } LogSearchStatistics(); transitionCandidates.Clear(); double bestCost = double.MaxValue; IOperator bestCostOperator; foreach (var transition in Problem.GetTransitions(currentNode)) { IOperator appliedOperator = transition.GetAppliedOperator(); ISearchNode node = transition.GetTransitionResult(); double transitionCost = appliedOperator.GetCost() + Heuristic.GetValue(node); if (transitionCost < bestCost) { bestCost = transitionCost; transitionCandidates.Clear(); transitionCandidates.Add(appliedOperator); } else if (transitionCost.Equals(bestCost)) { transitionCandidates.Add(appliedOperator); } } if (transitionCandidates.Count == 0) { return(FinishSearch(ResultStatus.NoSolutionFound)); // dead-end reached } else if (transitionCandidates.Count == 1) { bestCostOperator = transitionCandidates[0]; } else { bestCostOperator = transitionCandidates[RandomNumberGenerator.Next(transitionCandidates.Count)]; } SolutionPlan.Add(bestCostOperator); SolutionCost += bestCostOperator.GetCost(); currentNode = Apply(currentNode, bestCostOperator); ++ProcessedStatesCount; } if (SearchType != SearchType.Forward) { SolutionPlan.Reverse(); } return(FinishSearch(ResultStatus.SolutionFound, currentNode)); }