예제 #1
0
    /** @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;
    }
예제 #2
0
  /**
   * @param vertexNumber the number which identifies the vertex v in this order.
   * @return the identifying numbers of all vertices which are connected to v by an edge incoming to
   *     v.
   */
  public int[] getInEdges(int vertexNumber) {
    if (cacheEdges && (incomingEdges[vertexNumber] != null)) {
      return incomingEdges[vertexNumber];
    }

    V v = getVertex(vertexNumber);
    Set<E> edgeSet;

    if (graph instanceof DirectedGraph<?, ?>) {
      edgeSet = ((DirectedGraph<V, E>) graph).incomingEdgesOf(v);
    } else {
      edgeSet = graph.edgesOf(v);
    }

    int[] vertexArray = new int[edgeSet.size()];
    int i = 0;

    for (E edge : edgeSet) {
      V source = graph.getEdgeSource(edge), target = graph.getEdgeTarget(edge);
      vertexArray[i++] = mapVertexToOrder.get(source.equals(v) ? target : source);
    }

    if (cacheEdges) {
      incomingEdges[vertexNumber] = vertexArray;
    }

    return vertexArray;
  }
예제 #3
0
  public void union(AbstractBaseGraph<V, E> g2) {
    if (!(this instanceof DirectedGraph<?, ?> && g2 instanceof DirectedGraph<?, ?>)) {
      return;
    }
    Set<V> vertexSet = g2.vertexSet();
    for (V vertex : vertexSet) {
      if (!containsVertex(vertex)) addVertex(vertex);
    }

    for (V vertex : vertexSet) {
      Set<E> edgeSet = g2.specifics.outgoingEdgesOf(vertex);
      for (E edge : edgeSet) {
        V sourceVertex = getEdgeSource(edge);
        V targetVertex = getEdgeTarget(edge);
        if (!allowingMultipleEdges && containsEdge(sourceVertex, targetVertex)) {
          continue;
        }

        if (!allowingLoops && sourceVertex.equals(targetVertex)) {
          continue;
        }

        if (containsEdge(edge)) {
          continue;
        } else {
          IntrusiveEdge intrusiveEdge = createIntrusiveEdge(edge, sourceVertex, targetVertex);

          edgeMap.put(edge, intrusiveEdge);
          specifics.addEdgeToTouchingVertices(edge);
        }
      }
    }
  }
예제 #4
0
    /** @see AbstractBaseGraph#removeEdgeFromTouchingVertices(Edge) */
    public void removeEdgeFromTouchingVertices(E e) {
      V source = getEdgeSource(e);
      V target = getEdgeTarget(e);

      getEdgeContainer(source).removeEdge(e);

      if (!source.equals(target)) {
        getEdgeContainer(target).removeEdge(e);
      }
    }
예제 #5
0
  /** @see Graph#addEdge(Object, Object, Object) */
  public boolean addEdge(V sourceVertex, V targetVertex, E e) {
    if (e == null) {
      throw new NullPointerException();
    } else if (containsEdge(e)) {
      return false;
    }

    assertVertexExist(sourceVertex);
    assertVertexExist(targetVertex);

    if (!allowingMultipleEdges && containsEdge(sourceVertex, targetVertex)) {
      return false;
    }

    if (!allowingLoops && sourceVertex.equals(targetVertex)) {
      throw new IllegalArgumentException(LOOPS_NOT_ALLOWED);
    }

    IntrusiveEdge intrusiveEdge = createIntrusiveEdge(e, sourceVertex, targetVertex);

    edgeMap.put(e, intrusiveEdge);
    specifics.addEdgeToTouchingVertices(e);

    return true;
  }
예제 #6
0
  /** @see Graph#addEdge(Object, Object) */
  public E addEdge(V sourceVertex, V targetVertex) {
    assertVertexExist(sourceVertex);
    assertVertexExist(targetVertex);

    if (!allowingMultipleEdges && containsEdge(sourceVertex, targetVertex)) {
      return null;
    }

    if (!allowingLoops && sourceVertex.equals(targetVertex)) {
      throw new IllegalArgumentException(LOOPS_NOT_ALLOWED);
    }

    E e = edgeFactory.createEdge(sourceVertex, targetVertex);

    if (containsEdge(e)) { // this restriction should stay!

      return null;
    } else {
      IntrusiveEdge intrusiveEdge = createIntrusiveEdge(e, sourceVertex, targetVertex);

      edgeMap.put(e, intrusiveEdge);
      specifics.addEdgeToTouchingVertices(e);

      return e;
    }
  }
예제 #7
0
    /** {@inheritDoc} */
    protected void encounterVertexAgain(V vertex, E edge) {
      super.encounterVertexAgain(vertex, edge);

      int i;

      if (root != null) {
        // For rooted detection, the path must either
        // double back to the root, or to a node of a cycle
        // which has already been detected.
        if (vertex.equals(root)) {
          i = 0;
        } else if ((cycleSet != null) && cycleSet.contains(vertex)) {
          i = 0;
        } else {
          return;
        }
      } else {
        i = path.indexOf(vertex);
      }

      if (i > -1) {
        if (cycleSet == null) {
          // we're doing yes/no cycle detection
          throw new CycleDetectedException();
        } else {
          for (; i < path.size(); ++i) {
            cycleSet.add(path.get(i));
          }
        }
      }
    }
  private void assertGetPath(V endVertex) {
    if (endVertex.equals(this.startVertex)) {
      throw new IllegalArgumentException("The end vertex is the same as the start vertex!");
    }

    if (!this.graph.containsVertex(endVertex)) {
      throw new IllegalArgumentException("Graph must contain the end vertex!");
    }
  }
예제 #9
0
    /** @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;
    }
예제 #10
0
  /**
   * 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);
          }
        }
      }
    }
  }
예제 #11
0
  /**
   * Returns the list of vertices whose path has been improved during the current pass. Complexity =
   *
   * <ul>
   *   <li>O(<code>m*k*(m+n)</code>) where <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>
   *
   * @see java.util.Iterator#next()
   */
  @Override
  public Set<V> next() {
    if (!this.startVertexEncountered) {
      encounterStartVertex();
    }

    // at the i-th pass the shortest paths with i edges are calculated.
    if (hasNext()) {
      Set<V> improvedVertices = new HashSet<>();

      for (V vertex : this.prevImprovedVertices) {
        if (!vertex.equals(this.endVertex)) {
          updateOutgoingVertices(vertex, improvedVertices);
        }
      }

      savePassData(improvedVertices);
      this.passNumber++;

      return improvedVertices;
    }
    throw new NoSuchElementException();
  }
예제 #12
0
  private V findPath(V root) {
    Set<V> used = new HashSet<>();
    Queue<V> q = new ArrayDeque<>();

    // Expand graph back from its contracted state
    path.clear();
    contracted.clear();

    graph.vertexSet().forEach(vertex -> contracted.put(vertex, vertex));

    used.add(root);
    q.add(root);

    while (!q.isEmpty()) {
      V v = q.remove();

      for (E e : graph.edgesOf(v)) {
        V to = graph.getEdgeSource(e);

        if (to.equals(v)) {
          to = graph.getEdgeTarget(e);
        }

        if ((contracted.get(v).equals(contracted.get(to))) || to.equals(match.get(v))) {
          continue;
        }

        // Check whether we've hit a 'blossom'
        if ((to.equals(root)) || ((match.containsKey(to)) && (path.containsKey(match.get(to))))) {
          V stem = lowestCommonAncestor(v, to);

          Set<V> blossom = new HashSet<>();

          markPath(v, to, stem, blossom);
          markPath(to, v, stem, blossom);

          graph
              .vertexSet()
              .stream()
              .filter(i -> contracted.containsKey(i) && blossom.contains(contracted.get(i)))
              .forEach(
                  i -> {
                    contracted.put(i, stem);
                    if (!used.contains(i)) {
                      used.add(i);
                      q.add(i);
                    }
                  });

          // Check whether we've had hit a loop (of even length (!) presumably)
        } else if (!path.containsKey(to)) {
          path.put(to, v);

          if (!match.containsKey(to)) {
            return to;
          }

          to = match.get(to);

          used.add(to);
          q.add(to);
        }
      }
    }
    return null;
  }