示例#1
0
        public static void Bar()
        {
            // Stanford graphs conversion

            var inPath  = Program.Input("In path?", string.Copy);
            var outPath = Program.Input("Out path?", string.Copy);
            var graph   = new MultiDirectedGraph <int, int>();

            var lines = File.ReadAllLines(inPath);

            foreach (var line in lines)
            {
                var tokens = line.Split(new char[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);

                if (tokens[0] != "#")
                {
                    int source = int.Parse(tokens[0]);
                    int target = int.Parse(tokens[1]);

                    if (!graph.HasNode(source))
                    {
                        graph.AddNode(source);
                    }

                    if (!graph.HasNode(target))
                    {
                        graph.AddNode(target);
                    }

                    if (!graph.HasEdge(source, target) && !graph.HasEdge(target, source))
                    {
                        graph.AddEdge(source, target);
                    }
                }
            }

            GraphConverter.SaveToGraphML(graph, outPath);
        }
示例#2
0
        public static void Bar()
        {
            // Stanford graphs conversion

            var inPath = Program.Input("In path?", string.Copy);
            var outPath = Program.Input("Out path?", string.Copy);
            var graph = new MultiDirectedGraph<int, int>();

            var lines = File.ReadAllLines(inPath);
            foreach (var line in lines)
            {
                var tokens = line.Split(new char[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);

                if (tokens[0] != "#")
                {
                    int source = int.Parse(tokens[0]);
                    int target = int.Parse(tokens[1]);

                    if (!graph.HasNode(source))
                    {
                        graph.AddNode(source);
                    }

                    if (!graph.HasNode(target))
                    {
                        graph.AddNode(target);
                    }

                    if (!graph.HasEdge(source, target) && !graph.HasEdge(target, source))
                    {
                        graph.AddEdge(source, target);
                    }
                }
            }

            GraphConverter.SaveToGraphML(graph, outPath);
        }
示例#3
0
        /// <summary>
        /// Computes a reduced graph under some bisimulation equivalence relation.
        /// The input graph must be partitioned by the partitioner modulo said equivalence relation.
        /// </summary>
        /// <typeparam name="TNode">Node type.</typeparam>
        /// <typeparam name="TLabel">Label type.</typeparam>
        /// <param name="graph">Input graph.</param>
        /// <param name="labels">Labels of graph.</param>
        /// <param name="partitioner">Function which partitions the graph modulo some bisimulation equivalence relation.</param>
        /// <returns>A reduced graph where each partition block is a node and edges are reconstructued such that bisimulation equivalence is maintained.</returns>
        public static MultiDirectedGraph <int, TLabel> ReducedGraph <TNode, TLabel>(MultiDirectedGraph <TNode, TLabel> graph, Func <IDictionary <TNode, int> > partitioner)
        {
            var reduced   = new MultiDirectedGraph <int, TLabel>();
            var partition = partitioner();
            var inverted  = Utils.Invert(partition);

            // Add a node for each partition block
            foreach (var kvp in inverted)
            {
                var block = kvp.Key;
                var nodes = kvp.Value.ToArray();
                // var someNode = Utils.Shuffled(nodes).First();
                var someNode = nodes.First();

                reduced.AddNode(block, graph.NodeLabel(someNode));
            }

            // Add the edge going from each partition block to another
            foreach (var kvp in inverted)
            {
                var block = kvp.Key;
                var nodes = kvp.Value.ToArray();
                // var someSource = Utils.Shuffled(nodes).First();
                var someSource = nodes.First();

                foreach (var eo in graph.Out(someSource))
                {
                    var someTarget = graph.Target(eo);
                    var label      = graph.EdgeLabel(eo);

                    if (!reduced.HasEdge(block, partition[someTarget], label))
                    {
                        reduced.AddEdge(block, partition[someTarget], label);
                    }
                }
            }

            return(reduced);
        }
示例#4
0
        /// <summary>
        /// KerninghanLin algorithm which refines a partition.
        /// Equalizes block sizes and swaps nodes between partition blocks to minimize the edge cut.
        /// </summary>
        /// <typeparam name="TNode">Type of node.</typeparam>
        /// <typeparam name="TLabel">Type of label.</typeparam>
        /// <param name="graph">The graph of the partition.</param>
        /// <param name="partition">The partition to refine.</param>
        /// <param name="K">Maximum number of iterations.</param>
        public static void KernighanLin <TNode, TLabel>(MultiDirectedGraph <TNode, TLabel> graph, Dictionary <TNode, int> partition, int K)
        {
            // Compute ED and ID of each node
            var ED = new Dictionary <TNode, int>();
            var ID = new Dictionary <TNode, int>();
            Func <TNode, int> D = node => ED[node] - ID[node];

            foreach (var node in graph.Nodes)
            {
                ED.Add(node, 0);
                ID.Add(node, 0);
            }

            foreach (var edge in graph.Edges)
            {
                var s = graph.Source(edge);
                var t = graph.Target(edge);

                if (partition[s] == partition[t])
                {
                    ID[s] += 1;
                    ID[t] += 1;
                }
                else
                {
                    ED[s] += 1;
                    ED[t] += 1;
                }
            }

            // Stick nodes into sets of their partition block
            var inverted = Utils.Invert(partition);
            var AI       = inverted.Keys.First();
            var BI       = inverted.Keys.Last();

            // Swaps a node from its original partition block to the other
            Action <TNode> swap = node =>
            {
                foreach (var edge in graph.Out(node).Concat(graph.In(node)))
                {
                    var neighbor = graph.Target(edge);

                    if (node.Equals(neighbor))
                    {
                        continue;
                    }

                    if (partition[node] == partition[neighbor])
                    {
                        // Will be in other block now
                        ID[neighbor] -= 1;
                        ID[node]     -= 1;
                        ED[neighbor] += 1;
                        ED[node]     += 1;
                    }
                    else
                    {
                        // Will be in same block now
                        ID[neighbor] += 1;
                        ID[node]     += 1;
                        ED[neighbor] -= 1;
                        ED[node]     -= 1;
                    }
                }

                if (partition[node] == AI)
                {
                    partition[node] = BI;
                    inverted[AI].Remove(node);
                    inverted[BI].Add(node);
                }
                else
                {
                    partition[node] = AI;
                    inverted[AI].Add(node);
                    inverted[BI].Remove(node);
                }
            };

            // Equalize block sizes
            while (Math.Abs(inverted[AI].Count - inverted[BI].Count) > 1)
            {
                if (inverted[AI].Count > inverted[BI].Count)
                {
                    // Move from A to B
                    var a = inverted[AI].MaxBy(node => D(node));
                    swap(a);
                }
                else
                {
                    // Move from B to A
                    var b = inverted[BI].MaxBy(node => D(node));
                    swap(b);
                }
            }

            // Keep performing positive swaps
            int n = Math.Min(inverted[AI].Count, inverted[BI].Count);

            for (int i = 0; i < K; i++)
            {
                bool hasGained = false;
                var  AA        = new HashSet <TNode>(inverted[AI]);
                var  BB        = new HashSet <TNode>(inverted[BI]);

                for (int j = 0; j < n; j++)
                {
                    var a    = AA.MaxBy(node => D(node));
                    var b    = BB.MaxBy(node => D(node));
                    int gain = D(a) + D(b);

                    if (graph.HasEdge(a, b))
                    {
                        gain -= 2;
                    }

                    if (graph.HasEdge(b, a))
                    {
                        gain -= 2;
                    }

                    if (gain > 0)
                    {
                        hasGained = true;
                        swap(a);
                        swap(b);
                    }

                    AA.Remove(a);
                    BB.Remove(b);
                }

                if (!hasGained)
                {
                    break;
                }
            }
        }