0

I have different scenarios in my model, and in each scenario some road segments (edges) of the road network (Graph) is degraded (loses capacity) or disrupted (removed because of total damage). For that reason, I am trying to iterate over a set of edges for each scenario, starting with the original network, and update the network by changing capacity of some of the edges and removing some others. In the beginning I did not use an iterator to iterate over the edges which resulted in "ConcurrentModificationException". Then I changed the code so as to use Iterator, but this time it does not allow me to use remove method with my iterator (edgeIt.remove()). How can I solve this issue? Thanks for your help in advance.

.....

ArrayList<FloydWarshallShortestPaths<Integer, DefaultWeightedEdge>> FWS = new ArrayList<FloydWarshallShortestPaths<Integer, DefaultWeightedEdge>>();
        for(int w=0; w<numOfScenarios; w++){
            FWS.add(w, fr.readData(fileName));
        }

....

//Road Network and Shelters after disruption in Scenarios
        for(int i=1; i<6; i++){
            Iterator<FloydWarshallShortestPaths<Integer, DefaultWeightedEdge>> it = FWS.iterator();
            while(it.hasNext()){
                FloydWarshallShortestPaths<Integer, DefaultWeightedEdge> FWIt = it.next();
                Iterator<DefaultWeightedEdge> edgeIt = FWIt.getGraph().edgeSet().iterator();
                while(edgeIt.hasNext()){
                DefaultWeightedEdge e = edgeIt.next();
                    if(arcRiskZoneIndex[FWIt.getGraph().getEdgeSource(e)][FWIt.getGraph().getEdgeTarget(e)][FWS.indexOf(FWIt)]==i){
                        if(rng.nextDouble()<=arcDisruptProb[FWS.indexOf(FWIt)][i-1]){
                            roadCapS[FWS.get(FWS.indexOf(FWIt)).getGraph().getEdgeSource(e)][FWS.get(FWS.indexOf(FWIt)).getGraph().getEdgeTarget(e)][FWS.indexOf(FWIt)]=(roadCap[FWIt.getGraph().getEdgeSource(e)][FWIt.getGraph().getEdgeTarget(e)]*10000-rng.nextInt(((int) (10000*roadCap[FWIt.getGraph().getEdgeSource(e)][FWIt.getGraph().getEdgeTarget(e)]/2000))+1)*2000)/10000;
                            if(roadCapS[FWIt.getGraph().getEdgeSource(e)][FWIt.getGraph().getEdgeTarget(e)][FWS.indexOf(FWIt)]==0.0){
                                **edgeIt.remove()**;
                            }
                        }
                    }
                }
                for(int s:setOfFacilityNodesDummy){
                    if(shelterRiskZoneIndex[s][FWS.indexOf(FWIt)]==i){
                        if(rng.nextDouble()<=shelterDisruptProb[FWS.indexOf(FWIt)][i-1]){
                            setOfFacilityNodesS.get(FWS.indexOf(FWIt)).remove(s);
                        }
                    }
                }
            }
        }
11
  • 2
    What's an edgeSet()? Commented Aug 15, 2014 at 12:18
  • The set of edges in the graph. Commented Aug 15, 2014 at 12:19
  • 1
    possible duplicate of How to avoid "ConcurrentModificationException" while removing elements from `ArrayList` while iterating it? Commented Aug 15, 2014 at 12:20
  • The Iterator does not support removal, hence the UnsupportedOperationException. Can you post the original code as well, so we can debug that? THe issue MIGHT be that you used the List.remove(Object) which runs through the list behind the scenes, thus throwing ConcurrentModificationException. Removing by index would solve that issue. Commented Aug 15, 2014 at 12:21
  • @VedatBAYRAM ... What type is it? Obviously it's a set of edges. That provides no information with which anyone can diagnose the problem. In order to diagnose why the iterator won't let you remove an object from the set we need to know more about the set and its iterator. Commented Aug 15, 2014 at 12:21

2 Answers 2

2

Most likely the Collection returned by edgeSet() simply doesn't support the remove() operation, or it does support remove(), yet its Iterator does not.

To get around this (and the ConcurrentModificationException), you'll have to collect the edges you want removed in a seperate Set, and after you're done iterating, remove them through the proper API of the graph.

Sign up to request clarification or add additional context in comments.

Comments

1

Okay, I did some googling and apparently you're using the JGraphT library. (Protip: it helps to specify this in your question!) The JavaDoc for Graph.edgeSet() says:

Returns a set of the edges contained in this graph. The set is backed by the graph, so changes to the graph are reflected in the set. If the graph is modified while an iteration over the set is in progress, the results of the iteration are undefined.

Now, this just means that if the edges of the Graph change, then those changes can be seen in the returned Set. Unfortunately, it doesn't say anything about changes in the returned Set causing changes to the edges of the Graph. Seeing that you're getting an UnsupportedOperationException, I would assume Graph does not allow you change the returned Set. The source code of AbstractBaseGraph confirms this assumption:

/**
 * @see Graph#edgeSet()
 */
public Set<E> edgeSet()
{
    if (unmodifiableEdgeSet == null) {
        unmodifiableEdgeSet = Collections.unmodifiableSet(edgeMap.keySet());
    }

    return unmodifiableEdgeSet;
}

edgeSet() returns an unmodifiable view of a Graph's edges. You cannot change the edgeSet directly, you have to use the Graph interface to add/change/remove edges. Additionally, if you are iterating over the edgeSet while you're making these changes, you may run into undefined behavior.

To solve this, I recommend first collecting the edges to be removed while iterating, and then removing them afterwards:

// Collection holding the 'marked' edges
Set<DefaultWeightedEdge> toRemove = new HashSet<>();
Iterator<DefaultWeightedEdge> edgeIt = FWIt.getGraph().edgeSet().iterator();
while (edgeIt.hasNext()){
    DefaultWeightedEdge e = edgeIt.next();
    /* ... */
    if (/* something */) {
         // Mark the edge to be removed
         toRemove.add(e);
    }
}
// Remove the marked edges using the Graph's interface
FWIt.getGraph().removeAllEdges(toRemove);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.