public static DirectedAcyclicGraph<Op, DefaultEdge> convert(Op op) { DirectedAcyclicGraph<Op, DefaultEdge> result = new DirectedAcyclicGraph<Op, DefaultEdge>(DefaultEdge.class); result.addVertex(op); convert(op, result); return result; }
/** * {@inheritDoc} * * <p> * The complexity of adding a new edge in the graph depends on the number of edges incident to * the "affected region", and should in general be faster than recomputing the whole topological * ordering from scratch. * * @throws IllegalArgumentException if the edge would induce a cycle in the graph */ @Override 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); boolean result; try { updateDag(sourceVertex, targetVertex); result = super.addEdge(sourceVertex, targetVertex, e); } catch (CycleFoundException ex) { throw new IllegalArgumentException(EDGE_WOULD_INDUCE_A_CYCLE); } return result; }
/** * {@inheritDoc} * * <p> * The complexity of adding a new edge in the graph depends on the number of edges incident to * the "affected region", and should in general be faster than recomputing the whole topological * ordering from scratch. * * @throws IllegalArgumentException if the edge would induce a cycle in the graph */ @Override public E addEdge(V sourceVertex, V targetVertex) { assertVertexExist(sourceVertex); assertVertexExist(targetVertex); E result; try { updateDag(sourceVertex, targetVertex); result = super.addEdge(sourceVertex, targetVertex); } catch (CycleFoundException e) { throw new IllegalArgumentException(EDGE_WOULD_INDUCE_A_CYCLE); } return result; }
private static Work[] getSetVariableValuesOrdered(BaseElement element) { Work[] values = setVariablePropertyCache.get(element); if (values == null) { String[] expressions = DemoModelInstrumentator.readCamundaPropertyMulti(element, "simulateSetVariable").toArray(new String[] {}); values = new Work[expressions.length]; DirectedAcyclicGraph<Work, Object> graph = new DirectedAcyclicGraph<>(Object.class); for (int i = 0; i < expressions.length; i++) { values[i] = new Work(expressions[i]); graph.addVertex(values[i]); } for (Work currentWork : values) { for (Work otherWork : values) { if (currentWork.valueExpression.matches(".*\\W" + Pattern.quote(otherWork.variableExpression) + "\\W.*")) { try { graph.addEdge(otherWork, currentWork); } catch (IllegalArgumentException e) { LOG.warn("Possible cycle in simulateSetVariable-dependencies detected when checking '{}'", currentWork.valueExpression); } } } } int i = 0; for (Iterator<Work> iterator = graph.iterator(); iterator.hasNext();) { Work next = iterator.next(); values[i++] = next; } setVariablePropertyCache.put(element, values); } return values; }
/** * Computes the transitive closure of a directed acyclic graph in $O(nm)$ * * @param graph - Graph to compute transitive closure for. * @param <V> the graph vertex type * @param <E> the graph edge type */ public <V, E> void closeDirectedAcyclicGraph(DirectedAcyclicGraph<V, E> graph) { Deque<V> orderedVertices = new ArrayDeque<>(graph.vertexSet().size()); new TopologicalOrderIterator<>(graph).forEachRemaining(orderedVertices::addFirst); for (V vertex : orderedVertices) { for (V successor : Graphs.successorListOf(graph, vertex)) { for (V closureVertex : Graphs.successorListOf(graph, successor)) { graph.addEdge(vertex, closureVertex); } } } }
/** * Create a builder for this kind of graph. * * @param edgeClass class on which to base factory for edges * @param <V> the graph vertex type * @param <E> the graph edge type * @return a builder for this kind of graph */ public static <V, E> GraphBuilder<V, E, ? extends DirectedAcyclicGraph<V, E>> createBuilder( Class<? extends E> edgeClass) { return new GraphBuilder<>(new DirectedAcyclicGraph<>(edgeClass)); }
/** * Update as if a new edge is added. * * @param sourceVertex the source vertex * @param targetVertex the target vertex */ private void updateDag(V sourceVertex, V targetVertex) throws CycleFoundException { Integer lb = topoOrderMap.getTopologicalIndex(targetVertex); Integer ub = topoOrderMap.getTopologicalIndex(sourceVertex); if (lb < ub) { Set<V> df = new HashSet<>(); Set<V> db = new HashSet<>(); // discovery Region affectedRegion = new Region(lb, ub); VisitedStrategy visited = visitedStrategyFactory.getVisitedStrategy(affectedRegion); // throws CycleFoundException if there is a cycle dfsF(targetVertex, df, visited, affectedRegion); dfsB(sourceVertex, db, visited, affectedRegion); reorder(df, db, visited); /* * if we do a reorder, then the topology has been updated */ ++topoModCount; } }
for (E inEdge : incomingEdgesOf(vertex)) { V previousVertex = getEdgeSource(inEdge); Integer previousVertexTopoIndex = topoOrderMap.getTopologicalIndex(previousVertex);
for (E outEdge : outgoingEdgesOf(vertex)) { V nextVertex = getEdgeTarget(outEdge); Integer nextVertexTopoIndex = topoOrderMap.getTopologicalIndex(nextVertex);
/** * Create a builder for this kind of graph. * * @param edgeSupplier edge supplier for the edges * @param <V> the graph vertex type * @param <E> the graph edge type * @return a builder for this kind of graph */ public static <V, E> GraphBuilder<V, E, ? extends DirectedAcyclicGraph<V, E>> createBuilder( Supplier<E> edgeSupplier) { return new GraphBuilder<>(new DirectedAcyclicGraph<>(null, edgeSupplier, false)); }
public static DirectedAcyclicGraph<Op, DefaultEdge> convert(Op op) { DirectedAcyclicGraph<Op, DefaultEdge> result = new DirectedAcyclicGraph<Op, DefaultEdge>(DefaultEdge.class); result.addVertex(op); convert(op, result); return result; }