The SelfLoopsParallelEdges object is an object used to keep track of the self-loops and parallel edges found in a graph.

public SelfLoopsParallelEdges(boolean directed){
		selfLoops = new HashSet();
		parallelEdges = new HashSet();
		edges = new HashMap();
		this.directed = directed;

	}

	/***
	 * 
	 * @param e
	 * Here we take an Edge e, create a SimpleEdge object, which only stores
	 * the source and target ids. We create a HashSet to hold edges.
	 * We then link the SimpleEdge to the HashSet of real edges.
	 */
	
	
	public void addEdge(Edge e){
		SimpleEdge se = new SimpleEdge(e);

		if(directed){

			if(edges.get(se) == null){ //We haven't seen this source and target
				HashSet temp = new HashSet(); //create the HashSet to hold real edges.
				temp.add(e);
				edges.put(se, temp); //link real edges to source and target.
			}
			else{ //we've seen this source and target so we have a parallel edge.
				if(((HashSet)edges.get(se)).add(e)){ //add the real edge to the mapping, 
													//only if it is unique.

					parallelEdges.add(se); 
				}

			}	
		}
		else{
			//create a simple edge with the source and target swapped to handle undirected.
			SimpleEdge se2 = new SimpleEdge(e.getTargetNode().getRow(), e.getSourceNode().getRow());

			if((edges.get(se) == null) && (edges.get(se2) == null)){
				HashSet temp = new HashSet();
				temp.add(e);
				edges.put(se, temp);
			}
			else if((edges.get(se) != null)){
				if(((HashSet)edges.get(se)).add(e)){

					parallelEdges.add(se);
				}
			}
			else{
				if(((HashSet)edges.get(se2)).add(e)){

					parallelEdges.add(se2);
				}
			}

		}
		//if the source and target are the same, add a selfLoop.
		if(e.getSourceNode().getRow() == e.getTargetNode().getRow()){
			selfLoops.add(e);
		}
	}