// Need to override search() method so that I can re-initialize // the explored set should multiple calls to search be made. public override List<Action> search(Problem problem, Queue<Node> frontier) { // initialize the explored set to be empty explored.Clear(); frontierState.Clear(); return base.search(problem, frontier); }
// function HILL-CLIMBING(problem) returns a state that is a local maximum public List<Action> search(Problem p) { clearInstrumentation(); outcome = SearchOutcome.FAILURE; lastState = null; // current <- MAKE-NODE(problem.INITIAL-STATE) Node current = new Node(p.getInitialState()); Node neighbor = null; // loop do while (!CancelableThread.currIsCanceled()) { List<Node> children = expandNode(current, p); // neighbor <- a highest-valued successor of current neighbor = getHighestValuedNodeFrom(children, p); // if neighbor.VALUE <= current.VALUE then return current.STATE if ((neighbor == null) || (getValue(neighbor) <= getValue(current))) { if (SearchUtils.isGoalState(p, current)) { outcome = SearchOutcome.SOLUTION_FOUND; } lastState = current.getState(); return SearchUtils.actionsFromNodes(current.getPathFromRoot()); } // current <- neighbor current = neighbor; } return new List<Action>(); }
// function DEPTH-LIMITED-SEARCH(problem, limit) returns a solution, or // failure/cutoff /** * @param p * @return if goal found, the list of actions to the Goal. If already at the * goal you will receive a List with a single NoOp Action in it. If * fail to find the Goal, an empty list will be returned to indicate * that the search failed. If the search was cutoff (i.e. reached * its limit without finding a goal) a List with one * CutOffIndicatorAction.CUT_OFF in it will be returned (Note: this * is a NoOp action). */ public List<Action> search(Problem p) { clearInstrumentation(); // return RECURSIVE-DLS(MAKE-NODE(INITIAL-STATE[problem]), problem, // limit) return recursiveDLS(new Node(p.getInitialState()), p, limit); }
public void testMultiGoalProblem() { Map romaniaMap = new SimplifiedRoadMapOfPartOfRomania(); Problem problem = new Problem(SimplifiedRoadMapOfPartOfRomania.ARAD, MapFunctionFactory.getActionsFunction(romaniaMap), MapFunctionFactory.getResultFunction(), new DualMapGoalTest( SimplifiedRoadMapOfPartOfRomania.BUCHAREST, SimplifiedRoadMapOfPartOfRomania.HIRSOVA), new MapStepCostFunction(romaniaMap)); Search search = new BreadthFirstSearch(new GraphSearch()); SearchAgent agent = new SearchAgent(problem, search); Assert .Equals( "[Action[name==moveTo, location==Sibiu], Action[name==moveTo, location==Fagaras], Action[name==moveTo, location==Bucharest], Action[name==moveTo, location==Urziceni], Action[name==moveTo, location==Hirsova]]", agent.getActions().ToString()); Assert.Equals(5, agent.getActions().Count); Assert.Equals("14", agent.getInstrumentation()[ "nodesExpanded"]); Assert.Equals("1", agent.getInstrumentation()[ "queueSize"]); Assert.Equals("5", agent.getInstrumentation()[ "maxQueueSize"]); }
/** * * @param problem * @param frontier * @return if goal found, the list of actions to the Goal. If already at the * goal you will receive a List with a single NoOp Action in it. If * fail to find the Goal, an empty list will be returned to indicate * that the search failed. */ public virtual List<Action> search(Problem problem, Queue<Node> frontier) { this.frontier = frontier; clearInstrumentation(); // initialize the frontier using the initial state of the problem Node root = new Node(problem.getInitialState()); if (isCheckGoalBeforeAddingToFrontier()) { if (SearchUtils.isGoalState(problem, root)) { return SearchUtils.actionsFromNodes(root.getPathFromRoot()); } } frontier.Enqueue(root); setQueueSize(frontier.Count); while (!(frontier.Count==0)) { // choose a leaf node and remove it from the frontier Node nodeToExpand = popNodeFromFrontier(); setQueueSize(frontier.Count); // Only need to check the nodeToExpand if have not already // checked before adding to the frontier if (!isCheckGoalBeforeAddingToFrontier()) { // if the node contains a goal state then return the // corresponding solution if (SearchUtils.isGoalState(problem, nodeToExpand)) { setPathCost(nodeToExpand.getPathCost()); return SearchUtils.actionsFromNodes(nodeToExpand .getPathFromRoot()); } } // expand the chosen node, adding the resulting nodes to the // frontier foreach (Node fn in getResultingNodesToAddToFrontier(nodeToExpand, problem)) { if (isCheckGoalBeforeAddingToFrontier()) { if (SearchUtils.isGoalState(problem, fn)) { setPathCost(fn.getPathCost()); return SearchUtils.actionsFromNodes(fn .getPathFromRoot()); } } frontier.Enqueue(fn); } setQueueSize(frontier.Count); } // if the frontier is empty then return failure return failure(); }
public BidirectionalMapProblem(Map aMap, String initialState, String goalState) : base(initialState, MapFunctionFactory.getActionsFunction(aMap), MapFunctionFactory.getResultFunction(), new DefaultGoalTest( goalState), new MapStepCostFunction(aMap)) { ; map = aMap; reverseProblem = new Problem(goalState, MapFunctionFactory .getActionsFunction(aMap), MapFunctionFactory .getResultFunction(), new DefaultGoalTest(initialState), new MapStepCostFunction(aMap)); }
protected override List<Action> search(Problem problem) { List<Action> actions = new List<Action>(); try { List<Action> sactions = _search.search(problem); foreach (Action action in sactions) { actions.Add(action); } } catch (System.Exception ex) { System.Diagnostics.Debug.WriteLine(ex.ToString()); } return actions; }
// function RECURSIVE-BEST-FIRST-SEARCH(problem) returns a solution, or // failure public List<Action> search(Problem p) { List<Action> actions = new List<Action>(); clearInstrumentation(); // RBFS(problem, MAKE-NODE(INITIAL-STATE[problem]), infinity) Node n = new Node(p.getInitialState()); SearchResult sr = rbfs(p, n, evaluationFunction.f(n), INFINITY, 0); if (sr.getOutcome() == SearchResult.SearchOutcome.SOLUTION_FOUND) { Node s = sr.getSolution(); actions = SearchUtils.actionsFromNodes(s.getPathFromRoot()); setPathCost(s.getPathCost()); } // Empty List can indicate already at Goal // or unable to find valid set of actions return actions; }
public override List<Node> getResultingNodesToAddToFrontier(Node nodeToExpand, Problem problem) { addToFrontier.Clear(); // add the node to the explored set explored.Add(nodeToExpand.getState()); // expand the chosen node, adding the resulting nodes to the frontier foreach (Node cfn in expandNode(nodeToExpand, problem)) { Node frontierNode = frontierState[cfn.getState()]; bool yesAddToFrontier = false; // only if not in the frontier or explored set if (null == frontierNode && !explored.Contains(cfn.getState())) { yesAddToFrontier = true; } else if (null != frontierNode && null != replaceFrontierNodeAtStateCostFunction && replaceFrontierNodeAtStateCostFunction.Compare(cfn, frontierNode) < 0) { // child.STATE is in frontier with higher cost // replace that frontier node with child yesAddToFrontier = true; // Want to replace the current frontier node with the child // node therefore mark the child to be added and remove the // current fontierNode removeNodeFromFrontier(frontierNode); // Ensure removed from add to frontier as well // as 1 or more may reach the same state at the same time addToFrontier.Remove(frontierNode); } if (yesAddToFrontier) { addToFrontier.Add(cfn); frontierState.Add(cfn.getState(), cfn); } } return addToFrontier; }
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( SearchUtils.actionsFromNodes(n.getPathFromRoot()), n .getState()); } else { isGoal = true; } } return isGoal; }
public List<Node> expandNode(Node node, Problem problem) { List<Node> childNodes = 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); childNodes.Add(new Node(successorState, node, action, stepCost)); } metrics.set(METRIC_NODES_EXPANDED, metrics .getInt(METRIC_NODES_EXPANDED) + 1); return childNodes; }
// function ITERATIVE-DEEPENING-SEARCH(problem) returns a solution, or // failure public List<Action> search(Problem p) { iterationMetrics.set(METRIC_NODES_EXPANDED, 0); iterationMetrics.set(PATH_COST, 0); // for depth = 0 to infinity do for (int i = 0; i <= infinity; i++) { // result <- DEPTH-LIMITED-SEARCH(problem, depth) DepthLimitedSearch dls = new DepthLimitedSearch(i); List<Action> result = dls.search(p); iterationMetrics.set(METRIC_NODES_EXPANDED, iterationMetrics .getInt(METRIC_NODES_EXPANDED) + dls.getMetrics().getInt(METRIC_NODES_EXPANDED)); // if result != cutoff then return result if (!dls.isCutOff(result)) { iterationMetrics.set(PATH_COST, dls.getPathCost()); return result; } } return failure(); }
// function SIMULATED-ANNEALING(problem, schedule) returns a solution state public List<Action> search(Problem p) { clearInstrumentation(); outcome = SearchOutcome.FAILURE; lastState = null; // current <- MAKE-NODE(problem.INITIAL-STATE) Node current = new Node(p.getInitialState()); Node next = null; List<Action> ret = new List<Action>(); // for t = 1 to INFINITY do int timeStep = 0; while (!CancelableThread.currIsCanceled()) { // temperature <- schedule(t) double temperature = scheduler.getTemp(timeStep); timeStep++; // if temperature = 0 then return current if (temperature == 0.0) { if (SearchUtils.isGoalState(p, current)) { outcome = SearchOutcome.SOLUTION_FOUND; } ret = SearchUtils.actionsFromNodes(current.getPathFromRoot()); lastState = current.getState(); break; } List<Node> children = expandNode(current, p); if (children.Count > 0) { // next <- a randomly selected successor of current next = Util.selectRandomlyFromList(children); // /\E <- next.VALUE - current.value double deltaE = getValue(p, next) - getValue(p, current); if (shouldAccept(temperature, deltaE)) { current = next; } } } return ret; }
protected abstract List<Action> search(Problem problem);
// // PRIVATE METHODS // // function RECURSIVE-DLS(node, problem, limit) returns a solution, or // failure/cutoff private List<Action> recursiveDLS(Node node, Problem problem, int limit) { // if problem.GOAL-TEST(node.STATE) then return SOLUTION(node) if (SearchUtils.isGoalState(problem, node)) { setPathCost(node.getPathCost()); return SearchUtils.actionsFromNodes(node.getPathFromRoot()); } else if (0 == limit) { // else if limit = 0 then return cutoff return cutoff(); } else { // else // cutoff_occurred? <- false bool cutoff_occurred = false; // for each action in problem.ACTIONS(node.STATE) do foreach (Node child in this.expandNode(node, problem)) { // child <- CHILD-NODE(problem, node, action) // result <- RECURSIVE-DLS(child, problem, limit - 1) List<Action> result = recursiveDLS(child, problem, limit - 1); // if result = cutoff then cutoff_occurred? <- true if (isCutOff(result)) { cutoff_occurred = true; } else if (!isFailure(result)) { // else if result != failure then return result return result; } } // if cutoff_occurred? then return cutoff else return failure if (cutoff_occurred) { return cutoff(); } else { return failure(); } } }
public abstract List<Node> getResultingNodesToAddToFrontier( Node nodeToExpand, Problem p);
public List<Action> search(Problem p) { return search.search(p, new LIFOQueue<Node>()); }
public SearchAgent(Problem p, Search search) { actionList = search.search(p); actionIterator = actionList.GetEnumerator(); searchMetrics = search.getMetrics(); }
private double getValue(Problem p, Node n) { // assumption greater heuristic value => // HIGHER on hill; 0 == goal state; // SA deals with gardient DESCENT return -1 * hf.h(n.getState()); }
// // PRIVATE METHODS // // function RBFS(problem, node, f_limit) returns a solution, or failure and // a new f-cost limit private SearchResult rbfs(Problem p, Node n, double node_f, double fLimit, int recursiveDepth) { setMaxRecursiveDepth(recursiveDepth); // if problem.GOAL-TEST(node.STATE) then return SOLUTION(node) if (SearchUtils.isGoalState(p, n)) { return new SearchResult(n, fLimit); } // successors <- [] // for each action in problem.ACTION(node.STATE) do // add CHILD-NODE(problem, node, action) into successors List<Node> successors = expandNode(n, p); // if successors is empty then return failure, infinity if (0 == successors.Count) { return new SearchResult(null, INFINITY); } double[] f = new double[successors.Count]; // for each s in successors do // update f with value from previous search, if any int size = successors.Count; for (int s = 0; s < size; s++) { // s.f <- max(s.g + s.h, node.f) f[s] = Math.max(evaluationFunction.f(successors.get(s)), node_f); } // repeat while (true) { // best <- the lowest f-value node in successors int bestIndex = getBestFValueIndex(f); // if best.f > f_limit then return failure, best.f if (f[bestIndex] > fLimit) { return new SearchResult(null, f[bestIndex]); } // if best.f > f_limit then return failure, best.f int altIndex = getNextBestFValueIndex(f, bestIndex); // result, best.f <- RBFS(problem, best, min(f_limit, alternative)) SearchResult sr = rbfs(p, successors.get(bestIndex), f[bestIndex], Math.min(fLimit, f[altIndex]), recursiveDepth + 1); f[bestIndex] = sr.getFCostLimit(); // if result != failure then return result if (sr.getOutcome() == SearchResult.SearchOutcome.SOLUTION_FOUND) { return sr; } } }
// // PRIVATE METHODS // private Node getHighestValuedNodeFrom(List<Node> children, Problem p) { double highestValue = Double.NEGATIVE_INFINITY; Node nodeWithHighestValue = null; for (int i = 0; i < children.Count; i++) { Node child = (Node) children.get(i); double value = getValue(child); if (value > highestValue) { highestValue = value; nodeWithHighestValue = child; } } return nodeWithHighestValue; }
public override List<Node> getResultingNodesToAddToFrontier(Node nodeToExpand, Problem problem) { // expand the chosen node, adding the resulting nodes to the frontier return expandNode(nodeToExpand, problem); }
public List<Action> search(Problem p) { return search.search(p, new PriorityQueue<Node>(5, getComparator())); }
protected abstract List <Action> search(Problem problem);
public abstract List <Node> getResultingNodesToAddToFrontier( Node nodeToExpand, Problem p);