Recursive Backtracking in tree structure - java

I have this algorithm and I want to implement a graph search, using recursive backtracking.
First of all my code:
public static boolean buildTree(GenericTreeNode<String> inputNode){
while(!interruptFlag)
{
try { Thread.sleep(200); } catch(InterruptedException e) {}
gui.frame.MainWindow.progress.setText("Iterations Deployment: " + c);
gui.panel.ResultMatrix.setResult(mappingList);
Multimap<String,String> openList = LinkedHashMultimap.create();
openList = UtilityClasses.getOpenList.getOpenList(dataMap, ApplicationList, HardwareList, mappingList);
if(openList.isEmpty() && !mappingList.keySet().containsAll(XMLParser.ApplicationsListGUI))
{
gui.frame.MainWindow.labelSuccess.setText("Mapping not succesful!");
return false;
}
if(openList.isEmpty() && mappingList.keySet().containsAll(XMLParser.ApplicationsListGUI))
{
System.out.println(calculateOverallCost.getOverallCosts());
System.out.println("Mapping done:" + " " + mappingList);
gui.panel.ResultMatrix.setResult(mappingList);
return true;
}
if(!openList.isEmpty() && (!mappingList.keySet().containsAll(XMLParser.ApplicationsListGUI)))
{
for(String s : openList.keySet())
{
for(String h : openList.get(s))
{
GenericTreeNode<String> child = new GenericTreeNode<String>(s + ":" + h);
inputNode.addChild(child);
child.setCosts(UtilityClasses.CostFunction.calculateCostFunction(s, h));
}
}
List<GenericTreeNode<String>> childlist = inputNode.getChildren();
Collections.sort(childlist);
for(int i = 0; i < childlist.size() ; i++)
{
inputNode = childlist.get(i);
// do something
if (buildTree(inputNode))
{
return true;
}
else
{
// undo something
}
}
Thats the code I have so far. It builds the tree in everystep. Every node in the tree is a possible solution, ordered by a heuristic costfunction. The first 2 if-clauses are the conditions to terminate and return. If there is a solution, it finds it pretty smoothly. But if there is no quick solution, I need to undo the last step and try some other combinations. In the worst case, every combination should be tested.
The childlist holds every child nodes, ordered by their costfunction. The one with the least costfunction, will be chosen for expansion. Building the tree is done recursively, but I have problems with the backtracking. I dont get the search to go back a step and try the second best node and so on. The graph is expanded every step with the new calculated openList. I saved a reference to the parent node, if that could be a help.
The openlist is a list, which holds every possible next step -> nodes.
Maybe this picture will help explaining my problem better:
thats more or less the search I wanted to realize. But the code i have till now, stucks at the end of a leave, no matter if a solution is found or not. I tried many different things, but this backtracking dont seem to work, for my kind of problem or at least I cant get it going.

If I understood correctly, this needs a pre-order tree vist.
I ommited some details, but I think this code will help you (I haven't test it):
public static boolean buildTree(GenericTreeNode<String> inputNode) {
if (interruptFlag) {
// search was interrupted
// answer has not be found yet
return false;
}
boolean something = openList.isEmpty() && !mappingList.keySet().containsAll(XMLParser.ApplicationsListGUI);
if (something) {
// ... Mapping not succesful!
// answer can't be found
return false;
}
boolean answerFound = openList.isEmpty() && (mappingList.keySet().containsAll(XMLParser.ApplicationsListGUI));
if (answerFound) {
// ...
return true;
}
// answer has not been found
// visit each children
// order children list by cost
// ...
List<GenericTreeNode<String>> childlist = // ...
Collections.sort(childlist);
for (int i = 0; i < childlist.size(); i++) {
inputNode = childlist.get(i);
// do something
boolean childHasAnswer = buildTree(inputNode);
if (childHasAnswer) {
// answer was found
return true;
} // else: our children do not have the answer
}
// neither we or our children have the answer, let's go to the parent
return false;
}
I mainly deleted the first while, and deleted the last else.

Related

Java - Content of List is lost in recursion

I'm currently programming on a little project (which is way to specific to explain here) and I got everything working except one part. I've got a List pZiegel by parameter which is modified in recursion. Because it didn't work, I did a little debugging and found the problem: At one point, the list contains exactly one number at the end of the method. Then, the program jumps one recursion depth back. And directly after that, it doesn't contains any numbers anymore. How did it lose the number? Lists as parameters work with pass-by-reference, so it shouldn't just reject it, right?
public void erstelleBaum (Tree pTree, List<Integer> pZiegel, List<Integer> pFugen, int tiefe) {
if (tiefe / n >= maxHoehe) {
System.out.println("hi");
mauerGefunden = true;
alleFugen = pFugen;
}
if (!mauerGefunden) {
pZiegel.toFirst();
while (pZiegel.hasAccess() && !mauerGefunden) {
boolean ziegelHinzufügen = false;
möglich = true;
aktZiegel = pZiegel.getContent();
// ...
if (möglich) {
// ...
pZiegel.remove();
if (pZiegel.isEmpty()) {
ziegelHinzufügen = true;
pZiegel = new List();
for (int i = 1; i <= n; i++) {
pZiegel.append(i);
}
}
// Recursion
erstelleBaum(neuesBlatt, pZiegel, neueFugen, neueTiefe);
// Here, it tells me that pZiegel is empty (at recursion depth 17)
if (ziegelHinzufügen) {
pZiegel.toFirst();
while (pZiegel.hasAccess()) {
pZiegel.remove();
}
pZiegel.append(aktZiegel);
}
else {
pZiegel.toFirst();
while (pZiegel.hasAccess() && pZiegel.getContent() < aktZiegel) {
pZiegel.next();
}
if (pZiegel.hasAccess()) {
pZiegel.insert(aktZiegel);
pZiegel.toFirst();
while (pZiegel.getContent() != aktZiegel) {
pZiegel.next();
}
}
else {
pZiegel.toLast();
pZiegel.append(aktZiegel);
pZiegel.toLast();
}
}
}
pZiegel.next();
}
}
// Here, pZiegel contained one number (at recursion depth 18)
}
I hope, the code isn't too messy. I tried to keep out the parts that doesn't involve pZiegel. And sorry, that the variables are named in german. I didn't want to change them for this post because I know I would forget to change something in the code.
Feel free to ask, if something is unclear.
I believe the pZiegel List reference is being lost at some point. You should check the pZiegel object ID (a number displayed when you inspect the object) to make sure it is the same List instance all over the recursions.
Notice that there's one part of your code that makes the pZiegel identifier reference a new List:
...
if (pZiegel.isEmpty()) {
ziegelHinzufügen = true;
pZiegel = new List(); // <---- this line
for (int i = 1; i <= n; i++) {
pZiegel.append(i);
}
}
...
I believe you are calling the 18th recursion with pZiegel referencing one list (maybe empty). Inside the 18th recursion that line is called and pZiegel starts referencing a new List (realize that the last List still exists and is referenceed by the pZiegiel identifier of the 17th recursion). On the last line of the 18th recursion call you believe you are inspecting the same pZiegiel List from the 17th recursion, but that's not the case.

Find all possible hamiltonian cycles in a partially oriented graph

This is my algorithm to find a Hamiltonian cycle in a graph:
private SolutionArray solution;
private int V, pathCount;
private int[] path;
private int[][] graph;
/**
* Constructor
*/
public ConcreteSolver() {
solution = new SolutionArray();
}
#Override
public SolutionArray solve(PathMatrix input) {
V = input.getNbVertex();
path = new int[V];
/** Set all path to non-visited **/
boolean[] visited = new boolean[V];
for (int i = 0; i < V; i++) {
visited[i] = false;
}
Arrays.fill(path, -1);
graph = input.getMatrix();
try {
path[0] = input.getFirstVertex();
pathCount = 1;
findPaths(0);
System.out.println("No solution");
} catch (Exception e) {
System.out.println("\nSolution found");
//input.printMatrix();
displayAndWrite();
}
return solution;
}
/**
* function to find paths recursively
*/
private void findPaths(int vertex) throws Exception {
/** solution **/
if (graph[vertex][0] >= 1 && pathCount == V) {
throw new Exception();
}
/** all vertices selected but last vertex not linked to 0 **/
if (pathCount == V)
return;
for (int v = 0; v < V; v++) {
/** if connected **/
if (graph[vertex][v] >= 1) {
/** add to path **/
path[pathCount++] = v;
/** if vertex not already selected solve recursively **/
if (!isPresent(v))
findPaths(v);
/** remove path **/
path[--pathCount] = -1;
}
}
}
/**
* function to check if path is already selected
*/
private boolean isPresent(int v) {
for (int i = 0; i < pathCount - 1; i++)
if (path[i] == v)
return true;
return false;
}
I'm able to find a single first Hamiltonian cycle. Is it possible to adapt it to find all possible Hamiltonian cycles found in the graph?
The input is a non-symmetrical matrix (some links between nodes are one way) and some nodes may have 2 or 3 links to other nodes.
Thank you
EDIT:
To clarify, the algorithm can already find a solution but cannot find a second one and so on. From reading, A* using bactracking might solve the issue but I'm not sure if it can be added to what I already have.
Currently you have a single array to capture the current path being explored. presumably your displayAndWrite method uses this information to print the solution.
To record all solutions you need to take a copy of the path when you find a hamiltonian cycle.
Somthing like:
private static final int MAX_SOLUTIONS = 100;
private int[][] solutions = new int[MAX_SOLUTIONS][];
private int solutionCount = 0;
private void addSolution(int[] path) {
if (solutionCount < MAX_SOLUTIONS)
solutions[solutionCoun++] = Arrays.copyOf(path, path.length);
}
You need to call addSolution in the recursive method where you currently through the exception.
As an aside, throwing an exception to denote success would be considered poor style by nearly all experienced Java coders. I expect the same is true in other languages - exceptions are for exceptions :-)
Right now, you throw an Exception when you have detected a cycle:
if (graph[vertex][0] >= 1 && pathCount == V) {
throw new Exception();
}
Aside from the fact that throwing an Exception is the wrong thing to do here because it is not really an exceptional condition - see my comment on the question - all you need to do is to make the action to take when you have found the cycle less "explosive".
Without knowing the definition of SolutionArray I can't give an answer making use of that.
Since you don't know how many cycles you might find, add a List to gather your solutions:
private List<int[]> solutions = new ArrayList<>();
Now, when you find a solution, just add something to this list - and then return from the method:
if (graph[vertex][0] >= 1 && pathCount == V) {
solutions.add(java.util.Arrays.copyOf(path, V));
return;
}
Because this simply returns from the method, rather than throwing an exception, the execution of the calling function continues on to check the next possible path.
It is important that you take a copy of the path, because otherwise you will simply add a reference to the array that you are using as your working copy - so they will all be the same array, and, because you might update it after, will not even necessarily contain a valid solution at the end.
Then, in your main method, just check if this list is non-empty:
if (!solutions.isEmpty()) {
System.out.println("\nSolution(s) found");
displayAndWrite();
}

How to change one Boolean based on values found in ArrayList?

I am trying to make a deductive Algorithm for solving a Sudoku puzzle. My Board is made up of 81 Nodes in an ArrayList.
- Each Node has a boolean Value
I want my algorithm (called CRME) to be continue to try and solve the puzzle if it finds that at least one of the nodes has it's boolean value (hasChanged) equal to true but I am unsure how to do this. canChange is also a global variable in the class this method is contained in.
public void CRME() {
canChange = true;
while (canChange == true) {
for (Node node : cells) {
scanColumn(node);
scanRow(node);
scanMiniGrid(node);
}
}
}
public void scanRow(Node n){
for(Node node : cells){
int arraySize = node.posVals.size();
ArrayList<Integer> toRemove = new ArrayList<Integer>();
if(node.get_ROW_ID() == n.get_ROW_ID()){
toRemove.add(node.getValue());
}
n.posVals.removeAll(toRemove);
if(arraySize < node.posVals.size()){
node.hasChanged = true;
}
}
}
This is the scanRow method, the two other similarly named methods are the same but with the obvious syntax changed, such as node.get_ROW_ID(); would be node.get_COL_ID();.
I assume you have a static variable
static boolean hasChanged; // in the Node class
so you can use:
node.hasChanged = true;
or you can create hasChange method to set the variable like so
boolean hasChanged;
public void hasChanged(boolean val){
this.hasChanged = val;
}
and use in the loop, like so:
hasChanged(true); or hasChanged(false);
Not saying your approach is best, but if you are trying to simply continue while one of hasChanged is true for any of your nodes, the following will suffice:
public void CRME()
{
goOn = false;
for (Node node : yourArrayListOfNodes)
{
if (node.hasChanged)
{
goOn = true;
break;
}
}
if (goOn)
{
//Insert Whatever code you want to run after the check
//.........................................
//Use recursion to repeat process
//Note recursive call will only take place if goOn is true
CRME()
}
}
This seems like what you want to do, just note that if your logic is incorrect, you can get a StackOverflowError, since you would keep making recursive calls.

Building an All Paths Algorithm for a DAG

Been trying to build a method that gets all conceivable unique paths through a DAG. Went with recursion because it seemed like the easiest to understand. Ended up with this:
public class Brutus {
//the previous nodes visited
public ArrayList<Node> resultHistory = new ArrayList<Node>();
//Directed Graph class, contains a HashMap [adjacencies]
// that has keys for all nodes that contains all edges
public AdjacencyList paths;
//A list of all the pathways between nodes represented as a list of nodes
public ArrayList<ArrayList<Node>> allPaths = new ArrayList<ArrayList<Node>>();
public Brutus(AdjacencyList paths) {
this.paths = paths;
}
public ArrayList<ArrayList<Node>> findAll() {
int counter = 1;
for (Node key : paths.adjacencies.keySet()) {
System.out.println("[" + counter + "]: " + key.toString());
StringTokenizer st = new StringTokenizer(
paths.getAdjacentString(key), ",");
while (st.hasMoreTokens()) {
String child = st.nextToken();
if (paths.getNodeFromGraph(child) != null) {
resultHistory = new ArrayList<Node>();
resultHistory.add(key);
findPath(child, resultHistory);
}
}
counter++;
}
return allPaths;
}
public void findPath(String child, ArrayList<Node> resultHistory) {
if (resultHistory.contains(paths.getNodeFromGraph(child))) {
return;
}
resultHistory.add(paths.getNodeFromGraph(child));
if(!(inList(resultHistory, allPaths))) {
allPaths.add(resultHistory);
}
StringTokenizer st = new StringTokenizer(
paths.getAdjacentString(paths.getNodeFromGraph(child)), ",");
while (st.hasMoreTokens()) {
child = st.nextToken();
if (paths.getNodeFromGraph(child) != null) {
findPath(child, resultHistory);
}
}
}
public boolean inList(ArrayList<Node> resultHistory,
ArrayList<ArrayList<Node>> allPaths) {
for (int i = 0; i < allPaths.size();i++) {
if (allPaths.get(i).equals(resultHistory)) {
return true;
}
}
return false;
}
Problem is, I don't think it works for all paths, since I can't find certain paths inside it. Although as the dataset is 900 nodes, I am unable to find a pattern! Other questions on Stack seem to be somewhat more specialized and as such I attempted to build my own algorithm!
Can anyone either suggest a superior way to perform this, or tell me what I've done wrong?
If the algorithms correct, what would be the best way to withdraw all the paths between two nodes?
EDIT: I now realize that new paths don't get created from child nodes of the original, how would I make it so it does?
Here there is an implementation based on the BFS algorithm.
I will denote a path as a sequence of vertices l = (v, v', v'', ...) and I will perform the following two operations on it:
extend(l, v): puts vertex v at the end of list l;
v = back(l): gets the last vertex in list l.
FindPaths(G, v) {
// The first path is, simply, the starting node.
// It should be the first vertex in topological order.
pending_paths = {(v)};
while (pending_paths is not empty) {
l = pending_paths.remove_first(); // pop the first pending path
output(l); // output it (or save it in a list to be returned, if you prefer)
v = back(l); // Get the last vertex of the path
foreach(edge (v, v') in G) { // For each edge outgoing from v'...
// extend l with v' and put into the list of paths to be examined.
pending_paths.push_back(extend(l, v'));
}
}
}
Here's a simple recursive algorithm, expressed in pseudocode to avoid clouding the issue with lots of Java list manipulation:
AllPaths(currentNode):
result = EmptyList()
foreach child in children(node):
subpaths = AllPaths(child)
foreach subpath in subpaths:
Append(result, currentNode + subpath)
return result
Calling AllPaths on the root node will give you what you need, and you can improve the running time for nontrivial DAGs by caching the result of AllPaths on each node, so you only need to compute it once rather than once per distinct path that includes it.
So while #akappa's Pseudo was a good start, it took me awhile to understand how to make it work, if anyone else comes across this post here's how I did it:
public ArrayList<ArrayList<Node>> searchAll() {
try {
BufferedWriter out = new BufferedWriter(new FileWriter("output.txt"));
//Gets Nodes from Hashmap and puts them into Queue
for (Node key : paths.adjacencies.keySet()) {
queue.addToQueue(new QueueItem(key.chemName, new ArrayList<Node>()));
}
while (queue.getSize() > 0) {
QueueItem queueItem = queue.getFromQueue();
Node node = paths.getNodeFromGraph(queueItem.getNodeId());
if (node != null) {
findRelationAll(node, queueItem, out);
}
}
System.out.println("Cycle complete: Number of Edges: [" + resultHistoryAll.size() + "]");
out.close();
} catch (IOException e) {
}
return resultHistoryAll;
}
public void findRelationAll(Node node, QueueItem queueItem, BufferedWriter out) {
if (!foundRelation) {
StringTokenizer st = new StringTokenizer(paths.getAdjacentString(node), ",");
while (st.hasMoreTokens()) {
String child = st.nextToken();
ArrayList<Node> history = new ArrayList<Node>();
//Gets previous Nodes
history.addAll(queueItem.getHistoryPath());
//Makes sure path is unique
if (history.contains(node)) {
System.out.println("[" + counter2 + "]: Cyclic");
counter2++;
continue;
}
history.add(node);
resultHistory = history;
queue.addToQueue(new QueueItem(child, history));
if (!(inList(resultHistory, resultHistoryAll))) {
resultHistoryAll.add(resultHistory);
try {
out.write("[" + counter + "]: " + resultHistory.toString());
out.newLine();
out.newLine();
} catch (IOException e) {
}
System.out.println("[" + counter + "]: " + resultHistory.toString());
counter++;
} else {
System.out.println("[" + counter3 + "]: InList");
counter3++;
}
}
}
}
//This checks path isn't in List already
public boolean inList(ArrayList<Node> resultHistory, ArrayList<ArrayList<Node>> allPaths) {
for (int i = 0; i < allPaths.size(); i++) {
if (allPaths.get(i).equals(resultHistory)) {
return true;
}
}
return false;
}
}
The above code does a few extra things that you might not want:
It writes pathways to a text file as a list of nodes + it's counter value.
Makes sure the path doesn't cross the same node twice
Makes sure no two pathways are the same in the final list (in normal circumstances this is unnecessary work)
The QueueItem object is just a way to store the previously visited nodes. It's part of nemanja's code, which is what my code was based off.
Hat tip to him, akappa (for the most efficient answer), and jacobm (for finding a solution like my original code, and explaining it's limitations).
Incase anyone's actually interested in the work; I'm currently processing over 5 million pathways, of which 60,000 are unique pathways between 900 chemicals. And that's just 1,2,3 or 4 chemical pathways... Biology is complicated.
EDIT and Warning: IF anyone is handling huge reams of data like me, windows 7 - or at least my machine - throws a shit fit and closes the program after an ArrayList > 63,000 objects, regardless of how you arrange the pointers. The solution I started with was after 60,000 objects, restarting the list while adding everything to CSV. This led to some duplicates between list iteration, and should ultimately be surpassed by my moving to linux tomorrow!

Help making a singly linked list in Java

This is for homework but please know that I have looked online for help (such as http://www.sethi.org/classes/class_stuff/cis435/others/notes-java/data/collections/lists/simple-linked-list.html) and my textbook but I am still having some issues.
Any help would be appreciated...
Right now I'm trying to just insert values in but nothing is working. Whether it's the first item, whether it's being added as the last one, or somewhere in between.
Node header = null; // First element of list.
Node back = null; // Last element of list.
public void insert(int i, double value){ //insert value before i-th element
Node e = new Node();
e.num = value;
Node curr = header;
for(int x=0;x<i;x++) {
if (i == 1) { //we want to insert as first thing
if (size == 0) { //its the FIRST time we add something
header.next = e;
e.next = back;
break;
} else if (size == 1){
e.next = header.next; //i.e. the second thing in the list
header.next = e;
break;
} else {
e.next = header.next.next; //i.e. the second thing in the list
header.next = e;
break;
}
}
else if (x == (i-1)) {
e.next = curr.next;
curr.next = e;
break;
}
curr = curr.next;
}
size = size+1;
}
Not really sure why it isn't working.
Thanks!
For some reason, people who are still learning to program make things far more complicated then they need to be. I did it when I was learning java, I still do it when I am just getting into a new language, and students that I have marked find new and amazing ways to do it. You have more going on in your insert then there needs to be, for example, a method that inserts a value at a specific index should not check if it's the first item to be inserted (not saying it shouldn't check bounds). Here is the pseudo code of what I would do.
insert(index, value)
if index>size
throw null pointer
traverse to index -1 //lets call this nodeI
create newnode and set value
set newnode.next to nodeI.next
set nodeI.next to newnode
increase size.
Couple of handy hints for you, you should have a function to get an element from the link list, something that returns a node? public node elementAt(int index) for example? use that to traverse the linked list. If you want to append to the Linked list, try this
append(value)
insert(size-1,value)
and if you want to insert at the beginning? same idea
insert(value)
insert(0,value)
In the line e.next = header.next.next what would happen if header.next points to a 'null'? Is it possible to get there?
What are the corner cases you have to deal with and have you taken them all into account?
Can you start with the simplest case first, adding either an element to the front or an element to the back? Then use those functions to implement the insert?
A few suggestions:
implement java.util.List
Think about generics
Read this.
Start with "insert at the end" before you think about "insert at i".
I have tried a simple program, which will be useful for you guys, I am also learning Java, please bear with me for any mistakes, but this program works fine.
I am posting a very simple singly linked list program in Java, which I tried out today.
I hope it will help all.
LinkList.java
class LinkList
{
public static void main(String args[])
{
Node node = new Node(1);
node.addAtLast(2);
node.addAtLast(3);
node.addAtLast(4);
node.addAtLast(5);
node.printList();
}
}
Node.java
class Node
{
private int data;
private Node link;
public Node(int mydata)
{
data = mydata;
link = null;
}
public void printList()
{
System.out.print("|"+data+"|"+"->");
if(link != null)
{
//recursive call
link.printList();
}
else
{
//marking end of list as NULL
System.out.print("|NULL|");
}
}
public void addAtLast(int mydata)
{
if(link == null)
{
link = new Node(mydata);
}
else
{
link.addAtLast(mydata);
}
}
}
OUTPUT :
The below is our output
|1|->|2|->|3|->|4|->|5|->|NULL|

Categories