public void Graph_with_cycle_over_2_vertices() {
            g.Insert(new Edge{v = 0, w = 1});
            g.Insert(new Edge{v = 1, w = 0});

            var sc = new StrongComponents(g);

            Assert.That(sc.Count, Is.EqualTo(g.V - 1));
            Assert.That(sc.StronglyReachable(0, 1), Is.True);
        }
        public void Graph_without_cycles() {
            g.Insert(new Edge{v = 0, w = 1});
            g.Insert(new Edge{v = 1, w = 2});
            g.Insert(new Edge{v = 2, w = 3});

            var sc = new StrongComponents(g);

            Assert.That(sc.Count, Is.EqualTo(g.V));
            Assert.That(sc.StronglyReachable(0, 3), Is.False);
        }
Example #3
0
        /// <summary>
        /// Solves the 2-SAT problem and returns a possible variable assignment if it exits.
        /// </summary>
        /// <returns>The variable assignment, or null if no solution exists.</returns>
        public bool[] Solve()
        {
            var sc = new StrongComponents(graph);

            scGraph = sc.CreateGraph();

            literalValue = new bool[n * 2];

            for (int i = 0; i < n; i++)
            {
                if (graph.vcomp[i * 2] == graph.vcomp[i * 2 + 1])
                {
                    return(null);
                }
            }

            literalMap = new List <int> [scGraph.Length];
            for (int i = 0; i < scGraph.Length; i++)
            {
                literalMap[i] = new List <int>();
            }

            for (int i = 0; i < n * 2; i++)
            {
                literalMap[graph.vcomp[i]].Add(i);
            }

            visited  = new bool[scGraph.Length];
            conflict = new bool[scGraph.Length];
            for (int i = 0; i < scGraph.Length; i++)
            {
                Dfs(i);
            }

            var var = new bool[n];

            for (int i = 0; i < n; i++)
            {
                if (!literalValue[i * 2] && !literalValue[i * 2 + 1])
                {
                    return(null);
                }
                var[i] = literalValue[i * 2];
            }
            return(var);
        }
Example #4
0
        public void GraphSearchTest()
        {
            // this is the example graph at http://www.codeproject.com/cs/miscctrl/quickgraph.asp
            Graph <BasicNode> g = new Graph <BasicNode>();
            BasicNode         u = new BasicNode("u");
            BasicNode         v = new BasicNode("v");
            BasicNode         w = new BasicNode("w");
            BasicNode         x = new BasicNode("x");
            BasicNode         y = new BasicNode("y");
            BasicNode         z = new BasicNode("z");

            g.Nodes.Add(u);
            g.Nodes.Add(v);
            g.Nodes.Add(w);
            g.Nodes.Add(x);
            g.Nodes.Add(y);
            g.Nodes.Add(z);
            g.AddEdge(u, v);
            g.AddEdge(u, x);
            g.AddEdge(v, y);
            g.AddEdge(y, x);
            g.AddEdge(x, v);
            g.AddEdge(w, u);
            g.AddEdge(w, y);
            g.AddEdge(w, z);

            DepthFirstSearch <BasicNode> dfs = new DepthFirstSearch <BasicNode>(g);

            dfs.DiscoverNode   += delegate(BasicNode node) { Console.WriteLine("discover " + node); };
            dfs.FinishNode     += delegate(BasicNode node) { Console.WriteLine("finish " + node); };
            dfs.DiscoverEdge   += delegate(Edge <BasicNode> edge) { Console.WriteLine("discover " + edge); };
            dfs.TreeEdge       += delegate(Edge <BasicNode> edge) { Console.WriteLine("tree edge " + edge); };
            dfs.FinishTreeEdge += delegate(Edge <BasicNode> edge) { Console.WriteLine("finish tree edge " + edge); };
            dfs.CrossEdge      += delegate(Edge <BasicNode> edge) { Console.WriteLine("cross edge " + edge); };
            dfs.BackEdge       += delegate(Edge <BasicNode> edge) { Console.WriteLine("back edge " + edge); };
            Console.WriteLine("dfs from u:");
            dfs.SearchFrom(u);
            Console.WriteLine();
            Console.WriteLine("dfs from w:");
            dfs.SearchFrom(w);
            Console.WriteLine();
            dfs.Clear();
            Console.WriteLine("cleared dfs from w:");
            dfs.SearchFrom(w);
            Console.WriteLine();

            Console.WriteLine("bfs:");
            BreadthFirstSearch <BasicNode>      bfs      = new BreadthFirstSearch <BasicNode>(g);
            IndexedProperty <BasicNode, double> distance = g.CreateNodeData <double>(Double.PositiveInfinity);

            bfs.DiscoverNode += delegate(BasicNode node) { Console.WriteLine("discover " + node); };
            bfs.FinishNode   += delegate(BasicNode node) { Console.WriteLine("finish " + node); };
            bfs.TreeEdge     += delegate(Edge <BasicNode> edge)
            {
                Console.WriteLine("tree edge " + edge);
                distance[edge.Target] = distance[edge.Source] + 1;
            };
            // compute distances from w
            distance[w] = 0;
            bfs.SearchFrom(w);
            Console.WriteLine("distances from w:");
            foreach (BasicNode node in g.Nodes)
            {
                Console.WriteLine("[" + node + "] " + distance[node]);
            }
            Assert.Equal(2.0, distance[x]);
            Console.WriteLine();

            Console.WriteLine("distances from w:");
            DistanceSearch <BasicNode> dists = new DistanceSearch <BasicNode>(g);

            dists.SetDistance += delegate(BasicNode node, int dist) { Console.WriteLine("[" + node + "] " + dist); };
            dists.SearchFrom(w);
            Console.WriteLine();

            BasicNode start = z, end;

            (new PseudoPeripheralSearch <BasicNode>(g)).SearchFrom(ref start, out end);
            Console.WriteLine("pseudo-peripheral nodes: " + start + "," + end);

            StrongComponents <BasicNode> scc = new StrongComponents <BasicNode>(g);
            int count = 0;

            scc.AddNode        += delegate(BasicNode node) { Console.Write(" " + node); };
            scc.BeginComponent += delegate()
            {
                Console.Write("[");
                count++;
            };
            scc.EndComponent += delegate() { Console.Write("]"); };
            Console.Write("strong components reachable from w (topological order): ");
            scc.SearchFrom(w);
            Assert.Equal(4, count);
            Console.WriteLine();

            count = 0;
            StrongComponents2 <BasicNode> scc2 = new StrongComponents2 <BasicNode>(g);

            scc2.AddNode        += delegate(BasicNode node) { Console.Write(" " + node); };
            scc2.BeginComponent += delegate()
            {
                Console.Write("[");
                count++;
            };
            scc2.EndComponent += delegate() { Console.Write("]"); };
            Console.Write("strong components reachable from w (rev topological order): ");
            scc2.SearchFrom(w);
            Assert.Equal(4, count);
            Console.WriteLine();

#if false
            Console.WriteLine("CyclicDependencySort:");
            List <BasicNode> schedule = CyclicDependencySort <BasicNode> .Schedule(g,
                                                                                   delegate(BasicNode node, ICollection <BasicNode> available) {
                if (node == x)
                {
                    return(available.Contains(u));
                }
                else
                {
                    return(false);
                }
            },
                                                                                   g.Nodes);

            foreach (BasicNode node in schedule)
            {
                Console.Write(node + " ");
            }
            Console.WriteLine();
            Assert.Equal <int>(6, schedule.Count);
            // order should be: w u x v y z (z can be re-ordered)
            Assert.Equal <BasicNode>(w, schedule[0]);
            Assert.Equal <BasicNode>(u, schedule[1]);
            //Assert.Equal<BasicNode>(z,schedule[5]);
#endif
        }
Example #5
0
        private EquationDecomposition(EquationSystem eqsys)
        {
            /** This algorithm decomposes a given equation system into smaller equation blocks
             *  which can be solved subsequently. The algorithm is sometimes referred to as
             *  Tarjan's sorting or Dulmage-Mendelson decomposition.
             *
             *  The algorithm consists of several steps. The description below will use the
             *  following notions:
             *    Var: The set of variables of the whole equation system
             *    Eqn: The set of equations of the whole equation system
             *    Var u Eqn: The set unification of Var and Eqn
             *
             *  Step (1): Maximum matching
             *    Define an undirected graph G = (V, E) with V = Var u Eqn.
             *    Whenever an equation eqn \in Eqn references a variable var \in Var
             *    add the edge (eqn, var) to E.
             *    Compute a maximum matching M between variables and equations.
             *    M will now contain a set of equation/variable pairs.
             *
             * Step (2): Finding strongly connected components
             *    Define a directed graph Gd = (V, Ed) with V = Var u Eqn.
             *    Whenever an equation eqn \in Eqn references a variable var \in Var
             *    add the edge (eqn, var) to Ed.
             *    For each equation/variable pair (eqn, var) in M add furthermore
             *    the edge (var, eqn) to Ed.
             *    Note: Matched equation/variable pairs will result in bi-directional edges in Ed.
             *    Compute the strongly connected components SCC of Gd.
             *    SCC is a set of subsets of V such that each subset represents one component.
             *
             * Step (3): Building the tree of equation blocks
             *    Defined a directed graph Dt = (SCC, Et).
             *    For each equation eqn \in Eqn which is assigned to component c1 and
             *    references a variable var \in Var which is assigned to component c2
             *    add an edge (c1, c2) to Et of c1 and c2 are different.
             *
             *    The resulting graph will have a tree/forest sutrcture. Each node
             *    represents an equation block. An edge b1 -> b2 represents a dependency in the
             *    that b2 must be solved prior to b1. A schedule can be found by topological
             *    sorting the tree.
             * */

            if (eqsys == null ||
                eqsys.Equations == null ||
                eqsys.Variables == null)
            {
                throw new ArgumentException("null reference in equation system argument");
            }

            if (eqsys.Equations.Count != eqsys.Variables.Count)
            {
                throw new ArgumentException("equation system is not well-constrained!");
            }

            /** Assign each equation and each variable an index which will be a unique node
             * ID within the graphs. Indices are assigned as follows:
             *   - Equations get indices from 0...count(equations)-1
             *   - Variables get indices from count(equations)...count(equations)+count(variables)
             *   Note: Assuming a well-constrained equation system, count(equations) = count(variables)
             **/
            int curidx = 0;

            foreach (Expression eq in eqsys.Equations)
            {
                eq.Cookie = curidx++;
            }
            Dictionary <object, int> idx = new Dictionary <object, int>();

            foreach (Variable v in eqsys.Variables)
            {
                idx[v] = curidx++;
            }

            // Steps 1 and 2: Construct G and Gd
            Graph   g  = new Graph(curidx);
            Digraph dg = new Digraph(curidx);

            for (int i = 0; i < eqsys.Equations.Count; i++)
            {
                Expression         eq  = eqsys.Equations[i];
                LiteralReference[] lrs = eq.ExtractLiteralReferences();
                foreach (LiteralReference lr in lrs)
                {
                    int j;
                    if (idx.TryGetValue(lr.ReferencedObject, out j))
                    {
                        g.AddEdge(i, j);
                        dg.AddEdge(i, j);
                    }
                }
            }
            // Step 1: Maximum matching
            GraphAlgorithms.Matching m = g.GetMaximumMatching();
            bool success = m.IsMaximumCardinality;

            for (int i = 0; i < eqsys.Equations.Count; i++)
            {
                int k = m[i];
                if (k >= 0)
                {
                    dg.AddEdge(k, i);
                }
            }
            // Step 2: Strongly connected components
            StrongComponents sc = dg.GetStrongComponents();
            int numc            = sc.NumComponents;

            EquationBlock[] blocks = new EquationBlock[numc];
            for (int i = 0; i < numc; i++)
            {
                blocks[i] = new EquationBlock();
            }

            // Step 3: Construct the tree
            Digraph dg2 = new Digraph(numc);

            for (int i = 0; i < eqsys.Equations.Count; i++)
            {
                int c = sc[i];
                blocks[c].EqSys.Equations.Add(eqsys.Equations[i]);
                int      vi = m[i];
                Variable v  = eqsys.Variables[vi - eqsys.Equations.Count];
                blocks[c].EqSys.Variables.Add(v);
                List <int> outset = dg.GetOutSet(i);
                foreach (int ovi in outset)
                {
                    int oc = sc[ovi];
                    if (c != oc)
                    {
                        dg2.AddEdge(c, oc);
                    }
                }
            }
            List <int> rootSet = new List <int>();
            List <int> sinkSet = new List <int>();

            for (int c = 0; c < numc; c++)
            {
                if (dg2.GetOutDegree(c) == 0)
                {
                    rootSet.Add(c);
                }
                if (dg2.GetInDegree(c) == 0)
                {
                    sinkSet.Add(c);
                }
                List <int> outset = dg2.GetOutSet(c);
                foreach (int oc in outset)
                {
                    blocks[c].Predecessors.Add(blocks[oc]);
                }
                List <int> inset = dg2.GetInSet(c);
                foreach (int ic in inset)
                {
                    blocks[c].Successors.Add(blocks[ic]);
                }
            }
            RootSet = (from int c in rootSet
                       select blocks[c]).ToArray();
            SinkSet = (from int c in sinkSet
                       select blocks[c]).ToArray();
            AllBlocks = blocks;
        }