/**
   * Compute the unique decomposition of the input graph G (atoms of G). Implementation of algorithm
   * Atoms as described in Berry et al. (2010), DOI:10.3390/a3020197, <a
   * href="http://www.mdpi.com/1999-4893/3/2/197">http://www.mdpi.com/1999-4893/3/2/197</a>
   */
  private void computeAtoms() {
    if (chordalGraph == null) {
      computeMinimalTriangulation();
    }

    separators = new HashSet<>();

    // initialize g' as subgraph of graph (same vertices and edges)
    UndirectedGraph<V, E> gprime = copyAsSimpleGraph(graph);

    // initialize h' as subgraph of chordalGraph (same vertices and edges)
    UndirectedGraph<V, E> hprime = copyAsSimpleGraph(chordalGraph);

    atoms = new HashSet<>();

    Iterator<V> iterator = meo.descendingIterator();
    while (iterator.hasNext()) {
      V v = iterator.next();
      if (generators.contains(v)) {
        Set<V> separator = new HashSet<>(Graphs.neighborListOf(hprime, v));

        if (isClique(graph, separator)) {
          if (separator.size() > 0) {
            if (separators.contains(separator)) {
              fullComponentCount.put(separator, fullComponentCount.get(separator) + 1);
            } else {
              fullComponentCount.put(separator, 2);
              separators.add(separator);
            }
          }
          UndirectedGraph<V, E> tmpGraph = copyAsSimpleGraph(gprime);

          tmpGraph.removeAllVertices(separator);
          ConnectivityInspector<V, E> con = new ConnectivityInspector<>(tmpGraph);
          if (con.isGraphConnected()) {
            throw new RuntimeException("separator did not separate the graph");
          }
          for (Set<V> component : con.connectedSets()) {
            if (component.contains(v)) {
              gprime.removeAllVertices(component);
              component.addAll(separator);
              atoms.add(new HashSet<>(component));
              assert (component.size() > 0);
              break;
            }
          }
        }
      }

      hprime.removeVertex(v);
    }

    if (gprime.vertexSet().size() > 0) {
      atoms.add(new HashSet<>(gprime.vertexSet()));
    }
  }
  /** . */
  public void testDirectedGraph() {
    ListenableDirectedGraph<String, DefaultEdge> g =
        new ListenableDirectedGraph<String, DefaultEdge>(DefaultEdge.class);
    g.addVertex(V1);
    g.addVertex(V2);
    g.addVertex(V3);

    g.addEdge(V1, V2);

    ConnectivityInspector<String, DefaultEdge> inspector =
        new ConnectivityInspector<String, DefaultEdge>(g);
    g.addGraphListener(inspector);

    assertEquals(false, inspector.isGraphConnected());

    g.addEdge(V1, V3);

    assertEquals(true, inspector.isGraphConnected());
  }
  /** . */
  public void testIsGraphConnected() {
    Pseudograph<String, DefaultEdge> g = create();
    ConnectivityInspector<String, DefaultEdge> inspector =
        new ConnectivityInspector<String, DefaultEdge>(g);

    assertEquals(false, inspector.isGraphConnected());

    g.removeVertex(V4);
    inspector = new ConnectivityInspector<String, DefaultEdge>(g);
    assertEquals(true, inspector.isGraphConnected());

    g.removeVertex(V1);
    assertEquals(1, g.edgeSet().size());

    g.removeEdge(e2);
    g.addEdge(V2, V2);
    assertEquals(1, g.edgeSet().size());

    inspector = new ConnectivityInspector<String, DefaultEdge>(g);
    assertEquals(false, inspector.isGraphConnected());
  }