I am currently doing an assignment where we need to find a path from a node on an undirected graph, the start node, to the destination node without changing the type of edge (each edge is labelled with a letter) more than a specified amount of times. (E.g. If only one change is allowed, then going from an edge labelled 'a' to an edge labelled 'b' will use up that one change. But going from 'a' to 'a' will not use up any changes). We can only use Depth First Search (DFS) for traversing the tree. The graph is in a rectangular/square shaped grid format, so each node can have a minimum of 1 or 2 edges (these nodes are either just connected to one node or at the corner of the graph and connected to two nodes) and a maximum of 4 edges.
My algorithm uses DFS to traverse through the graph and finds every solution/path possible from start to end, then finds the number of changes each solution/path would require and will then return the solution that requires the minimum amount of changes if that number of changes is smaller or equal to the number of allowed changes. This does work most of the time, however, when the graph size is 18 nodes across x 18 nodes down, and above, it takes too long to come up with an answer or just plain crashes.
So I am just wondering if there is a much more efficient way of doing this? Is there any way to alter my code to make it more efficient?
//The solver method that returns the solution
public Iterator<GraphNode> solve() throws GraphException {
GraphNode startNode = graph.getNode(startLoc); //Creates the starting node.
GraphNode endNode = graph.getNode(endLoc); //Creates the ending node.
pathDepthFirstSearch(graph, startNode, endNode);
int smallest = findSmallestChangeSolution(listOfSolutions);
if(smallest == -1) {
return null;
}
return listOfSolutions.get(smallest).iterator();
}
//DFS traversal and add the nodes along a path to an ArrayList.
private void pathDepthFirstSearch(Graph graph, GraphNode u, GraphNode v) throws GraphException {
listOfNodes.add(u);
u.setMark(true);
if(u.getName() == v.getName()) {
addSolutionToList(new ArrayList<GraphNode>(listOfNodes));
} else {
for (Iterator<GraphEdge> iter = graph.incidentEdges(u); iter.hasNext();) {
GraphEdge nextEdge = iter.next();
GraphNode secondEndPoint = nextEdge.secondEndpoint();
if(secondEndPoint.getMark() == false) {
pathDepthFirstSearch(graph,secondEndPoint, v);
}
}
}
listOfNodes.remove(u);
u.setMark(false);
}
//Adds the each solution to an ArrayList
private void addSolutionToList(ArrayList<GraphNode> list) {
ArrayList<GraphNode> tempList = new ArrayList<GraphNode>();
for (int i = 0; i < list.size(); i++) {
tempList.add(list.get(i));
}
listOfSolutions.add(tempList);
}
//Finds the solution with the smallest number of changes and returns the
//index of the solution list with that number of changes.
private int findSmallestChangeSolution(ArrayList<ArrayList<GraphNode>> list) throws GraphException {
int changes = 0;
int[] changesForEachSolution = new int[list.size()];
for (int i = 0; i < list.size(); i++) {
for(int j = 0; j < list.get(i).size() - 2; j++) {
if(graph.getEdge(list.get(i).get(j), list.get(i).get(j+1)).getLabel() != graph.getEdge(list.get(i).get(j+1), list.get(i).get(j+2)).getLabel()) {
changes++; //Increments the number of changes by 1 if the two consecutive edges have different labels.
}
}
changesForEachSolution[i] = changes;
changes = 0; //Resets the number of changes to 0 for the next solution.
}
//Finds the position of the solution with the smallest number of changes.
int smallest = changesForEachSolution[0];
int indexOfSmallest = 0;
for(int i = 0; i < changesForEachSolution.length; i++) {
if(changesForEachSolution[i] < smallest) {
smallest = changesForEachSolution[i];
indexOfSmallest = i;
}
}
//If the smallest number of changes is larger than the allowed number of changes, no solution exists, so return -1.
if(smallest > kNumOfChanges) {
return -1;
}
//Otherwise, the index of the solution is returned.
return indexOfSmallest;
}
I have also tried altering the code a bit so that the recursive calls in the DFS method stops if a valid solution is found, but it didn't seem to make a difference with larger graphs (anything larger than 18 x 18).