/** @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; }
/** * @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; }
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); } } } }
/** @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); } }
/** @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; }
/** @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; } }
/** {@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!"); } }
/** @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; }
/** * 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); } } } } }
/** * 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(); }
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; }