Recursive algorithms and StackOverFlow Error - java

I have been coding a recursive algorithm in order to go through different nodes and analyze all the paths in a directed acyclic graph. The thing is that, after some new data has been introduced to the algorithm I get this message Exception in thread "AWT-EventQueue-0" java.lang.StackOverflowError. I have looked through different questions about this and it seems that the error is because of insufficient memory. Could anyone help me to solve this problem?
Here I add a picture of the recursive algorithm:
public boolean checkduration(Node node, double dur, int freq){
boolean outcome=true;
currentPath.add(node);
if((dur>minduration)&&(node.getRep()<=node.getMaxRep())){
ArrayList<Node> clone = (ArrayList<Node>) currentPath.clone();
currentPath2=clone;
failingPaths.add(new ImmutableTriple<Double,Integer, ArrayList<Node>> (dur,freq,currentPath2));
currentPath.remove(node);
return false;
}
node.setRep(node.getRep()+1);
for(int i=0;i<node.getEdge().size();i++){
if(!checkduration(node.getEdge().get(i).previousNode,dur+node.getEdge().get(i).timeRelation, freq+node.getEdge().get(i).frequency)){
outcome=false;
}
}
currentPath.remove(node);
node.setRep(node.getRep()-1);
return outcome;
}
The error seems to be in the condition of (if(!checkduration(node.getEdge().get(i).previousNode,dur+node.getEdge().get(i).timeRelation, freq+node.getEdge().get(i).frequency))) but I do not understand why it works with some data and not always as not so much information has been changed.
Any comments, suggestions would be truly helpful. Thanks to everyone

The StackOverflowError is occurring because you are recursing too many times. And if there are too many recursive calls, that means there is a flaw or incorrect assumption in your terminating condition. Here is your terminating condition:
(dur > minduration) && (node.getRep() <= node.getMaxRep())
Since you have not provided enough information with your question for us to analyze your graph or nodes further, I would suggest you take a closer look at this terminating condition, and make sure that every traversal of the graph will eventually fulfill this condition.
The use of the debugger can also help you to step through the traversal and see where the cycle is occurring, and why it fails to satisfy the terminal condition.

Your graph traversal seems inefficient, since you are counting repetitions per each node, how many times you have visited and you limit your effort by adding some maxRep
All you need is the set of visited nodes, rather than increment of a counter for each node, when you visit it.
Does you DAG have many roots? Is the lack of cycles guaranteed, or do you need to detect cycles?
Please also note that you don't need cloning of paths.

Related

Does a partial traversal of a linked-list count as "one pass" of the list?

I've been going through algorithm challenges on LeetCode and just completed "Remove Nth Node From End of List".
Many of the top answers claimed to have found a "one pass" solution and I've included a Java example below.
Please could someone explain why "while(n-->0) h2=h2.next;" doesn't count as an extra pass of the linked list and, therefore, make this a "two pass" solution?
public ListNode RemoveNthFromEnd(ListNode head, int n) {
ListNode h1=head, h2=head;
while(n-->0) h2=h2.next;
if(h2==null)return head.next; // The head need to be removed, do it.
h2=h2.next;
while(h2!=null){
h1=h1.next;
h2=h2.next;
}
h1.next=h1.next.next; // the one after the h1 need to be removed
return head;
}
I've looked in the comments to this and other solutions and couldn't find an answer. Equally, a general Google search didn't yield an explanation.
Thanks in advance.
No, it's not one-pass. One-pass is defined with respect to a sequential I/O mechanism (canonically a tape) and means that each piece of data is read at most once, in order. Analogizing the linked list to the tape here, this algorithm is not one-pass because in general, some node will have its next field read once by h2=h2.next (in either loop) and again by h1=h1.next in the second loop.
The algorithm is not single pass, but not because of the first loop.
The first loop performs a partial pass on n elements.
The second loop performs two simultaneous partial passes on l-n elements (that on h2 being complementary to that in the first loop). In total, 2l-n lookups of next fields.
A single-pass solution can be implemented with the help of a FIFO queue of length n, but this is "hiding" a partial pass.

Why do I get StackOverFlowError when trying to DFS this graph for finding strongly connected component?

I am trying to write an algorithm that determines whether a graph is strongly connected or not. I think my code is almost correct, although I keep getting StackOverFlowError. I personally think because there's a cycle in the graph I'm testing my algorithm with, my code doesn't understand that and comes in a loop. But I'm using an array to see if a node was already visited! So that should not happen! Please help me understand what's wrong with my code. Anyways this is my code:
static void dfs(int src,boolean[] visited,Stack<Integer> stack){
visited[src]=true;
for(Integer i:adj[src]){
if(!visited[i]){
dfs(i,visited,stack);
}
}
stack.push(src);
}
This is how I called my DFS function from main:
Stack<Integer> stack=new Stack<Integer>();
boolean[] visited=new boolean[n+1];
for(int i=1;i<=n;i++){
if(!visited[i]){
g.dfs(i,visited,stack);
}
}
There are two possible explanations:
There is a loop and your loop detection code isn't working.
The graph is too deep; i.e. your code would work if the stack was larger.
Looking at your code, I think that the second explanation is the correct one.
Example: suppose that your graph is actually a chain of N nodes in a line. To reach the last node in the list you need to make recursive calls N deep. For large enough N, that will cause a stack overflow.

Branch And Bound not working in OptaPlanner

I have a Directed Acyclic Graph, arcs are Entities and Weights associated do each Arc are the PlanningVariables. I use:
#ValueRangeProvider(id = "bufferRange")
public CountableValueRange<Integer> getDelayRange() {
return ValueRangeFactory.createIntValueRange(1, 1000);
}
to assign values to my variables. Also, i've come across this issue:
Exhaustive Search in OptaPlanner does not work on very simple example, which is now solved by setting variables from int to Integer and checking null values in the score calculation.
Now the problem is that the solver seems not to be backtraking when assigning values. I've used a print to check values being attributed to each arc. In the beginning of the solving process i can see values being set to different arcs. But after some time attributions the solver stucks in assigning values to the same arc. Checking the prints I see the attributions going from 1 to 1000 and then starting again. Since all values from the domain are tested one time, why the solver does not backtrack instead of assigning the same values again?
I tested with all the <nodeExplorationType> options and created a class to use the <entitySorterManner> with the same results.
Thanks in advance.
I supose you are right Geoffrey, deactivated the log and let the program run for almost 48h and it came up with an answer. The way logs are printed mislead the analysis. Just for remark, if logger is deactivated the performance is considerably superior.

Stack Overflow Error java

I'm trying to solve a problem that calls for recursive backtracking and my solution produces a stackoverflow error. I understand that this error often indicates a bad termination condition, but my ternimation condition appears correct. Is there anything other than a bad termination condition that would be likely to cause a stackoverflow error? How can I figure out what the problem is?
EDIT: sorry tried to post the code but its too ugly..
As #irreputable says, even if your code has a correct termination condition, it could be that the problem is simply too big for the stack (so that the stack is exhausted before the condition is reached). There is also a third possibility: that your recursion has entered into a loop. For example, in a depth-first search through a graph, if you forget to mark nodes as visited, you'll end up going in circles, revisiting nodes that you have already seen.
How can you determine which of these three situations you are in? Try to make a way to describe the "location" of each recursive call (this will typically involve the function parameters). For instance, if you are writing a graph algorithm where a function calls itself on neighbouring nodes, then the node name or node index is a good description of where the recursive function is. In the top of the recursive function, you can print the description, and then you'll see what the function does, and perhaps you can tell whether it does the right thing or not, or whether it goes in circles. You can also store the descriptions in a HashMap in order to detect whether you have entered a circle.
Instead of using recursion, you could always have a loop which uses a stack. E.g. instead of (pseudo-code):
function sum(n){
if n == 0, return 0
return n + sum(n-1)
}
Use:
function sum(n){
Stack stack
while(n > 0){
stack.push(n)
n--
}
localSum = 0
while(stack not empty){
localSum += stack.pop()
}
return localSum
}
In a nutshell, simulate recursion by saving the state in a local stack.
You can use the -Xss option to give your stack more memory if your problem is too large to fix in the default stack limit size.
As the other fellas already mentioned, there might be few reasons for that:
Your code has problem by nature or in the logic of the recursion. It has to be a stoping condition, base case or termination point for any recursive function.
Your memory is too small to keep the number of recursive calls into the stack. Big Fibonacci numbers might be good example here. Just FYI Fibonacci is as follows (sometimes starts at zero):
1,1,2,3,5,8,13,...
Fn = Fn-1 + Fn-2
F0 = 1, F1 = 1, n>=2
If your code is correct, then the stack is simply too small for your problem. We don't have real Turing machines.
There are two common coding errors that could cause your program to get into an infinite loop (and therefore cause a stack overflow):
Bad termination condition
Bad recursion call
Example:
public static int factorial( int n ){
if( n < n ) // Bad termination condition
return 1;
else
return n*factorial(n+1); // Bad recursion call
}
Otherwise, your program could just be functioning properly and the stack is too small.

Java Algorithm for finding the largest set of independent nodes in a binary tree

By independent nodes, I mean that the returned set can not contain nodes that are in immediate relations, parent and child cannot both be included. I tried to use Google, with no success. I don't think I have the right search words.
A link, any help would be very much appreciated. Just started on this now.
I need to return the actual set of independent nodes, not just the amount.
You can compute this recursive function with dynamic programming (memoization):
MaxSet(node) = 1 if "node" is a leaf
MaxSet(node) = Max(1 + Sum{ i=0..3: MaxSet(node.Grandchildren[i]) },
Sum{ i=0..1: MaxSet(node.Children[i]) })
The idea is, you can pick a node or choose not to pick it. If you pick it, you can't pick its direct children but you can pick the maximum set from its grandchildren. If you don't pick it, you can pick maximum set from the direct children.
If you need the set itself, you just have to store how you selected "Max" for each node. It's similar to the LCS algorithm.
This algorithm is O(n). It works on trees in general, not just binary trees.
I would take-and-remove all leaves first while marking their parents as not-to-take, then remove all leaves that are marked until no such leaves are left, then recurse until the tree is empty. I don't have a proof that this always produces the largest possible set, but I believe it should.
I've provided an answer to a question for the same problem, although the solution is in python, the explanation, algorithm, and test cases could be applicable.

Categories