Avoiding ConcurrentModificationException in dijkstra's algorithm - java

For this program, I read in a excel file that lays out a map of towns, towns adjacent to them, and the distance between them, which looks like:
Bourke Nyngan 200
Brewarrina Walgett 134
Broken Hill Mildura 266
Broken Hill Wilcannia 195
Bungendore Queanbeyan 54
etc.
And that's working great. Everything seems perfect. I'm trying to make a program that if I give it two towns, it returns the shortest possible path between the two.
I can get my program to correctly read in the file, and set up everything, so I know that this issue isn't anything to do with the setup. To the best of my knowledge this part of my program works, as my program can get through it without throwing errors:
//returns the Vertex with the smallest distance from a list of Vertices
public static Vertex minDist(List<Vertex> Q){
int min = 2147483647;
Vertex closest = new Vertex("Closest");
for(Vertex v : Q){
if(v.distance < min){
closest = v;
}
}
return closest;
}
//used to relax (change the distance of a town)
public static void relax(Vertex u, Vertex v, int w){
if(v.distance > u.distance + w){
v.distance = u.distance + w;
v.predecessor = u;
}
}
public static void Dijkstra(Graph G, Vertex s){
Vertex u = new Vertex("not good");
List<Vertex> Q = V;
Vertex v = new Vertex("oh no");
//while Q is not empty:
while(!Q.isEmpty()){
//the vertex in Q that has the smallest distance (at first s with 0, then we relax and that changes things)
u = minDist(Q);
if(u.name.equals("Closest")){
//Q.remove(u);
return;
}
Q.remove(u);
S.add(u);
//for each edge e in u's adjacencyList:
for(Edge e : u.roadList){
if(e != null && !e.finish.name.equals(u.name) ){
v = e.finish;
relax(u,v,w(u,v)); //w(u,v) returns the distance between u and v
}
}
}
System.out.println("Q is null");
}
So I have that, and things look okay to me. I know it's a bit Frankenstein'ed together, but I got it to at least run without errors, because the ConcurrentModificationException gets thrown AFTER this method returns in my main method.
This is where my Dijkstra method gets called in my main method. I never reach the line in my code that prints "SHOULD REACH HERE" because the program throws the ConcurrentModificationException.
//if both towns exist and are unique, find the shortest route between them.
if(isTown(town1,V) && isTown(town2,V) && !town1.equals(town2)){
for(Vertex f : V){
if(f.name.equals(town2)){
destination = f;
}
}
System.out.println("Traveling...");
Graph G = new Graph(V,E);
for(Vertex s : V){
if(s.name.equals(town1)){
//////////////////DIJKSTRA STUFF GOES HERE///////////////////
initialize(G,s);
Dijkstra(G, s);
System.out.println("FINISHED DIJKSTRA");
//Print out the things in the vertex array S with their distances.
for(Vertex b : S){
System.out.println(b.name + " (" + b.distance + ")");
}
///////////////////////////////////////////////
}
}
System.out.println("SHOULD REACH HERE");
}
I have never seen a ConcurrentModificationException, my lab TA has never seen a ConcurrentModificationException, and even my professor has never seen a ConcurrentModificationException. Can I get some help with avoiding this? A person in a higher class said that he has only seen this happening when working with multiple threads, and I don't even know what that really means so I assume my program doesn't do that.
If I run the program with with town1 = Grafton and town2 = Bathurst, then the output should be:
First town: Grafton
Second town: Bathurst
Bathurst (820)
Lithgow (763)
Windsor (672)
Singleton (511)
Muswellbrook (463)
Tamworth (306)
Bendemeer (264)
Uralla (218)
Armidale (195)
Ebor (106)
Grafton
But is instead
First town: Grafton
Second town: Bathurst
Grafton (0)
Glen Innes (158)
Inverell (225)
Warialda (286)
Coffs Harbour (86)
I/O error: java.util.ConcurrentModificationException

You're getting this because you're removing from Q while iterating over it it. See Iterating through a Collection, avoiding ConcurrentModificationException when removing in loop

Related

Prevent Depth First Search Algorithm from getting stuck in an infinite loop ,8 Puzzle

So my code works for basic 8 Puzzle problems, but when I test it with harder puzzle configurations it runs into an infinite loop. Can someone please edit my code to prevent this from happening. Note that I have included code that prevents the loops or cycles. I tried including the the iterative depth first search technique, but that too did not work. Can someone please review my code.
/** Implementation for the Depth first search algorithm */
static boolean depthFirstSearch(String start, String out ){
LinkedList<String> open = new LinkedList<String>();
open.add(start);
Set<String> visitedStates = new HashSet<String>(); // to prevent the cyle or loop
LinkedList<String> closed = new LinkedList<String>();
boolean isGoalState= false;
while((!open.isEmpty()) && (isGoalState != true) ){
String x = open.removeFirst();
System.out.println(printPuzzle(x)+"\n\n");
jtr.append(printPuzzle(x) +"\n\n");
if(x.equals(out)){ // if x is the goal
isGoalState = true;
break;
}
else{
// generate children of x
LinkedList<String> children = getChildren(x);
closed.add(x); // put x on closed
open.remove(x); // since x is now in closed, take it out from open
//eliminate the children of X if its on open or closed ?
for(int i=0; i< children.size(); i++){
if(open.contains(children.get(i))){
children.remove(children.get(i));
}
else if(closed.contains(children.get(i))){
children.remove(children.get(i));
}
}
// put remaining children on left end of open
for(int i= children.size()-1 ; i>=0 ; i--){
if ( !visitedStates.contains(children.get(i))) { // check if state already visited
open.addFirst(children.get(i)); // add last child first, and so on
visitedStates.add(children.get(i));
}
}
}
}
return true;
}
I would suggest putting the positions that you are considering into a https://docs.oracle.com/javase/7/docs/api/java/util/PriorityQueue.html with a priority based on how close they are to being solved.
So what you do is take the closest position off of the queue, and add in all of the one move options from there that haven't yet been processed. Then repeat. You'll spent most of your time exploring possibilities that are close to solved instead of just moving randomly forever.
Now your question is "how close are we to solving it". One approach is to take the sum of all of the taxicab distances between where squares are and where they need to be. A better heuristic may be to give more weight to getting squares away from the corner in place first. If you get it right, changing your heuristic should be easy.

I can't find the cause of my java.util.ConcurrentModificationException

I have code that enters the for loop within my Main method.
for (List<Point2D> points : output) {
currentPath = pathDistance(points);
if (shortest == 0){
shortest = currentPath;
} else if (currentPath < shortest) {
best = points;
shortest = currentPath;
}
}
where pathDistance is defined as
public static Double pathDistance(List<Point2D> path){
double distance = 0;
int count = path.size()-1;
for (int i = 0; i < count; i++) {
distance = distance + path.get(i).distance(path.get(i+1));
}
distance = distance + path.get(0).distance(path.get(count));
return distance;
}
But I keep getting the error
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.SubList.checkForComodification(Unknown Source)
at java.util.SubList.size(Unknown Source)
at java.util.Collections$SynchronizedCollection.size(Unknown Source)
at TSMain.pathDistance(TSMain.java:76)
at TSMain.main(TSMain.java:203)
I know this is supposed to mean that I am altering an object while an iteration depends on it, but I can't for the life of me figure out where that might be happening. Any help would be appreciated.
Your stacktrace shows that somewhere in your code subList is passed to Collections.synchronizedCollection (directly or indirectly). Like this
Set<List<Point2D>> output = Collections.singleton(
Collections.synchronizedCollection(data.subList(start, end)));
However it does not copy data list. And points subList is still pointing to a range in data list. And original list is modified at the momet path.size() call occurs.
You can easily fix your problem by doing explicit list copy before passing it to pathDistance
for(List<Point2D> points : output){
List<Point2D> pointsCopy = new ArrayList<>(points)
currentPath = pathDistance(pointsCopy);
// rest of code using pointsCopy
}
I also should notice that it looks like there is a problem with synchronization in your code. Wrapping sublists in synchronized collection is a bad idea because original list could be modified in unsafe manner w/o proper synchronization.
You can learn more about list modification checking by looking into AbstractList#modCount sources.

Modification to Dijkstra, verification needed

Dijkstra algorithm has a step which mentions "chose the node with shortest path". I realize that this step is unnecessary if we dont throw a node out of the graph/queue. This works great in my knowledge with no known disadvantage. Here is the code. Please instruct me if it fails ? if it does then how ? [EDIT => THIS CODE IS TESTED AND WORKS WELL, BUT THERE IS A CHANCE MY TEST CASES WERE NOT EXHAUSTIVE, THUS POSTING IT ON STACKOVERFLOW]
public Map<Integer, Integer> findShortest(int source) {
final Map<Integer, Integer> vertexMinDistance = new HashMap<Integer, Integer>();
final Queue<Integer> queue = new LinkedList<Integer>();
queue.add(source);
vertexMinDistance.put(source, 0);
while (!queue.isEmpty()) {
source = queue.poll();
List<Edge> adjlist = graph.getAdj(source);
int sourceDistance = vertexMinDistance.get(source);
for (Edge edge : adjlist) {
int adjVertex = edge.getVertex();
if (vertexMinDistance.containsKey(adjVertex)) {
int vertexDistance = vertexMinDistance.get(adjVertex);
if (vertexDistance > (sourceDistance + edge.getDistance())) {
//previous bug
//vertexMinDistance.put(adjVertex, vertexDistance);
vertexMinDistance.put(adjVertex, sourceDistance + edge.getDistance())
}
} else {
queue.add(adjVertex);
vertexMinDistance.put(adjVertex, edge.getDistance());
}
}
}
return vertexMinDistance;
}
Problem 1
I think there is a bug in the code where it says:
int vertexDistance = vertexMinDistance.get(adjVertex);
if (vertexDistance > (sourceDistance + edge.getDistance())) {
vertexMinDistance.put(adjVertex, vertexDistance);
}
because this has no effect (vertexMinDistance for adjVertex is set back to its original value).
Better would be something like:
int vertexDistance = vertexMinDistance.get(adjVertex);
int newDistance = sourceDistance + edge.getDistance();
if (vertexDistance > newDistance ) {
vertexMinDistance.put(adjVertex, newDistance );
}
Problem 2
You also need to add the adjVertex into the queue using something like:
int vertexDistance = vertexMinDistance.get(adjVertex);
int newDistance = sourceDistance + edge.getDistance();
if (vertexDistance > newDistance ) {
vertexMinDistance.put(adjVertex, newDistance );
queue.add(adjVertex);
}
If you don't do this then you will get an incorrect answer for graphs such as:
A->B (1)
A->C (10)
B->C (1)
B->D (10)
C->D (1)
The correct path is A->B->C->D of weight 3, but without the modification then I believe your algorithm will choose a longer path (as it doesn't reexamine C once it has found a shorter path to it).
High level response
With these modifications I think this approach is basically sound, but you should be careful about the computational complexity.
Dijkstra will only need to go round the main loop V times (where V is the number of vertices in the graph), while your algorithm may need many more loops for certain graphs.
You will still get the correct answer, but it may take longer.
Although the worst-case complexity will be much worse than Dijkstra, I would be interested in how well it performs in practice. My guess is that it will work well for sparse almost tree-like graphs, but less well for dense graphs.

Level Order tree Traversal for a generic tree, displaying the tree level by level

I would like to display the tree structure level by level. My current code does a BFS or Level Order Traversal but I cannot get the output to display the tree structure like a tree
See current output and Expected output.
My idea was to use some kind of count to iterate over elements from the same level in the queue.
How can I do so.
Original Code without this function can be found in the link below in case someone needs the entire implementation else just look at the displayBFS function below.
Level Order traversal of a generic tree(n-ary tree) in java
Thanks!
void displayBFS(NaryTreeNode n)
{
Queue<NaryTreeNode> q = new LinkedList<NaryTreeNode>();
System.out.println(n.data);
while(n!=null)
{
for(NaryTreeNode x:n.nary_list)
{
q.add(x);
System.out.print(x.data + " ");
}
n=q.poll();
System.out.println();
}
}
Current Tree Structure for reference:
root(100)
/ | \
90 50 70
/ \
20 30 200 300
Current Output:
100
90 50 70
20 30
200 300
Expected Output
100
90 50 70
20 30 200 300
Also, I had posted a logic issue with the same function earlier, as that was answered and the current question realtes to a different problem, I posted a new question, is this approach okay or should I make edits to the earlier question and not open a new one?
only need to keep track of current level and next level.
static void displayBFS(NaryTreeNode root) {
int curlevel = 1;
int nextlevel = 0;
LinkedList<NaryTreeNode> queue = new LinkedList<NaryTreeNode>();
queue.add(root);
while(!queue.isEmpty()) {
NaryTreeNode node = queue.remove(0);
if (curlevel == 0) {
System.out.println();
curlevel = nextlevel;
nextlevel = 0;
}
for(NaryTreeNode n : node.nary_list) {
queue.addLast(n);
nextlevel++;
}
curlevel--;
System.out.print(node.data + " ");
}
}
when you switch levels, swap nextlevel for currentlevel and reset nextlevel. i prefer the simplicity of this over keeping a whole separate queue.
i had this question for a microsoft interview last week... it didn't go so well for me over the phone. good on you for studying it.
The simplest solution I know of to this problem is to use a sentinel. The queue is initialized with the root node followed by the sentinel, and then you loop through the queue:
remove the front element
if it is the sentinel:
we're at the end of a level, so we can end the output line
if the queue is not empty, push the sentinel back onto the queue at the end.
if it is not the sentinel:
print it out
push all its children onto the queue.
I don't do Java, but I have some C++ code for depth-aware BFS, which I stripped down to do this printing task:
void show_tree_by_levels(std::ostream& os, Node* tree) {
Node* sentinel = new Node;
std::deque<Node*> queue{tree, sentinel};
while (true) {
Node* here = queue.front();
queue.pop_front();
if (here == sentinel) {
os << std::endl;
if (queue.empty())
break;
else
queue.push_back(sentinel);
} else {
for (Node* child = here->child; child; child = child->sibling)
queue.push_back(child);
os << here->value << ' ';
}
}
}
Note that I prefer to use a two-pointer solution (first_child/next_sibling), because it usually works out to be simpler than embedded lists. YMMV.
Use another queue to indicate depth.
The below code is not tested, but it should give you the idea (the sep variable is introduced to avoid trailing white-spaces):
void displayBFS(NaryTreeNode n) {
Queue<NaryTreeNode> q = new LinkedList<NaryTreeNode>();
Queue<Integer> depth = new LinkedList<Integer>();
q.add(n);
depth.add(0);
String sep = "";
int oldDepth = 0
while(!q.isEmpty()) {
NaryTreeNode currN = q.poll();
int currDepth = depth.poll();
if (currDepth > oldDepth) {
System.out.println();
oldDepth = currDepth;
sep = "";
}
System.out.print(sep + currN.data);
sep = " ";
for(NaryTreeNode x : currN.nary_list) {
q.add(x);
depth.add(currDepth + 1);
}
}
}
For my taste this approach is more self-explanatory compared to other ways one could do it.
I think we need three more variables. numInCurrentLevel for keeping track of the number of elements in current level, indexInCurrentLevel for doing the count when traversal in current level and numInNextLevel for keeping track of the number of elements in next level. The code is below:
static void displayBFS(NaryTreeNode root) {
Queue<NaryTreeNode> q = new LinkedList<NaryTreeNode>();;
q.add(root);
int numInCurrentLevel = 1;
int numInNextLevel = 0;
int indexInCurrentLevel=0;
while(!q.isEmpty()) {
NaryTreeNode node = q.poll();
System.out.print(node.data + " ");
indexInCurrentLevel++;
for(NaryTreeNode n : node.nary_list) {
q.add(n);
numInNextLevel++;
}
//finish traversal in current level
if(indexInCurrentLevel==numInCurrentLevel) {
System.out.println();
numInCurrentLevel=numInNextLevel;
numInNextLevel=0;
indexInCurrentLevel=0;
}
}
}
Hope it helps, I am not so familiar with java programming.
def printLevelWiseTree(tree):
q= queue.Queue()
if tree == None:
return None
q.put(tree)
while (not(q.empty())):
c = q.get()
print(c.data,end=":")
for i in range(len(c.children)):
if i != len(c.children)-1:
print(c.children[i].data,end=",")
else:
print(c.children[i].data,end="")
q.put(c.children[i])
print()

LinkedList: java.lang.OutOfMemoryError: Java heap space

I'm trying to make a graph implementation for an assignment, which has Graph(GraphImp) objects and Node(NodeImp) objects.
Node objects contain a reference to their Graph, x & y co-ordinates and a name.
The Graph object contains a linked list of its Nodes.
The problem occurs when I try to add a Node into the middle of the List of Nodes (Appending to the end works fine). The program runs out of heap space. I'm not sure why this is occurring though, since the complexity of inserting to a LinkedList should be O(1), and Java (I believe) uses pointers, rather that the objects themselves. I've also tried an arraylist
Making the heap larger is not an option in this instance, and (as far as I understand) should not be the source of the problem.
Thanks in advance.
Here is the error:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.LinkedList.addBefore(LinkedList.java:795)
at java.util.LinkedList.add(LinkedList.java:361)
at pt.graph.GraphImp.addNode(GraphImp.java:79)
at pt.graph.NodeImp.<init>(NodeImp.java:25)
at pt.graph.Graphs.newNode(Solution.java:68)
Here is the Code:
class Graphs
{
static Node newNode(Graph g, double xpos, double ypos, String name) throws InvalidGraphException,InvalidLabelException
{
if(g==null || !(g instanceof GraphImp)){ //Checking validity of inputs
throw new InvalidGraphException();
}
if(name==null){
throw new InvalidLabelException();
}
NodeImp[] existNodes = ((GraphImp)g).getNodes(); //Get all Nodes already present in the Graph
for(int i=0;i<existNodes.length;i++){
if(existNodes[i].getXPos() == xpos && existNodes[i].getYPos() == ypos){ //If node already present at this position, throw InvalidLabelException()
throw new InvalidLabelException();
}
}
Node n = new NodeImp((GraphImp)g, xpos, ypos, name); //If all inputs are valid, create new node
return n;
}
}
class NodeImp extends Node //Node Class
{
private Object flags = null;
private GraphImp g = null;
private double xpos = 0.0;
private double ypos = 0.0;
private String name = "";
NodeImp(GraphImp g, double xpos, double ypos, String name){
this.g = g;
this.xpos = xpos;
this.ypos = ypos;
this.name = name;
g.addNode(this); // Add Node to the Graph
}
}
class GraphImp extends Graph
{
private LinkedList<NodeImp> nodes = new LinkedList<NodeImp>(); //LinkedList of all Nodes in the Graph
GraphImp(){
}
NodeImp[] getNodes(){ //Returns an array of all Nodes
NodeImp[] nArr = new NodeImp[nodes.size()];
return nodes.toArray(nArr);
}
int countNodes(){ //Returns number of Nodes
return nodes.size();
}
void addNode(NodeImp n){ //Add a Node to the LinkedList in order
boolean added = false;
for(int i = 0;i<nodes.size();i++){
if(n.compareTo(nodes.get(i))<=0 ){
nodes.add(i,n); //fails here
}
}
if(!added){
nodes.add(n);
}
return;
}
}
The problem is that you are not exiting your loop after inserting the new node in the middle of the list. Your code will try to insert the same node an infinite number of times, hence the OOM.
Try this:
for(int i = 0;i<nodes.size();i++){
if(n.compareTo(nodes.get(i))<=0 ){
nodes.add(i,n);
added = true;
break;
}
}
As an aside, your insertion is pretty inefficient. Since you know the list is already sorted you could use a binary search to find the insertion point rather than an O(n) scan of the list. Your current implementation is O(n^2) to insert n items, but it could be O(n log n).
It's hard to diagnose the exact cause of your OOM without the whole program, but here's one observation:
getNodes()
is pretty inefficient. You toArray the LinkedList simply to traverse it and look for a particular instance. Why not just use .contains() properly? No need to copy all of the elements then. Or just do what you were doing before but do it on the List instead of an array copy:
for(NodeImp n : existingNodes){
if(n.getXPos() == xpos && n.getYPos() == ypos){
throw new InvalidLabelException();
}
}
My guess is that the 'old' approach of adding to the end was likely to hit an OOM as well but for some heisenbug reason it hasn't manifested itself. Have you run with a profiler?

Categories

Resources