Search code examples
javagraphjgrapht

Simple weighted Graph: Loops not allowed exception


I'm attempting to create a programme which tracks the emails of people. I am using a string for the vertex in my graph (The string is their email) and a DefaultWeightedEdge from Jgrapht. If these people send one email between each other then the weight of the edge connecting that node is set to 1. If they send another email after already having sent one I increment the edge weight by 1.

I think I have the main bulk of the code correct, however I am getting this exception.

Exception in thread "main" java.lang.IllegalArgumentException: loops not allowed at org.jgrapht.graph.AbstractBaseGraph.addEdge(AbstractBaseGraph.java:203) at groupProject.Analysis.StoreEmails(Analysis.java:58) at groupProject.AnalyserRun.main(AnalyserRun.java:7)

Here is my code:

public class Analysis {
    SimpleWeightedGraph<String, DefaultWeightedEdge>  graph = new SimpleWeightedGraph<String, DefaultWeightedEdge>(DefaultWeightedEdge.class);
    jsonParser jP = new jsonParser("/Users/Kieran/test/test2.json");
    int numEmails = jP.getNumEmails();
    ArrayList<String> senders = new ArrayList<String>();
    ArrayList<String> recipients = new ArrayList<String>();
    ArrayList<String> all = senders;
    ArrayList<DefaultWeightedEdge> edges = new ArrayList<DefaultWeightedEdge>();

    public void StoreEmails(){
        //Creates vertex's for every sender
        for(int i = 0; i < numEmails; i++){
            Email email = jP.parseJSON(i);
            if(!senders.contains(email.getSender())){
                graph.addVertex(email.getSender());
                senders.add(email.getSender());
            }
        }

        //creates vertex's for every recipient
        for(int i = 0; i < numEmails; i++){
            Email email = jP.parseJSON(i);
            if(email.getRecipients().length != 0){
                    for(int j = 0; j < email.getRecipients().length; j++){
                        if(!recipients.contains(email.getRecipients()[j])){
                            graph.addVertex(email.getRecipients()[j]);
                            recipients.add(email.getRecipients()[j]);
                        }
                    }
            }
        }

        all.removeAll(recipients);
        all.addAll(recipients);
        /*
         * Adds all of the edges from senders to recipients and if the edge already exists then it will increase the weight by one
         * however is is a directed graph so you need to check both pairs.
         */
        for(int j = 0; j < numEmails; j++){
            Email email = jP.parseJSON(j);
            for(int k = 0; k < email.getRecipients().length; k++){
                if(graph.containsEdge(email.getSender(), email.getRecipients()[k])){
                    int current_weight = (int) graph.getEdgeWeight(graph.getEdge(email.getSender(), email.getRecipients()[k]));
                    graph.setEdgeWeight(graph.getEdge(email.getSender(), email.getRecipients()[k]), current_weight+1);
                }else{
                    DefaultWeightedEdge e = graph.addEdge(email.getSender(), email.getRecipients()[k]);
                    graph.setEdgeWeight(e, 1);
                }
            }
        }
        builder();
    }

    public int calcConnectedness(String s1,String s2){
        int connectedness = 0;
        int weightS1S2 = 0;
        int weightS2S1 = 0;
        if(graph.containsEdge(s1, s2)){
            weightS1S2 = (int) graph.getEdgeWeight(graph.getEdge(s1, s2));
            connectedness += weightS1S2;
        }
        /*if(graph.containsEdge(s2, s1)){
            weightS2S1 = (int) graph.getEdgeWeight(graph.getEdge(s2, s1));
            connectedness += weightS2S1;
        }*/
        return connectedness;
    }

    public void builder(){
        for(int i = 0; i < all.size(); i++){
            for(int j = i+1; j < all.size(); j++){
                    if(graph.containsEdge(all.get(i), all.get(j)))
                        make(all.get(i), all.get(j), calcConnectedness(all.get(i), all.get(j)));
            }
        }
    }

    public void make(String user1, String user2, int connectedness){
        System.out.println(user1 + " " + user2 + " Are connected by a factor of: "+connectedness);
    }
}

After some research the only information I was able to find which may be causing the problem is the fact that in Java, strings are immutable. However, I was still not able to resolve my issues.


Solution

  • The answer was in this section of code:

    }else{
                        DefaultWeightedEdge e = graph.addEdge(email.getSender(), email.getRecipients()[k]);
                        graph.setEdgeWeight(e, 1);
                    }
    

    It turns out that email.getSender() was in email.getRecipients() so the source and destination of the edge was the same i.e a loop. I solved the issue by doing a simple check beforehand with an if statement to only add an edge if it was not the same as the source.