I created a generic version of IDA*. I am attempting to create the following code with exceptional quality and performance. I'm hoping to try and create short code tutorials regarding. However, the quality of my code may not be up to standard for a tutorial on the subject. I attempted to closely follow the pseudocode from here. Please let me know if you can think of any improvements I can make to the following.
public interface Node<T extends Node<T>> {
public T[] getChildren();
public T[] getVisitedNodes();
public int getCost();
}
public class IDAStar {
/**
* Takes in a Node<T> vb, a Heuristic using the Node<T>(This is an anonymous function) and a Goal.
* Returns a List of the visited nodes or null if it could not find the desired node.
* Note: This could run forever if it can't find the given node and there are an infinite number of nodes to process.
* @param vb
* @param h
* @param g
* @return
*/
public static <T extends Node<T>> List<T> IDA_Star(T vb, Heuristic<T> h, Goal<T> g)
{
int bound=h.getHeuristic(vb);
while(true)
{
IDAStarRet<T> found=search(vb, 0, bound, h, g);
switch(found.getSearchReturn())
{
case BOUND:
bound=found.getHeuristic();
break;
case FOUND:
return found.getVisitedNodes();
case NOT_FOUND:
return null;
}
}
}
private static <T extends Node<T>> IDAStarRet<T> search(T currentNode, int currentCost, int bound, Heuristic<T> h, Goal<T> goal) {
int estimatedCost=currentCost+h.getHeuristic(currentNode);
IDAStarRet<T> ret=new IDAStarRet<T>();
//If estimatedCost is greater than the bound, return and set the new bound appropriately.
if(estimatedCost>bound)
{
ret.setSearchReturn(SEARCHRETURN.BOUND);
ret.setHeuristic(estimatedCost);
return ret;
}
//Check if the currentNode is the goal.
if(goal.isGoal(currentNode))
{
ret.setSearchReturn(SEARCHRETURN.FOUND);
ret.setVisitedNodes(Arrays.asList(currentNode.getVisitedNodes()));
return ret;
}
//Set to an arbitrarily large value, to make sure that any available values replace this.
int min=Integer.MAX_VALUE;
//Iterate through all of the current nodes children.
//Should I sort the children based on the heuristic here?
//Note: This was a bad idea. Sorting decreased the speed significantly.
for(T successor:currentNode.getChildren())
{
//Get the return value for each of the children.
IDAStarRet<T> t=search(successor, currentCost+successor.getCost(), bound, h, goal);
switch(t.getSearchReturn())
{
case BOUND:
if(t.getHeuristic()<min)
min=t.getHeuristic();
break;
case FOUND:
return t;
case NOT_FOUND:
continue;
}
}
//If the minimum did not change, then the node could not be found.
if(min==Integer.MAX_VALUE)
{
ret.setSearchReturn(SEARCHRETURN.NOT_FOUND);
}
else
{
ret.setHeuristic(min);
ret.setSearchReturn(SEARCHRETURN.BOUND);
}
return ret;
}
public static interface Heuristic <T>
{
public int getHeuristic(T item);
}
public static interface Goal <T>
{
public boolean isGoal(T n);
}
private static enum SEARCHRETURN { BOUND, FOUND, NOT_FOUND };
/**
* Returns a value associated with IDA*.
* If it is found, it will return a list of visited nodes.
* Otherwise it will return a heuristic or NOT FOUND.
*
* @param <T>
*/
private static class IDAStarRet <T extends Node<T>> {
private SEARCHRETURN sr;
private int newHeuristic;
private List<T> visitedNodes;
public SEARCHRETURN getSearchReturn()
{
return sr;
}
public void setSearchReturn(SEARCHRETURN sr)
{
this.sr=sr;
}
public void setHeuristic(int newHeuristic)
{
this.newHeuristic=newHeuristic;
}
public int getHeuristic()
{
return newHeuristic;
}
public void setVisitedNodes(List<T> visitedNodes)
{
this.visitedNodes=visitedNodes;
}
public List<T> getVisitedNodes()
{
return this.visitedNodes;
}
}
}