package aima.core.search.uninformed; import java.util.List; import aima.core.agent.Action; import aima.core.search.framework.GraphSearch; import aima.core.search.framework.Metrics; import aima.core.search.framework.Node; import aima.core.search.framework.Problem; import aima.core.search.framework.QueueSearch; import aima.core.search.framework.Search; import aima.core.util.datastructure.FIFOQueue; /** * Artificial Intelligence A Modern Approach (3rd Edition): Figure 3.11, page * 82.<br> * <br> * * <pre> * function BREADTH-FIRST-SEARCH(problem) returns a solution, or failure * node <- a node with STATE = problem.INITIAL-STATE, PATH-COST=0 * if problem.GOAL-TEST(node.STATE) then return SOLUTION(node) * frontier <- a FIFO queue with node as the only element * explored <- an empty set * loop do * if EMPTY?(frontier) then return failure * node <- POP(frontier) // chooses the shallowest node in frontier * add node.STATE to explored * for each action in problem.ACTIONS(node.STATE) do * child <- CHILD-NODE(problem, node, action) * if child.STATE is not in explored or frontier then * if problem.GOAL-TEST(child.STATE) then return SOLUTION(child) * frontier <- INSERT(child, frontier) * </pre> * * Figure 3.11 Breadth-first search on a graph.<br> * <br> * <b>Note:</b> Supports both Tree and Graph based versions by assigning an * instance of TreeSearch or GraphSearch to its constructor. * * @author Ciaran O'Reilly */ public class BreadthFirstSearch implements Search { private final QueueSearch search; public BreadthFirstSearch() { this(new GraphSearch()); } public BreadthFirstSearch(QueueSearch search) { // Goal test is to be applied to each node when it is generated // rather than when it is selected for expansion. search.setCheckGoalBeforeAddingToFrontier(true); this.search = search; } public List<Action> search(Problem p) { return search.search(p, new FIFOQueue<Node>()); } public Metrics getMetrics() { return search.getMetrics(); } }