001    /*
002     * Created on Sep 8, 2004
003     *
004     */
005    package aima.search.uninformed;
006    
007    import java.util.ArrayList;
008    import java.util.List;
009    
010    import aima.search.framework.Metrics;
011    import aima.search.framework.NodeExpander;
012    import aima.search.framework.Problem;
013    import aima.search.framework.Search;
014    
015    /**
016     * Artificial Intelligence A Modern Approach (2nd Edition): Figure 3.14, page
017     * 78.
018     * 
019     * <code>
020     * function ITERATIVE-DEEPENING-SEARCH(problem) returns a solution, or failure
021     *   inputs: problem, a problem
022     *   
023     *   for depth <- to infinity  do
024     *     result <- DEPTH-LIMITED-SEARCH(problem, depth)
025     *     if result != cutoff then return result
026     * </code>
027     * Figure 3.14 The iterative deepening search algorithm, which repeatedly
028     * applies depth- limited search with increasing limits. It terminates when a
029     * solution is found or if the depth- limited search returns failure, meaning
030     * that no solution exists.
031     */
032    
033    /**
034     * @author Ravi Mohan
035     * 
036     */
037    public class IterativeDeepeningSearch extends NodeExpander implements Search {
038            private static String PATH_COST = "pathCost";
039    
040            private final int limit;
041    
042            private final Metrics iterationMetrics;
043    
044            public IterativeDeepeningSearch() {
045                    this.limit = Integer.MAX_VALUE;
046                    iterationMetrics = new Metrics();
047                    iterationMetrics.set(NODES_EXPANDED, 0);
048                    iterationMetrics.set(PATH_COST, 0);
049            }
050    
051            // function ITERATIVE-DEEPENING-SEARCH(problem) returns a solution, or
052            // failure
053            // inputs: problem, a problem
054            public List search(Problem p) throws Exception {
055                    iterationMetrics.set(NODES_EXPANDED, 0);
056                    iterationMetrics.set(PATH_COST, 0);
057                    // for depth <- to infinity do
058                    for (int i = 1; i <= limit; i++) {
059                            // result <- DEPTH-LIMITED-SEARCH(problem, depth)
060                            DepthLimitedSearch dls = new DepthLimitedSearch(i);
061                            List result = dls.search(p);
062                            iterationMetrics.set(NODES_EXPANDED, iterationMetrics
063                                            .getInt(NODES_EXPANDED)
064                                            + dls.getMetrics().getInt(NODES_EXPANDED));
065                            // if result != cutoff then return result
066                            if (!cutOffResult(result)) {
067                                    iterationMetrics.set(PATH_COST, dls.getPathCost());
068                                    return result;
069                            }
070                    }
071                    return new ArrayList();// failure
072            }
073    
074            private boolean cutOffResult(List result) { // TODO remove this duplication
075    
076                    return result.size() == 1 && result.get(0).equals("cutoff");
077            }
078    
079            @Override
080            public Metrics getMetrics() {
081                    return iterationMetrics;
082            }
083    
084    }