@Override
  public TraversalGraph<V, E> reconstructTraversalGraph() {

    if (currentStartNode == null) {
      throw new IllegalStateException(
          "You must call #calculate before " + "reconstructing the traversal graph.");
    }

    TraversalGraph<V, E> traversalGraph =
        new TraversalGraph<V, E>(graph.getEdgeFactory(), currentStartNode);
    for (V v : graph.vertexSet()) {
      Set<E> predEdges = (Set<E>) v.getPredecessorEdges();
      for (E e : predEdges) {
        V source = graph.getEdgeSource(e);
        V target = graph.getEdgeTarget(e);
        traversalGraph.addVertex(source);
        traversalGraph.addVertex(target);
        if (v.equals(source)) {
          traversalGraph.addEdge(target, source).setBaseGraphEdge(e);
        } else if (v.equals(target)) {
          traversalGraph.addEdge(source, target).setBaseGraphEdge(e);
        } else {
          throw new IllegalStateException(
              "A vertex has a predecessor " + "edge not ending on itself.");
        }
      }
    }

    return traversalGraph;
  }
    E addEdge(V jtSource, V jtTarget) {
      E jtEdge = graph.getEdgeFactory().createEdge(jtSource, jtTarget);
      jtElementsBeingAdded.add(jtEdge);

      boolean added = graph.addEdge(jtSource, jtTarget, jtEdge);
      jtElementsBeingAdded.remove(jtEdge);

      return added ? jtEdge : null;
    }
  /**
   * @param connectedOnly if true, the result will be a connected graph
   * @return
   */
  public Graph<V, E> toGraph() {
    if (subgraph != null) return subgraph;
    if (directed) {
      subgraph = new DirectedMultigraph<V, E>(g2.getEdgeFactory());
    } else {
      subgraph = new Multigraph<V, E>(g2.getEdgeFactory());
    }

    E edge;
    V source;
    V target;
    for (int x = 0; x < dimx; x++) {
      for (int y = 0; y < dimy; y++) {
        if (matrix[x][y]) {
          edge = edgeList2.get(y);
          source = g2.getEdgeSource(edge);
          target = g2.getEdgeTarget(edge);
          if (mappedVerticesFromG2.contains(source) && mappedVerticesFromG2.contains(target)) {
            // make sure the source and target vertices have been added, then add the edge
            subgraph.addVertex(source);
            subgraph.addVertex(target);
            subgraph.addEdge(source, target, edge);
          }
        }
      }
    }

    if (connectedOnly) {
      // make sure this subgraph is connected, if it is not return the largest connected part
      List<Set<V>> connectedVertices = new ArrayList<Set<V>>();
      for (V v : subgraph.vertexSet()) {
        if (!SharedStaticMethods.containsV(connectedVertices, v)) {
          connectedVertices.add(SharedStaticMethods.getConnectedVertices(subgraph, v));
        }
      }
      // ConnectedVertices now contains Sets of connected vertices every vertex of the subgraph is
      // contained exactly once in the list
      // if there is more then 1 set, then this method should return the largest connected part of
      // the graph
      if (connectedVertices.size() > 1) {
        Graph<V, E> largestResult = null;
        Graph<V, E> currentGraph;
        int largestSize = -1;
        Set<V> currentSet;
        for (int i = 0; i < connectedVertices.size(); i++) {
          currentSet = connectedVertices.get(i);
          /*note that 'subgraph' is the result from the Mcgregor algorithm, 'currentGraph' is an
           * induced subgraph of 'subgraph'. 'currentGraph' is connected, because the vertices in
           * 'currentSet' are connected with edges in 'subgraph'
           */
          currentGraph = new Subgraph<V, E, Graph<V, E>>(subgraph, currentSet);
          if (currentGraph.edgeSet().size() > largestSize) {
            largestResult = currentGraph;
          }
        }

        return largestResult;
      }
    }

    return subgraph;
  }