All Downloads are FREE. Search and download functionalities are using the official Maven repository.

aima.core.search.framework.qsearch.GraphSearch Maven / Gradle / Ivy

Go to download

AIMA-Java Core Algorithms from the book Artificial Intelligence a Modern Approach 3rd Ed.

The newest version!
package aima.core.search.framework.qsearch;

import java.util.HashSet;
import java.util.Queue;
import java.util.Set;

import aima.core.search.framework.Node;
import aima.core.search.framework.NodeExpander;
import aima.core.search.framework.problem.Problem;

/**
 * Artificial Intelligence A Modern Approach (3rd Edition): Figure 3.7, page 77.
 * 
* *
 * function GRAPH-SEARCH(problem) returns a solution, or failure
 *   initialize the frontier using the initial state of problem
 *   initialize the explored set to be empty
 *   loop do
 *     if the frontier is empty then return failure
 *     choose a leaf node and remove it from the frontier
 *     if the node contains a goal state then return the corresponding solution
 *     add the node to the explored set
 *     expand the chosen node, adding the resulting nodes to the frontier
 *       only if not in the frontier or explored set
 * 
* * Figure 3.7 An informal description of the general graph-search algorithm. *
* This implementation is based on the template method * {@link QueueSearch#findNode(Problem, Queue)} of the superclass and provides * implementations for the needed primitive operations. In contrast to the code * above, here, nodes resulting from node expansion are added to the frontier * even if nodes for the same states already exist there. This makes it possible * to use the implementation also in combination with priority queue frontiers. * This implementation avoids linear costs for frontier node removal (compared * to {@link GraphSearchReducedFrontier}) and gets by without node comparator * knowledge. * * @author Ruediger Lunde */ public class GraphSearch extends QueueSearch { private Set explored = new HashSet(); public GraphSearch() { this(new NodeExpander()); } public GraphSearch(NodeExpander nodeExpander) { super(nodeExpander); } /** * Clears the set of explored states and calls the search implementation of * {@link QueueSearch}. */ @Override public Node findNode(Problem problem, Queue frontier) { // initialize the explored set to be empty explored.clear(); return super.findNode(problem, frontier); } /** * Inserts the node at the tail of the frontier if the corresponding state * was not yet explored. */ @Override protected void addToFrontier(Node node) { if (!explored.contains(node.getState())) { frontier.add(node); updateMetrics(frontier.size()); } } /** * Removes the node at the head of the frontier, adds the corresponding * state to the explored set, and returns the node. Leading nodes of already * explored states are dropped. So the resulting node state will always be * unexplored yet. * * @return the node at the head of the frontier. */ @Override protected Node removeFromFrontier() { cleanUpFrontier(); // not really necessary because isFrontierEmpty // should be called before... Node result = frontier.remove(); explored.add(result.getState()); updateMetrics(frontier.size()); return result; } /** * Pops nodes of already explored states from the head of the frontier * and checks whether there are still some nodes left. */ @Override protected boolean isFrontierEmpty() { cleanUpFrontier(); updateMetrics(frontier.size()); return frontier.isEmpty(); } /** * Helper method which removes nodes of already explored states from the head * of the frontier. */ private void cleanUpFrontier() { while (!frontier.isEmpty() && explored.contains(frontier.element().getState())) frontier.remove(); } }