示例#1
0
        public void MinCutTest()
        {
            Graph <BasicEdgeNode, BasicEdge> g = new Graph <BasicEdgeNode, BasicEdge>(BasicEdge.New);
            // this graph is from Cormen et al, fig 27.1
            BasicEdgeNode s  = new BasicEdgeNode("s");
            BasicEdgeNode v1 = new BasicEdgeNode("v1");
            BasicEdgeNode v2 = new BasicEdgeNode("v2");
            BasicEdgeNode v3 = new BasicEdgeNode("v3");
            BasicEdgeNode v4 = new BasicEdgeNode("v4");
            BasicEdgeNode t  = new BasicEdgeNode("t");

            g.Nodes.Add(s);
            g.Nodes.Add(v1);
            g.Nodes.Add(v2);
            g.Nodes.Add(v3);
            g.Nodes.Add(v4);
            g.Nodes.Add(t);
            Dictionary <BasicEdge, float> capacity = new Dictionary <BasicEdge, float>();
            BasicEdge e;

            e           = g.AddEdge(s, v1);
            capacity[e] = 16;
            e           = g.AddEdge(s, v2);
            capacity[e] = 13;
            e           = g.AddEdge(v1, v2);
            capacity[e] = 10;
            e           = g.AddEdge(v1, v3);
            capacity[e] = 12;
            e           = g.AddEdge(v2, v1);
            capacity[e] = 4;
            e           = g.AddEdge(v2, v4);
            capacity[e] = 14;
            e           = g.AddEdge(v3, v2);
            capacity[e] = 9;
            e           = g.AddEdge(v3, t);
            capacity[e] = 20;
            e           = g.AddEdge(v4, v3);
            capacity[e] = 7;
            e           = g.AddEdge(v4, t);
            capacity[e] = 4;
            var mc = new MinCut <BasicEdgeNode, BasicEdge>(g, e2 => capacity[e2]);

            mc.Sources.Add(s);
            mc.Sinks.Add(t);
            // sourceGroup should be s,v1,v2,v4
            Set <BasicEdgeNode> sourceGroup = mc.GetSourceGroup();

            Console.WriteLine("sourceGroup = {0}", sourceGroup);
            Assert.True(sourceGroup.Count == 4 && sourceGroup.ContainsAll(new BasicEdgeNode[] { s, v1, v2, v4 }));
            mc.Sources.Add(v1);
            mc.Sinks.Add(v3);
            sourceGroup = mc.GetSourceGroup();
            Console.WriteLine("sourceGroup = {0}", sourceGroup);
            Assert.True(sourceGroup.Count == 4 && sourceGroup.ContainsAll(new BasicEdgeNode[] { s, v1, v2, v4 }));
            capacity[g.GetEdge(v2, v4)] = 1;
            sourceGroup = mc.GetSourceGroup();
            Console.WriteLine("sourceGroup = {0}", sourceGroup);
            Assert.True(sourceGroup.Count == 3 && sourceGroup.ContainsAll(new BasicEdgeNode[] { s, v1, v2 }));
        }
示例#2
0
        public void MinCutCycleTest()
        {
            Graph <BasicEdgeNode, BasicEdge> g = new Graph <BasicEdgeNode, BasicEdge>(BasicEdge.New);
            // cycle graph
            BasicEdgeNode s  = new BasicEdgeNode("s");
            BasicEdgeNode v1 = new BasicEdgeNode("v1");
            BasicEdgeNode v2 = new BasicEdgeNode("v2");
            BasicEdgeNode t  = new BasicEdgeNode("t");

            g.Nodes.Add(s);
            g.Nodes.Add(v1);
            g.Nodes.Add(v2);
            g.Nodes.Add(t);
            Dictionary <BasicEdge, float> capacity = new Dictionary <BasicEdge, float>();
            BasicEdge e;

            e           = g.AddEdge(s, v1);
            capacity[e] = 16;
            e           = g.AddEdge(v1, v2);
            capacity[e] = 10;
            e           = g.AddEdge(v2, s);
            capacity[e] = 14;
            var mc = new MinCut <BasicEdgeNode, BasicEdge>(g, e2 => capacity[e2]);

            mc.Sources.Add(s);
            mc.Sinks.Add(s);
            // sourceGroup should be s,v1
            Set <BasicEdgeNode> sourceGroup = mc.GetSourceGroup();

            Console.WriteLine("sourceGroup = {0}", sourceGroup);
            Assert.True(sourceGroup.Count == 2 && sourceGroup.ContainsAll(new BasicEdgeNode[] { s, v1 }));
            mc.Sinks.Remove(s);
            // test the case where t is not reachable from s
            mc.Sinks.Add(t);
            // sourceGroup should be s,v1,v2
            sourceGroup = mc.GetSourceGroup();
            Console.WriteLine("sourceGroup = {0}", sourceGroup);
            Assert.True(sourceGroup.Count == 3 && sourceGroup.ContainsAll(new BasicEdgeNode[] { s, v1, v2 }));
            // test IsSinkEdge
            mc.Sinks.Remove(t);
            e             = g.GetEdge(v2, s);
            mc.IsSinkEdge = edge => edge.Equals(e);
            // sourceGroup should be s,v1
            sourceGroup = mc.GetSourceGroup();
            Console.WriteLine("sourceGroup = {0}", sourceGroup);
            Assert.True(sourceGroup.Count == 2 && sourceGroup.ContainsAll(new BasicEdgeNode[] { s, v1 }));
        }
示例#3
0
        /// <summary>
        /// Test of solving an initializer scheduling problem as a min cut problem.
        /// </summary>
        //[Fact]
        internal void MinCutTest3()
        {
            Graph <BasicEdgeNode, BasicEdge> g = new Graph <BasicEdgeNode, BasicEdge>(BasicEdge.New);
            BasicEdgeNode s  = new BasicEdgeNode("s");
            BasicEdgeNode v1 = new BasicEdgeNode("v1");
            BasicEdgeNode v2 = new BasicEdgeNode("v2");
            BasicEdgeNode v3 = new BasicEdgeNode("v3");
            BasicEdgeNode b1 = new BasicEdgeNode("b1");
            BasicEdgeNode b2 = new BasicEdgeNode("b2");
            BasicEdgeNode t  = new BasicEdgeNode("t");

            g.Nodes.Add(s);
            g.Nodes.Add(v1);
            g.Nodes.Add(v2);
            g.Nodes.Add(v3);
            g.Nodes.Add(b1);
            g.Nodes.Add(b2);
            g.Nodes.Add(t);
            Dictionary <BasicEdge, float> capacity = new Dictionary <BasicEdge, float>();

            foreach (var node in new[] { v1, v2, v3 })
            {
                BasicEdge e2 = g.AddEdge(s, node);
                capacity[e2] = 1;
            }
            BasicEdgeNode[,] pairs =
            {
                { v1, b1 },
                { v2, b1 },
                { v2, b2 },
                { v3, b2 }
            };
            for (int i = 0; i < pairs.GetLength(0); i++)
            {
                var       source = pairs[i, 0];
                var       target = pairs[i, 1];
                BasicEdge e2     = g.AddEdge(source, target);
                capacity[e2] = 1;
            }
            BasicEdge e;

            e           = g.AddEdge(b1, t);
            capacity[e] = 1.1f;
            e           = g.AddEdge(b2, t);
            capacity[e] = 1.1f;
            var mc = new MinCut <BasicEdgeNode, BasicEdge>(g, e2 => capacity[e2]);

            mc.Sources.Add(s);
            mc.Sinks.Add(t);
            Set <BasicEdgeNode> sourceGroup = mc.GetSourceGroup();

            Console.WriteLine("sourceGroup = {0}", sourceGroup);
        }
        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);
        }