/** * Generate the topological ordering for the given jobGraph. * * @param jobgraph the job graph * @return a {@link List} of the {@link IndigoJob} in topological order * @throws IllegalArgumentException if the graph has cycles (hence no topological order exists). */ protected List<IndigoJob> getJobsTopologicalOrder(Map<String, IndigoJob> jobgraph) { DefaultDirectedGraph<IndigoJob, DefaultEdge> graph = new DefaultDirectedGraph<IndigoJob, DefaultEdge>(DefaultEdge.class); for (IndigoJob job : jobgraph.values()) { graph.addVertex(job); } for (IndigoJob job : jobgraph.values()) { for (IndigoJob parent : job.getParents()) { graph.addEdge(parent, job); // job depends on parent } } LOG.debug("IndigoJob graph: {}", graph.toString()); // Are there cycles in the dependencies. CycleDetector<IndigoJob, DefaultEdge> cycleDetector = new CycleDetector<IndigoJob, DefaultEdge>(graph); if (cycleDetector.detectCycles()) { LOG.error("Job graph has cycles!"); throw new IllegalArgumentException( String.format( "Failed to generate topological order for a graph with cycles: <%s>", graph)); } TopologicalOrderIterator<IndigoJob, DefaultEdge> orderIterator = new TopologicalOrderIterator<IndigoJob, DefaultEdge>(graph); List<IndigoJob> topoOrder = Lists.newArrayList(orderIterator); LOG.debug("IndigoJob topological order: {}", topoOrder); return topoOrder; }
/** * Indicate if a variable is involved in a cycle containing non-local variables * * <p>These cycles are immutable. * * @param ref */ private boolean immutableCycle(CtVariableReference ref) { Set<CtVariableReference> cycle = cycleDetector.findCyclesContainingVertex(ref); for (CtVariableReference r : cycle) { if (!declaredInsideBlock.contains(r)) return true; } return false; }
@Help("general statistics on the session") public String main(WorkingSession session) { StringBuilder res = new StringBuilder(); res.append("There are " + session.graph().gavs().size() + " gavs<br/>"); StrongConnectivityInspector<GAV, Relation> conn = new StrongConnectivityInspector<>(session.graph().internalGraph()); res.append( "There are " + conn.stronglyConnectedSets().size() + " strongly connected components<br/>"); ConnectivityInspector<GAV, Relation> ccon = new ConnectivityInspector<>(session.graph().internalGraph()); res.append("There are " + ccon.connectedSets().size() + " weakly connected components<br/>"); CycleDetector<GAV, Relation> cycles = new CycleDetector<GAV, Relation>(session.graph().internalGraph()); res.append("Is there cycles ? " + cycles.detectCycles() + "<br/>"); return res.toString(); }
/** * Indicate if the statement contains a mutable expression * * <p>A mutability expression is an expression that assigns value to a variable in the left side * using that variable also in the right side, like this: * * <p>a = a * b * * <p>or like this: c = a * 2 a = c + b * * <p> * * <p>Also, all unary operators and are mutable: a--; a++; * * @param statement Statement to check whether is a mutability expression * @return True if it is a mutability expression */ private Mutability mutability(CtElement statement) { Mutability result = Mutability.ERASABLE; if (statement instanceof CtAssignment) { CtAssignment e = (CtAssignment) statement; List<CtVariableAccess> left = accessOfLeftExpression(e.getAssigned()); for (CtVariableAccess access : left) { CtVariableReference ref = access.getVariable(); try { if (!declaredInsideBlock.contains(ref) && cycleDetector.detectCyclesContainingVertex(ref)) { return Mutability.IMMUTABLE; } } catch (IllegalArgumentException ex) { continue; } } } if (containNonLocalOperatorAssignment(statement)) return Mutability.IMMUTABLE; else if (containsNonLocalUnaryOperators(statement)) return Mutability.REPLACEABLE; else return Mutability.ERASABLE; }
/** * Initialize a created SDFAdpaterDemo with the given Graph to display * * @param graphIn The graph to display */ public void init(DirectedAcyclicGraph graphIn) { DirectedAcyclicGraph graph = (DirectedAcyclicGraph) graphIn.clone(); // create a JGraphT graph model = new DAGListenableGraph(); // create a visualization using JGraph, via an adapter jgAdapter = new JGraphModelAdapter<DAGVertex, DAGEdge>(model); JGraph jgraph = new JGraph(jgAdapter); adjustDisplaySettings(jgraph); getContentPane().add(jgraph); resize(DEFAULT_SIZE); System.out.println(" graph has " + graph.vertexSet().size() + " vertice, including broadcast"); for (DAGVertex vertex : graph.vertexSet()) { model.addVertex(vertex); } for (DAGEdge edge : graph.edgeSet()) { DAGEdge newEdge = model.addEdge(graph.getEdgeSource(edge), graph.getEdgeTarget(edge)); for (String propertyKey : edge.getPropertyBean().keys()) { Object property = edge.getPropertyBean().getValue(propertyKey); newEdge.getPropertyBean().setValue(propertyKey, property); } } CycleDetector<DAGVertex, DAGEdge> detector = new CycleDetector<DAGVertex, DAGEdge>(model); GraphIterator<DAGVertex, DAGEdge> order; if (detector.detectCycles()) { order = new DAGIterator(model); } else { order = new TopologicalOrderIterator<DAGVertex, DAGEdge>(model); } Vector<DAGVertex> vertices = new Vector<DAGVertex>(); int x = 0; int y = 100; int ymax = y; DAGVertex previousVertex = null; while (order.hasNext()) { DAGVertex nextVertex = order.next(); vertices.add(nextVertex); if (previousVertex != null && model.getEdge(nextVertex, previousVertex) == null && model.getEdge(previousVertex, nextVertex) == null) { y += 50; this.positionVertexAt(nextVertex, x, y); if (y > ymax) { ymax = y; } } else { y = 100; x += 200; this.positionVertexAt(nextVertex, x, 100); previousVertex = nextVertex; } } JFrame frame = new JFrame(); jgraph.setPreferredSize(new Dimension(x + 200, ymax + 300)); frame.setContentPane(new ScrollPane()); frame.getContentPane().add(this); frame.setTitle("DAG Transformation"); if (adapters.size() == 1) { frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } else { frame.setDefaultCloseOperation(WindowConstants.HIDE_ON_CLOSE); } frame.pack(); frame.setVisible(true); }
protected static Element findRootLinkOfJointTree( ArrayList<Element> jointList, ArrayList<Element> linkList) { SimpleDirectedGraph<String, DefaultEdge> graph = new SimpleDirectedGraph<String, DefaultEdge>(DefaultEdge.class); for (Element joint : jointList) { Element parent = (Element) joint.getElementsByTagName("parent").item(0); Element child = (Element) joint.getElementsByTagName("child").item(0); String parentLinkName = parent.getAttribute("link"); String childLinkName = child.getAttribute("link"); if (!graph.containsVertex(parentLinkName)) { graph.addVertex(parentLinkName); } if (!graph.containsVertex(childLinkName)) { graph.addVertex(childLinkName); } if (graph.containsEdge(parentLinkName, childLinkName)) { throw new RuntimeException( "Multiple joints between parent link '" + parentLinkName + "' and child link '" + childLinkName + "'"); } else if (graph.containsEdge(childLinkName, parentLinkName)) { throw new RuntimeException( "Inverse joint between parent link '" + parentLinkName + "' and child link '" + childLinkName + "' already exists"); } else { graph.addEdge(parentLinkName, childLinkName); } } CycleDetector<String, DefaultEdge> cycDet; cycDet = new CycleDetector<String, DefaultEdge>(graph); Set<String> cycSet = cycDet.findCycles(); if (cycSet.size() > 0) { Iterator<String> it = cycSet.iterator(); StringBuffer sb = new StringBuffer(it.next()); while (it.hasNext()) { sb.append(", " + it.next()); } throw new RuntimeException("Cycle in joint graph, involving elements '" + sb + "'"); } TopologicalOrderIterator<String, DefaultEdge> toit; toit = new TopologicalOrderIterator<String, DefaultEdge>(graph); String rootLinkName = toit.next(); Element rootLink = null; for (Element link : linkList) { if (link.getAttribute("name").equals(rootLinkName)) { rootLink = link; break; } } if (rootLink == null) { throw new RuntimeException("Root joint's parent '" + rootLinkName + "' doesn't exist"); } return rootLink; }