/// <summary>
        /// Measures the weighted k-bisimulation partition equivalence between two graphs.
        /// </summary>
        /// <typeparam name="TNode"></typeparam>
        /// <typeparam name="TLabel"></typeparam>
        /// <param name="G1"></param>
        /// <param name="G2"></param>
        /// <param name="L1"></param>
        /// <param name="L2"></param>
        /// <param name="k">A tuple indicating how many nodes of G1 and G2 are in partition blocks that are shared between G1 and G2.</param>
        /// <returns></returns>
        public static Tuple <int, int> WeightedBisimulationEquivalence <TNode, TLabel>(MultiDirectedGraph <TNode, TLabel> G1, MultiDirectedGraph <TNode, TLabel> G2, int k)
        {
            // Create new empty graph and label provider
            var G = new MultiDirectedGraph <Tuple <int, TNode>, TLabel>();

            // Add nodes of G1
            foreach (var node in G1.Nodes.Select(node => Tuple.Create(1, node)))
            {
                G.AddNode(node, G1.NodeLabel(node.Item2));
            }

            // Add nodes of G2
            foreach (var node in G2.Nodes.Select(node => Tuple.Create(2, node)))
            {
                G.AddNode(node, G2.NodeLabel(node.Item2));
            }

            // Add edges of G1
            foreach (var edge in G1.Edges)
            {
                var s = Tuple.Create(1, G1.Source(edge));
                var t = Tuple.Create(1, G1.Target(edge));
                G.AddEdge(s, t, G1.EdgeLabel(edge));
            }

            // Add edges of G2
            foreach (var edge in G2.Edges)
            {
                var s = Tuple.Create(2, G2.Source(edge));
                var t = Tuple.Create(2, G2.Target(edge));
                G.AddEdge(s, t, G2.EdgeLabel(edge));
            }

            // Perform bisimulation reduction
            var partitioner = new GraphPartitioner <Tuple <int, TNode>, TLabel>(G);
            var partition   = partitioner.BoundedExactBisimulationReduction(k);

            // Partition blocks of G1 and G2
            HashSet <int> P1 = new HashSet <int>();
            HashSet <int> P2 = new HashSet <int>();

            foreach (var node in G.Nodes)
            {
                int block = partition[node];

                switch (node.Item1)
                {
                case 1:
                    if (!P1.Contains(block))
                    {
                        P1.Add(block);
                    }
                    break;

                case 2:
                    if (!P2.Contains(block))
                    {
                        P2.Add(block);
                    }
                    break;
                }
            }

            int s1 = 0;
            int s2 = 0;

            foreach (var node in G.Nodes)
            {
                if (P1.Contains(partition[node]) && P2.Contains(partition[node]))
                {
                    switch (node.Item1)
                    {
                    case 1:
                        s1 += 1;
                        break;

                    case 2:
                        s2 += 1;
                        break;
                    }
                }
            }

            return(Tuple.Create(s1, s2));
        }
Exemple #2
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="D"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        public static MultiDirectedGraph <int, int> GenerateNiceDAG(int D, int b)
        {
            // Create empty graph and label provider
            var graph = new MultiDirectedGraph <int, int>();

            graph.Name = "Synthetic_DAG_" + D + "_" + b;

            // Define parent function
            Func <int, int> parent = node =>
            {
                // Assume node > 0 (not the root node)
                return(graph.In(node).First());
            };

            // Define level function
            Func <int, int> level = Utils.Y <int, int>(fix => node =>
            {
                if (node == 0)
                {
                    // Root node
                    return(0);
                }
                else
                {
                    return(1 + fix(parent(node)));
                }
            });

            // Create initial tree
            int counter = 0;

            graph.AddNode(counter, 0);
            counter += 1;

            while (graph.Nodes.Select(node => level(node)).Max() < D)
            {
                int max    = graph.Nodes.Select(node => level(node)).Max();
                var lowest = graph.Nodes.Where(node => level(node) == max).ToArray();

                foreach (var node in lowest)
                {
                    int k = StaticRandom.Next(b + 1);

                    for (int i = 0; i < k; i++)
                    {
                        graph.AddNode(counter, 0);
                        graph.AddEdge(node, counter, i);
                        // graph.AddEdge(node, counter, 0);
                        counter += 1;
                    }
                }
            }

            // Transform tree to DAG with nicer partition block distribution
            var copy              = graph.Clone();
            var partitioner       = new GraphPartitioner <int, int>(graph);
            var partition         = partitioner.BoundedExactBisimulationReduction(D);
            var partitionInverted = Utils.Invert(partition);
            var blocks            = partition.Values.Distinct();
            var blockSizes        = Utils.Distribution(partition.Values);
            int blockMax          = blockSizes.Values.Max();

            foreach (var block in blocks)
            {
                int size  = blockSizes[block];
                var nodes = new List <int>(partitionInverted[block]);

                for (int i = size; i < blockMax; i++)
                {
                    // Replicate a random node in this partition block
                    int k = StaticRandom.Next(size);
                    var v = nodes[k];

                    // Replicate the node
                    graph.AddNode(counter, graph.NodeLabel(v));

                    // Replicate its incoming edges
                    foreach (var ei in copy.In(v))
                    {
                        var u = graph.Source(ei);
                        graph.AddEdge(u, counter, graph.EdgeLabel(ei));
                    }

                    // Replicate its outgoing edges
                    foreach (var eo in copy.Out(v))
                    {
                        var w = graph.Target(eo);
                        graph.AddEdge(counter, w, graph.EdgeLabel(eo));
                    }

                    counter += 1;
                }
            }

            return(graph);
        }