/// <summary> /// Returns all nodes in the schedule whose target appears prior to the node. /// </summary> /// <param name="g"></param> /// <param name="schedule"></param> /// <returns></returns> internal static Set <NodeIndex> CollectUses(IndexedGraph g, IEnumerable <NodeIndex> schedule) { Set <NodeIndex> uses = new Set <NodeIndex>(); Set <NodeIndex> available = new Set <NodeIndex>(); foreach (NodeIndex node in schedule) { foreach (NodeIndex source in g.SourcesOf(node)) { if (!available.Contains(source)) { uses.Add(source); } } available.Add(node); } return(uses); }
/// <summary> /// Returns all nodes in the schedule whose target appears prior to the node. /// </summary> /// <param name="g"></param> /// <param name="schedule"></param> /// <param name="isDeleted"></param> /// <returns></returns> internal static Set <NodeIndex> CollectUses(IndexedGraph g, IEnumerable <NodeIndex> schedule, Func <EdgeIndex, bool> isDeleted = null) { Set <NodeIndex> uses = new Set <NodeIndex>(); Set <NodeIndex> available = new Set <NodeIndex>(); foreach (NodeIndex node in schedule) { foreach (EdgeIndex edge in g.EdgesInto(node).Where(e => isDeleted == null || !isDeleted(e))) { NodeIndex source = g.SourceOf(edge); if (!available.Contains(source)) { uses.Add(source); } } available.Add(node); } return(uses); }
int CalculateNodeDepth(IndexedGraph <string, Orbit> orbits) { foreach (var orbit in orbits.DepthFirstWalk()) { if (orbit.Name != "COM") { orbit.Depth = orbits.GetParent(orbit).Depth + 1; } } var total = 0; foreach (var orbit in orbits.DepthFirstWalk()) { total += orbit.Depth; } return(total); }
IndexedGraph <string, Orbit> BuildOrbits(Dictionary <string, string> orbitsDef) { var orbits = new IndexedGraph <string, Orbit>(); orbits["COM"] = new Orbit("COM"); foreach (var orbit in orbitsDef.Keys) { orbits[orbit] = new Orbit(orbit); } foreach (var orbit in orbitsDef) { orbits.AddParentChildLink(orbit.Value, orbit.Key); } orbits.Root = orbits["COM"]; return(orbits); }
internal static IEnumerable <NodeIndex> GetOverwrites(BasicTransformContext context, IndexedGraph dependencyGraph, NodeIndex writer, List <IStatement> nodes, Dictionary <IStatement, int> indexOfNode) { IStatement ist = nodes[writer]; DependencyInformation di = context.InputAttributes.Get <DependencyInformation>(ist); if (di == null) { context.Error("Dependency information not found for statement: " + ist); di = new DependencyInformation(); } foreach (IStatement previousWriteStmt in di.Overwrites) { NodeIndex previousWriter = indexOfNode[previousWriteStmt]; if (previousWriter < writer) { yield return(previousWriter); } } }
public void VisualizeDependencyGraph(IndexedGraph dg, IEnumerable <EdgeStylePredicate> edgeStyles = null, Func <int, string> nodeName = null, Func <int, string> edgeName = null, string visualizationTitle = "Dependency_Graph") { DependencyGraphView view = new DependencyGraphView(dg, edgeStyles, nodeName, edgeName); view.Show(visualizationTitle); }
protected override void DoConvertMethodBody(IList <IStatement> outputs, IList <IStatement> inputs) { List <int> whileNumberOfNode = new List <int>(); List <int> fusedCountOfNode = new List <int>(); List <List <IStatement> > containersOfNode = new List <List <IStatement> >(); // the code may have multiple while(true) loops, however these must be disjoint. // therefore we treat 'while' as one container, but give each loop a different 'while number'. int outerWhileCount = 0; int currentOuterWhileNumber = 0; int currentFusedCount = 0; List <Set <IVariableDeclaration> > loopVarsOfWhileNumber = new List <Set <IVariableDeclaration> >(); // build the dependency graph var g = new DependencyGraph2(context, inputs, DependencyGraph2.BackEdgeHandling.Ignore, delegate(IWhileStatement iws) { if (iws is IFusedBlockStatement) { if (iws.Condition is IVariableReferenceExpression) { currentFusedCount++; } } else { outerWhileCount++; currentOuterWhileNumber = outerWhileCount; } }, delegate(IWhileStatement iws) { if (iws is IFusedBlockStatement) { if (iws.Condition is IVariableReferenceExpression) { currentFusedCount--; } } else { currentOuterWhileNumber = 0; } }, delegate(IConditionStatement ics) { }, delegate(IConditionStatement ics) { }, delegate(IStatement ist, int targetIndex) { int whileNumber = currentOuterWhileNumber; whileNumberOfNode.Add(whileNumber); fusedCountOfNode.Add(currentFusedCount); List <IStatement> containers = new List <IStatement>(); LoopMergingTransform.UnwrapStatement(ist, containers); containersOfNode.Add(containers); for (int i = 0; i < currentFusedCount; i++) { if (containers[i] is IForStatement ifs) { var loopVar = Recognizer.LoopVariable(ifs); if (loopVarsOfWhileNumber.Count <= whileNumber) { while (loopVarsOfWhileNumber.Count <= whileNumber) { loopVarsOfWhileNumber.Add(new Set <IVariableDeclaration>()); } } Set <IVariableDeclaration> loopVars = loopVarsOfWhileNumber[whileNumber]; loopVars.Add(loopVar); } } }); var nodes = g.nodes; var dependencyGraph = g.dependencyGraph; for (int whileNumber = 1; whileNumber < loopVarsOfWhileNumber.Count; whileNumber++) { foreach (var loopVar in loopVarsOfWhileNumber[whileNumber]) { // Any statement (in the while loop) that has a forward descendant and a backward descendant will be cloned, so we want to minimize the number of such nodes. // The free variables in this problem are the loop directions at the leaf statements, since all other loop directions are forced by these. // We find the optimal labeling of the free variables by solving a min cut problem on a special network. // The network is constructed so that the cost of a cut is equal to the number of statements that will be cloned. // The network has 2 nodes for every statement: an in-node and an out-node. // For a non-leaf statement, there is a capacity 1 edge from the in-node to out-node. This edge is cut when the statement is cloned. // For a leaf statement, there is an infinite capacity edge in both directions, or equivalently a single node. // If statement A depends on statement B, then there is an infinite capacity edge from in-A to in-B, and from out-B to out-A, // representing the fact that cloning A requires cloning B, but not the reverse. // If a statement must appear with a forward loop, it is connected to the source. // If a statement must appear with a backward loop, it is connected to the sink. // construct a capacitated graph int inNodeStart = 0; int outNodeStart = inNodeStart + dependencyGraph.Nodes.Count; int sourceNode = outNodeStart + dependencyGraph.Nodes.Count; int sinkNode = sourceNode + 1; int cutNodeCount = sinkNode + 1; Func <NodeIndex, int> getInNode = node => node + inNodeStart; Func <NodeIndex, int> getOutNode = node => node + outNodeStart; IndexedGraph network = new IndexedGraph(cutNodeCount); const float infinity = 1000000f; List <float> capacity = new List <float>(); List <NodeIndex> nodesOfInterest = new List <NodeIndex>(); foreach (var node in dependencyGraph.Nodes) { if (whileNumberOfNode[node] != whileNumber) { continue; } NodeIndex source = node; List <IStatement> containersOfSource = containersOfNode[source]; bool hasLoopVar = containersOfSource.Any(container => container is IForStatement && Recognizer.LoopVariable((IForStatement)container) == loopVar); if (!hasLoopVar) { continue; } nodesOfInterest.Add(node); IStatement sourceSt = nodes[source]; var readAfterWriteEdges = dependencyGraph.EdgesOutOf(source).Where(edge => !g.isWriteAfterRead[edge]); bool isLeaf = true; int inNode = getInNode(node); int outNode = getOutNode(node); foreach (var target in readAfterWriteEdges.Select(dependencyGraph.TargetOf)) { List <IStatement> containersOfTarget = containersOfNode[target]; IStatement targetSt = nodes[target]; ForEachMatchingLoopVariable(containersOfSource, containersOfTarget, (loopVar2, afs, bfs) => { if (loopVar2 == loopVar) { int inTarget = getInNode(target); int outTarget = getOutNode(target); network.AddEdge(inTarget, inNode); capacity.Add(infinity); network.AddEdge(outNode, outTarget); capacity.Add(infinity); isLeaf = false; } }); } if (isLeaf) { if (debug) { log.Add($"loopVar={loopVar.Name} leaf {sourceSt}"); } network.AddEdge(inNode, outNode); capacity.Add(infinity); network.AddEdge(outNode, inNode); capacity.Add(infinity); } else { network.AddEdge(inNode, outNode); capacity.Add(1f); } int fusedCount = fusedCountOfNode[node]; Direction desiredDirectionOfSource = GetDesiredDirection(loopVar, containersOfSource, fusedCount); if (desiredDirectionOfSource == Direction.Forward) { if (debug) { log.Add($"loopVar={loopVar.Name} forward {sourceSt}"); } network.AddEdge(sourceNode, inNode); capacity.Add(infinity); } else if (desiredDirectionOfSource == Direction.Backward) { if (debug) { log.Add($"loopVar={loopVar.Name} backward {sourceSt}"); } network.AddEdge(outNode, sinkNode); capacity.Add(infinity); } } network.IsReadOnly = true; // compute the min cut MinCut <NodeIndex, EdgeIndex> mc = new MinCut <EdgeIndex, EdgeIndex>(network, e => capacity[e]); mc.Sources.Add(sourceNode); mc.Sinks.Add(sinkNode); Set <NodeIndex> sourceGroup = mc.GetSourceGroup(); foreach (NodeIndex node in nodesOfInterest) { IStatement sourceSt = nodes[node]; bool forwardIn = sourceGroup.Contains(getInNode(node)); bool forwardOut = sourceGroup.Contains(getOutNode(node)); if (forwardIn != forwardOut) { if (debug) { log.Add($"loopVar={loopVar.Name} will clone {sourceSt}"); } } else if (forwardIn) { if (debug) { log.Add($"loopVar={loopVar.Name} wants forward {sourceSt}"); } } else { if (debug) { log.Add($"loopVar={loopVar.Name} wants backward {sourceSt}"); } var containers = containersOfNode[node]; bool isForwardLoop = true; foreach (var container in containers) { if (container is IForStatement) { IForStatement ifs = (IForStatement)container; if (Recognizer.LoopVariable(ifs) == loopVar) { isForwardLoop = Recognizer.IsForwardLoop(ifs); } } } if (isForwardLoop) { Set <IVariableDeclaration> loopVarsToReverse; if (!loopVarsToReverseInStatement.TryGetValue(sourceSt, out loopVarsToReverse)) { // TODO: re-use equivalent sets loopVarsToReverse = new Set <IVariableDeclaration>(); loopVarsToReverseInStatement.Add(sourceSt, loopVarsToReverse); } loopVarsToReverse.Add(loopVar); } } } } } base.DoConvertMethodBody(outputs, inputs); }
public IndexedAStarPathFinder(IndexedGraph <N> graph) : this(graph, false) { }
public void VisualizeDependencyGraph(IndexedGraph dg, IEnumerable <EdgeStylePredicate> edgeStyles = null, Func <int, string> nodeName = null, Func <int, string> edgeName = null, string visualizationTitle = "Infer.NET Dependency Graph Viewer") { var view = new DependencyGraphView(dg, edgeStyles, nodeName, edgeName); view.RunInForm(visualizationTitle); }
internal DependencyGraphView(IndexedGraph dg, IEnumerable <EdgeStylePredicate> edgeStyles = null, Func <NodeIndex, string> nodeName = null, Func <EdgeIndex, string> edgeName = null) { this.dg = dg; this.edgeStyles = edgeStyles; this.nodeName = nodeName; this.edgeName = edgeName; nodeOf = dg.CreateNodeData <Node>(null); OnGraphChanged(); panel.Dock = DockStyle.Fill; gviewer.Dock = DockStyle.Fill; panel.Controls.Add(gviewer); if (edgeStyles != null) { // draw the legend TableLayoutPanel legend = new TableLayoutPanel(); legend.AutoSize = true; legend.ColumnCount = 2 * edgeStyles.Count(); foreach (EdgeStylePredicate esp in edgeStyles) { PictureBox pic = new PictureBox(); pic.SizeMode = PictureBoxSizeMode.AutoSize; legend.Controls.Add(pic); int size = 8; var bitmap = new System.Drawing.Bitmap(size, size); var graphics = System.Drawing.Graphics.FromImage(bitmap); var color = System.Drawing.Color.Black; if ((esp.Style & EdgeStyle.Dimmed) > 0) { color = System.Drawing.Color.LightGray; } else if ((esp.Style & EdgeStyle.Back) > 0) { color = System.Drawing.Color.Red; } else if ((esp.Style & EdgeStyle.Blue) > 0) { color = System.Drawing.Color.Blue; } int width = 1; if ((esp.Style & EdgeStyle.Bold) > 0) { width = 2; } var pen = new System.Drawing.Pen(color, width); if ((esp.Style & EdgeStyle.Dashed) > 0) { pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash; } int y = bitmap.Height / 2; graphics.DrawLine(pen, 0, y, bitmap.Width - 1, y); pic.Image = bitmap; ToolLabel label = new ToolLabel(); label.Text = esp.Name; label.AutoSize = true; legend.Controls.Add(label); } legend.Anchor = AnchorStyles.None; // centers the legend in its parent TableLayoutPanel legendPanel = new TableLayoutPanel(); legendPanel.AutoSize = true; legendPanel.BackColor = System.Drawing.Color.LightGray; legendPanel.Controls.Add(legend); legendPanel.Dock = DockStyle.Bottom; panel.Controls.Add(legendPanel); } }
#pragma warning restore 162 #endif private void PostProcess() { // create a dependency graph between MethodInvokes Dictionary <IVariableDeclaration, List <int> > mutationsOfVariable = new Dictionary <IVariableDeclaration, List <NodeIndex> >(); IndexedGraph g = new IndexedGraph(factorExprs.Count); foreach (NodeIndex node in g.Nodes) { IExpression factor = factorExprs[node]; NodeInfo info = GetNodeInfo(factor); for (int i = 0; i < info.arguments.Count; i++) { if (info.isReturnOrOut[i]) { // this is a mutation. add to mutationsOfVariable. IVariableDeclaration ivd = Recognizer.GetVariableDeclaration(info.arguments[i]); if (ivd != null && CodeRecognizer.IsStochastic(context, ivd)) { List <int> nodes; if (!mutationsOfVariable.TryGetValue(ivd, out nodes)) { nodes = new List <NodeIndex>(); mutationsOfVariable[ivd] = nodes; } nodes.Add(node); } } } } foreach (NodeIndex node in g.Nodes) { IExpression factor = factorExprs[node]; NodeInfo info = GetNodeInfo(factor); for (int i = 0; i < info.arguments.Count; i++) { if (!info.isReturnOrOut[i]) { // not a mutation. create a dependency on all mutations. IVariableDeclaration ivd = Recognizer.GetVariableDeclaration(info.arguments[i]); if (ivd != null && CodeRecognizer.IsStochastic(context, ivd)) { foreach (NodeIndex source in mutationsOfVariable[ivd]) { g.AddEdge(source, node); } } } } } List <NodeIndex> topo_nodes = new List <NodeIndex>(); DepthFirstSearch <NodeIndex> dfs = new DepthFirstSearch <NodeIndex>(g.SourcesOf, g); dfs.FinishNode += delegate(NodeIndex node) { IExpression factor = factorExprs[node]; ProcessFactor(factor, MessageDirection.Forwards); topo_nodes.Add(node); }; // process nodes forward dfs.SearchFrom(g.Nodes); // process nodes backward for (int i = topo_nodes.Count - 1; i >= 0; i--) { NodeIndex node = topo_nodes[i]; IExpression factor = factorExprs[node]; ProcessFactor(factor, MessageDirection.Backwards); } }