/** @see java.util.Iterator#hasNext() */
  public boolean hasNext() {
    if (startVertex != null) {
      encounterStartVertex();
    }

    if (isConnectedComponentExhausted()) {
      if (state == CCS_WITHIN_COMPONENT) {
        state = CCS_AFTER_COMPONENT;
        if (nListeners != 0) {
          fireConnectedComponentFinished(ccFinishedEvent);
        }
      }

      if (isCrossComponentTraversal()) {
        while (vertexIterator.hasNext()) {
          V v = vertexIterator.next();

          if (!isSeenVertex(v)) {
            encounterVertex(v, null);
            state = CCS_BEFORE_COMPONENT;

            return true;
          }
        }

        return false;
      } else {
        return false;
      }
    } else {
      return true;
    }
  }
    /** @see Graph#getAllEdges(Object, Object) */
    public Set<E> getAllEdges(V sourceVertex, V targetVertex) {
      Set<E> edges = null;

      if (containsVertex(sourceVertex) && containsVertex(targetVertex)) {
        edges = new ArrayUnenforcedSet<E>();

        Iterator<E> iter = getEdgeContainer(sourceVertex).vertexEdges.iterator();

        while (iter.hasNext()) {
          E e = iter.next();

          boolean equalStraight =
              sourceVertex.equals(getEdgeSource(e)) && targetVertex.equals(getEdgeTarget(e));

          boolean equalInverted =
              sourceVertex.equals(getEdgeTarget(e)) && targetVertex.equals(getEdgeSource(e));

          if (equalStraight || equalInverted) {
            edges.add(e);
          }
        }
      }

      return edges;
    }
  /**
   * Creates a new iterator for the specified graph. Iteration will start at the specified start
   * vertex. If the specified start vertex is <code>
   * null</code>, Iteration will start at an arbitrary graph vertex.
   *
   * @param g the graph to be iterated.
   * @param startVertex the vertex iteration to be started.
   * @throws IllegalArgumentException if <code>g==null</code> or does not contain <code>startVertex
   *     </code>
   */
  public CrossComponentIterator(Graph<V, E> g, V startVertex) {
    super();

    if (g == null) {
      throw new IllegalArgumentException("graph must not be null");
    }
    graph = g;

    specifics = createGraphSpecifics(g);
    vertexIterator = g.vertexSet().iterator();
    setCrossComponentTraversal(startVertex == null);

    reusableEdgeEvent = new FlyweightEdgeEvent<V, E>(this, null);
    reusableVertexEvent = new FlyweightVertexEvent<V>(this, null);

    if (startVertex == null) {
      // pick a start vertex if graph not empty
      if (vertexIterator.hasNext()) {
        this.startVertex = vertexIterator.next();
      } else {
        this.startVertex = null;
      }
    } else if (g.containsVertex(startVertex)) {
      this.startVertex = startVertex;
    } else {
      throw new IllegalArgumentException("graph must contain the start vertex");
    }
  }
  /**
   * 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()));
    }
  }
    /** @see Graph#getEdge(Object, Object) */
    public E getEdge(V sourceVertex, V targetVertex) {
      if (containsVertex(sourceVertex) && containsVertex(targetVertex)) {
        DirectedEdgeContainer<V, E> ec = getEdgeContainer(sourceVertex);

        Iterator<E> iter = ec.outgoing.iterator();

        while (iter.hasNext()) {
          E e = iter.next();

          if (getEdgeTarget(e).equals(targetVertex)) {
            return e;
          }
        }
      }

      return null;
    }
Example #6
0
  /**
   * This method will check whether the graph passed in is Eulerian or not.
   *
   * @param g The graph to be checked
   * @return true for Eulerian and false for non-Eulerian
   */
  public static <V, E> boolean isEulerian(UndirectedGraph<V, E> g) {
    // If the graph is not connected, then no Eulerian circuit exists
    if (!(new ConnectivityInspector<V, E>(g)).isGraphConnected()) {
      return false;
    }

    // A graph is Eulerian if and only if all vertices have even degree
    // So, this code will check for that
    Iterator<V> iter = g.vertexSet().iterator();
    while (iter.hasNext()) {
      V v = iter.next();
      if ((g.degreeOf(v) % 2) == 1) {
        return false;
      }
    }
    return true;
  }
    /** @see Graph#getEdge(Object, Object) */
    public E getEdge(V sourceVertex, V targetVertex) {
      if (containsVertex(sourceVertex) && containsVertex(targetVertex)) {
        Iterator<E> iter = getEdgeContainer(sourceVertex).vertexEdges.iterator();

        while (iter.hasNext()) {
          E e = iter.next();

          boolean equalStraight =
              sourceVertex.equals(getEdgeSource(e)) && targetVertex.equals(getEdgeTarget(e));

          boolean equalInverted =
              sourceVertex.equals(getEdgeTarget(e)) && targetVertex.equals(getEdgeSource(e));

          if (equalStraight || equalInverted) {
            return e;
          }
        }
      }

      return null;
    }
    /** @see Graph#getAllEdges(Object, Object) */
    public Set<E> getAllEdges(V sourceVertex, V targetVertex) {
      Set<E> edges = null;

      if (containsVertex(sourceVertex) && containsVertex(targetVertex)) {
        edges = new ArrayUnenforcedSet<E>();

        DirectedEdgeContainer<V, E> ec = getEdgeContainer(sourceVertex);

        Iterator<E> iter = ec.outgoing.iterator();

        while (iter.hasNext()) {
          E e = iter.next();

          if (getEdgeTarget(e).equals(targetVertex)) {
            edges.add(e);
          }
        }
      }

      return edges;
    }
  /**
   * Updates outgoing vertices of the vertex. For each outgoing vertex, the new paths are obtained
   * by concatenating the specified edge to the calculated paths of the specified vertex. If the
   * weight of a new path is greater than the weight of any path stored so far at the outgoing
   * vertex then the path is not added, otherwise it is added to the list of paths in increasing
   * order of weight. Complexity =
   *
   * <ul>
   *   <li>O(<code>d(v)*k*(m+n)</code>) where <code>d(v)</code> is the outgoing degree of the
   *       specified vertex, <code>k</code> is the maximum number of shortest paths to compute,
   *       <code>m</code> is the number of edges of the graph and <code>n</code> is the number of
   *       vertices of the graph
   * </ul>
   *
   * @param vertex
   * @param improvedVertices
   */
  private void updateOutgoingVertices(V vertex, Set<V> improvedVertices) {
    // try to add new paths for the target vertices of the outgoing edges
    // of the vertex in argument.
    for (Iterator<E> iter = edgesOfIterator(vertex); iter.hasNext(); ) {
      E edge = iter.next();
      V vertexReachedByEdge = Graphs.getOppositeVertex(this.graph, edge, vertex);

      // check if the path does not loop over the start vertex.
      if (!vertexReachedByEdge.equals(this.startVertex)) {
        if (this.seenDataContainer.containsKey(vertexReachedByEdge)) {
          boolean relaxed = tryToAddNewPaths(vertexReachedByEdge, edge);
          if (relaxed) {
            improvedVertices.add(vertexReachedByEdge);
          }
        } else {
          boolean relaxed = tryToAddFirstPaths(vertexReachedByEdge, edge);
          if (relaxed) {
            improvedVertices.add(vertexReachedByEdge);
          }
        }
      }
    }
  }
  /** {@inheritDoc} */
  public void generateGraph(
      Graph<V, E> target, VertexFactory<V> vertexFactory, Map<String, V> resultMap) {
    if (size < 1) {
      return;
    }

    // Add all the vertices to the set
    for (int i = 0; i < size; i++) {
      V newVertex = vertexFactory.createVertex();
      target.addVertex(newVertex);
    }

    /*
     * We want two iterators over the vertex set, one fast and one slow.
     * The slow one will move through the set once. For each vertex,
     * the fast iterator moves through the set, adding an edge to all
     * vertices we haven't connected to yet.
     *
     * If we have an undirected graph, the second addEdge call will return
     * nothing; it will not add a second edge.
     */
    Iterator<V> slowI = target.vertexSet().iterator();
    Iterator<V> fastI;

    while (slowI.hasNext()) { // While there are more vertices in the set

      V latestVertex = slowI.next();
      fastI = target.vertexSet().iterator();

      // Jump to the first vertex *past* latestVertex
      while (fastI.next() != latestVertex) {;
      }

      // And, add edges to all remaining vertices
      V temp;
      while (fastI.hasNext()) {
        temp = fastI.next();
        target.addEdge(latestVertex, temp);
        target.addEdge(temp, latestVertex);
      }
    }
  }
Example #11
0
  /**
   * This method will return a list of vertices which represents the Eulerian circuit of the graph.
   *
   * @param g The graph to find an Eulerian circuit
   * @return null if no Eulerian circuit exists, or a list of vertices representing the Eulerian
   *     circuit if one does exist
   */
  public static <V, E> List<V> getEulerianCircuitVertices(UndirectedGraph<V, E> g) {
    // If the graph is not Eulerian then just return a null since no
    // Eulerian circuit exists
    if (!isEulerian(g)) {
      return null;
    }

    // The circuit will be represented by a linked list
    List<V> path = new LinkedList<V>();
    UndirectedGraph<V, E> sg = new UndirectedSubgraph<V, E>(g, null, null);
    path.add(sg.vertexSet().iterator().next());

    // Algorithm for finding an Eulerian circuit Basically this will find an
    // arbitrary circuit, then it will find another arbitrary circuit until
    // every edge has been traversed
    while (sg.edgeSet().size() > 0) {
      V v = null;

      // Find a vertex which has an edge that hasn't been traversed yet,
      // and keep its index position in the circuit list
      int index = 0;
      for (Iterator<V> iter = path.iterator(); iter.hasNext(); index++) {
        v = iter.next();
        if (sg.degreeOf(v) > 0) {
          break;
        }
      }

      // Finds an arbitrary circuit of the current vertex and
      // appends this into the circuit list
      while (sg.degreeOf(v) > 0) {
        for (Iterator<V> iter = sg.vertexSet().iterator(); iter.hasNext(); ) {
          V temp = iter.next();
          if (sg.containsEdge(v, temp)) {
            path.add(index, temp);
            sg.removeEdge(v, temp);
            v = temp;
            break;
          }
        }
      }
    }
    return path;
  }