From 90249546780085050b8d93d927a5a8a729511eb5 Mon Sep 17 00:00:00 2001 From: jsuyash1514 Date: Mon, 4 Mar 2019 03:11:27 +0530 Subject: [PATCH 1/2] Update Graph search algorithm as per the pseudo code --- .../search/basic/uninformed/GraphSearch.java | 103 ++++++++---------- 1 file changed, 48 insertions(+), 55 deletions(-) diff --git a/core/src/main/java/aima/core/search/basic/uninformed/GraphSearch.java b/core/src/main/java/aima/core/search/basic/uninformed/GraphSearch.java index 4a42f267f0..6b186ddea5 100644 --- a/core/src/main/java/aima/core/search/basic/uninformed/GraphSearch.java +++ b/core/src/main/java/aima/core/search/basic/uninformed/GraphSearch.java @@ -1,19 +1,11 @@ package aima.core.search.basic.uninformed; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Queue; -import java.util.Set; - -import aima.core.search.api.Node; -import aima.core.search.api.NodeFactory; -import aima.core.search.api.Problem; -import aima.core.search.api.SearchController; -import aima.core.search.api.SearchForActionsFunction; +import aima.core.search.api.*; import aima.core.search.basic.support.BasicNodeFactory; import aima.core.search.basic.support.BasicSearchController; +import java.util.*; + /** * Artificial Intelligence A Modern Approach (4th Edition): Figure ??, page ??. *
@@ -31,84 +23,85 @@ * expand the chosen node, adding the resulting nodes to the frontier * only if not in the frontier or explored set * - * + *

* Figure ?? An informal description of the general graph-search algorithm. * - * * @author Ciaran O'Reilly */ public class GraphSearch implements SearchForActionsFunction { + + // + // Supporting Code + protected NodeFactory nodeFactory = new BasicNodeFactory<>(); + protected SearchController searchController = new BasicSearchController(); + + public GraphSearch() { + } // function GRAPH-SEARCH(problem) returns a solution, or failure @Override public List apply(Problem problem) { // initialize the frontier using the initial state of problem Queue> frontier = newFrontier(problem.initialState()); - // initialize the explored set to be empty - Set explored = newExploredSet(); + // initialize the reached table to be empty + Map> reached = new HashMap<>(); + // initialize the solution + List solution = failure(); + + // if the frontier is empty then return failure + if (frontier.isEmpty()) { + return failure(); + } // loop do - while (true) { - // if the frontier is empty then return failure - if (frontier.isEmpty()) { - return failure(); - } + while (!frontier.isEmpty()) { // choose a leaf node and remove it from the frontier - Node node = frontier.remove(); - // if the node contains a goal state then return the corresponding - // solution - if (isGoalState(node, problem)) { - return solution(node); - } - // add the node to the explored set - explored.add(node.state()); - // expand the chosen node, adding the resulting nodes to the - // frontier - for (A action : problem.actions(node.state())) { - Node child = newChildNode(problem, node, action); - // only if not in the frontier or explored set - if (!(containsState(frontier, child) || explored.contains(child.state()))) { + Node parent = frontier.remove(); + // expand the chosen node + for (Node child : expand(problem, parent)) { + // only if the child is not in reached or child is a cheaper path than reached[child.state()] + if (!reached.containsKey(child.state()) || child.pathCost() < reached.get(child.state()).pathCost()) { + // add child in reached and frontier + reached.put(child.state(), child); frontier.add(child); + // if child is a goal and is cheaper than the best solution found so far then update the solution + if (isGoalState(child, problem)){ + solution = getSolution(child); + } } } } + return solution; } - - // - // Supporting Code - protected NodeFactory nodeFactory = new BasicNodeFactory<>(); - protected SearchController searchController = new BasicSearchController(); - - public GraphSearch() { + + public List> expand(Problem problem, Node parent) { + List> nodes = new ArrayList<>(); + for (A action : problem.actions(parent.state())) { + Node node = newChildNode(problem, parent, action); + nodes.add(node); + } + return nodes; } - + public Node newChildNode(Problem problem, Node node, A action) { return nodeFactory.newChildNode(problem, node, action); } - + public Queue> newFrontier(S initialState) { Queue> frontier = new LinkedList<>(); frontier.add(nodeFactory.newRootNode(initialState)); return frontier; } - - public Set newExploredSet() { - return new HashSet<>(); - } - + public List failure() { return searchController.failure(); } - public List solution(Node node) { + public List getSolution(Node node) { return searchController.solution(node); } - + public boolean isGoalState(Node node, Problem problem) { return searchController.isGoalState(node, problem); } - - public boolean containsState(Queue> frontier, Node child) { - // NOTE: Not very efficient (i.e. linear in the size of the frontier) - return frontier.stream().anyMatch(frontierNode -> frontierNode.state().equals(child.state())); - } + } From 853be48d187cae66ef369117b913b78dc1582a0e Mon Sep 17 00:00:00 2001 From: jsuyash1514 Date: Mon, 4 Mar 2019 03:30:32 +0530 Subject: [PATCH 2/2] Code improvements --- .../aima/core/search/basic/uninformed/GraphSearch.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/aima/core/search/basic/uninformed/GraphSearch.java b/core/src/main/java/aima/core/search/basic/uninformed/GraphSearch.java index 6b186ddea5..3a81d56d99 100644 --- a/core/src/main/java/aima/core/search/basic/uninformed/GraphSearch.java +++ b/core/src/main/java/aima/core/search/basic/uninformed/GraphSearch.java @@ -30,14 +30,13 @@ */ public class GraphSearch implements SearchForActionsFunction { - // - // Supporting Code protected NodeFactory nodeFactory = new BasicNodeFactory<>(); protected SearchController searchController = new BasicSearchController(); public GraphSearch() { + //empty constructor } - + // function GRAPH-SEARCH(problem) returns a solution, or failure @Override public List apply(Problem problem) { @@ -64,7 +63,7 @@ public List apply(Problem problem) { reached.put(child.state(), child); frontier.add(child); // if child is a goal and is cheaper than the best solution found so far then update the solution - if (isGoalState(child, problem)){ + if (isGoalState(child, problem)) { solution = getSolution(child); } } @@ -95,7 +94,7 @@ public Queue> newFrontier(S initialState) { public List failure() { return searchController.failure(); } - + public List getSolution(Node node) { return searchController.solution(node); }