TDDC17AICourse/lab2/CustomGraphSearch.java
2021-08-22 13:07:04 +02:00

141 wiersze
5,3 KiB
Java

package searchCustom;
import java.util.ArrayList;
import java.util.HashSet;
import searchShared.NodeQueue;
import searchShared.Problem;
import searchShared.SearchObject;
import searchShared.SearchNode;
import world.GridPos;
public class CustomGraphSearch implements SearchObject {
private HashSet<SearchNode> explored;
private NodeQueue frontier;
protected ArrayList<SearchNode> path;
private boolean insertFront;
/**
* The constructor tells graph search whether it should insert nodes to front or back of the frontier
*/
public CustomGraphSearch(boolean bInsertFront) {
insertFront = bInsertFront;
}
/**
* Implements "graph search", which is the foundation of many search algorithms
*/
public ArrayList<SearchNode> search(Problem problem) {
// The frontier is a queue of expanded SearchNodes not processed yet
frontier = new NodeQueue();
// The explored set is a set of nodes that have been processed
explored = new HashSet<SearchNode>();
// The start state is given
GridPos startState = (GridPos) problem.getInitialState();
// Initialise the frontier with the start state
frontier.addNodeToFront(new SearchNode(startState));
// Path will be empty until we find the goal.
path = new ArrayList<SearchNode>();
/*
* Note on how java and this program work:
* -ArrayList are just resizable array. "<>" contains the type of the listed objects
* -Structures :
* while (boolean) {}
* while (a > 0) {}
* for (int i = 0; i < 5; i++){} --> 5 iterations
* for (String i : StringList){} --> Iterations on all the objects in the list
* -Class used here:
* -SearchNode --> Equivalent of the "Node" class in the Python program. Represent a node.
* -Problem --> Class containing lot of informations on the problem
* like the reachable states from a position, the start, the end
* -GridPos --> represent a position (with x and y coordinates)
*/
// While we have something to explore
while (frontier.size() > 0) {
// Get the first node on the list
SearchNode Node = frontier.removeFirst();
// We check if it is our destination
if (problem.isGoalState(Node.getState())) {
return path = Node.getPathFromRoot();
} // if not, we continue
// Get the list of children of the current node
ArrayList<GridPos> childPosition = problem.getReachableStatesFrom(Node.getState());
// For every child in the list
for (GridPos position : childPosition) {
// Creating a new node
SearchNode childNode = new SearchNode(position, Node);
// If we have not explored the node
if (explored.contains(childNode) == false) {
// Adding the child node to the frontier
// Front --> DFS (LIFO queue)
// Back --> BFS (FIFO queue)
if (insertFront) {
frontier.addNodeToFront(childNode);
}
else {
frontier.addNodeToBack(childNode);
}
// We add the node to explored node
explored.add(childNode);
}
}
}
/* Some hints:
* -Read early part of chapter 3 in the book!
* -You are free to change anything how you wish as long as the program runs, but some structure is given to help you.
* -You can Google for "javadoc <class>" if you are uncertain of what you can do with a particular Java type.
*
* -SearchNodes are the nodes of the search tree and contains the relevant problem state, in this case x,y position (GridPos) of the agent
* --You can create a new search node from a state by: SearchNode childNode = new SearchNode(childState, currentNode);
* --You can also extract the state by .getState() method
* --All search structures use search nodes, but the problem object only speaks in state, so you may need to convert between them
*
* -The frontier is a queue of search nodes, open this class to find out what you can do with it!
*
* -If you are unfamiliar with Java, the "HashSet<SearchNode>" used for the explored set means a set of SearchNode objects.
* --You can add nodes to the explored set, or check if it contains a node!
*
* -To get the child states (adjacent grid positions that are not walls) of a particular search node, do: ArrayList<GridPos> childStates = p.getReachableStatesFrom(currentState);
*
* -Depending on the addNodesToFront boolean variable, you may need to do something with the frontier... (see book)
*
* -You can check if you have reached the goal with p.isGoalState(NodeState)
*
* When the goal is found, the path to be returned can be found by: path = node.getPathFromRoot();
*/
/* Note: Returning an empty path signals that no path exists */
return path;
}
/*
* Functions below are just getters used externally by the program
*/
public ArrayList<SearchNode> getPath() {
return path;
}
public ArrayList<SearchNode> getFrontierNodes() {
return new ArrayList<SearchNode>(frontier.toList());
}
public ArrayList<SearchNode> getExploredNodes() {
return new ArrayList<SearchNode>(explored);
}
public ArrayList<SearchNode> getAllExpandedNodes() {
ArrayList<SearchNode> allNodes = new ArrayList<SearchNode>();
allNodes.addAll(getFrontierNodes());
allNodes.addAll(getExploredNodes());
return allNodes;
}
}