/** * Constructs a node with the specified state, parent, action, and path * cost. * * @param state * the state in the state space to which the node corresponds. * @param parent * the node in the search tree that generated the node. * @param action * the action that was applied to the parent to generate the * node. * @param pathCost * full pathCost from the root node to here, typically * the root's path costs plus the step costs for executing * the the specified action. */ public Node(System.Object state, Node parent, Action action, double stepCost) : this(state) { this.parent = parent; this.action = action; this.pathCost = parent.pathCost + stepCost; }
/** * Inserts the node at the tail of the frontier if the corresponding state * was not yet explored. */ protected override void addToFrontier(Node node) { if (!explored.Contains(node.getState())) { frontier.Enqueue(node); updateMetrics(frontier.Count); } }
/** * Calls the goal test of the problem and - if the goal test is effectively * a {@link SolutionChecker} - additionally checks, whether the solution is * acceptable. Solution checkers can be used to analyze several or all * solutions with only one search run. */ public static bool isGoalState(Problem p, Node n) { bool isGoal = false; GoalTest gt = p.getGoalTest(); if (gt.isGoalState(n.getState())) { if (gt is SolutionChecker) { isGoal = ((SolutionChecker)gt).isAcceptableSolution( getSequenceOfActions(n), n.getState()); } else { isGoal = true; } } return isGoal; }
/** * Returns the children obtained from expanding the specified node in the * specified problem. * * @param node * the node to expand * @param problem * the problem the specified node is within. * * @return the children obtained from expanding the specified node in the * specified problem. */ public List<Node> expand(Node node, Problem problem) { List<Node> successors = new List<Node>(); ActionsFunction actionsFunction = problem.getActionsFunction(); ResultFunction resultFunction = problem.getResultFunction(); StepCostFunction stepCostFunction = problem.getStepCostFunction(); foreach (Action action in actionsFunction.actions(node.getState())) { System.Object successorState = resultFunction.result(node.getState(), action); double stepCost = stepCostFunction.c(node.getState(), action, successorState); successors.Add(createNode(successorState, node, action, stepCost)); } foreach (NodeListener listener in nodeListeners) { listener.onNodeExpanded(node); } counter++; return successors; }
/** * Returns the list of actions corresponding to the complete path to the * given node or NoOp if path length is one. */ public static List<Action> getSequenceOfActions(Node node) { List<Node> nodes = node.getPathFromRoot(); List<Action> actions = new List<Action>(); if(nodes.Count == 1) { // I'm at the root node, this indicates I started at the // Goal node, therefore just return a NoOp actions.Add(NoOpAction.NO_OP); } else { // ignore the root node this has no action // hence index starts from 1 not zero for (int i = 1; i < nodes.Count; i++) { Node node_temp = nodes[i]; actions.Add(node_temp.getAction()); } } return actions; }
/** * Computes the path cost for getting from the root node state via the * parent node state to the specified state, creates a new node for the * specified state, adds it as child of the provided parent, and returns it. */ public Node createNode(System.Object state, Node parent, Action action, double stepCost) { return new Node(state, parent, action, parent.getPathCost() + stepCost); }
/** * Inserts the node at the tail of the frontier. */ protected override void addToFrontier(Node node) { frontier.Enqueue(node); updateMetrics(frontier.Count); }
/** * * @param n * @return the cost, traditionally denoted by g(n), of the path from the * initial state to the node, as indicated by the parent pointers. */ public double g(Node n) { return n.getPathCost(); }