/// <summary>
        /// Compute the partition block size distribution.
        /// </summary>
        /// <param name="graph"></param>
        /// <param name="labels"></param>
        /// <param name="k"></param>
        /// <returns></returns>
        public static Experiment PartitionBlockDistribution <TNode, TLabel>(MultiDirectedGraph <TNode, TLabel> graph)
        {
            var partitioner = new GraphPartitioner <TNode, TLabel>(graph);
            var partitions  = partitioner.MultilevelExactBisimulationReduction();
            int k_max       = partitions.Count - 1;

            var sizes = Utils.Distribution(partitions[k_max].Values).Values.ToArray();

            Array.Sort(sizes);
            Array.Reverse(sizes);

            var experiment = new Experiment(2)
            {
                Labels = new string[] { "Partition block", "Number of nodes" },
                Meta   = new string[] { "Blocks", graph.Name, },
                F      = i =>
                {
                    int index = Convert.ToInt32(i);
                    int size  = sizes[index];

                    return(new double[] { index + 1, size });
                },
            };

            experiment.Run(0, sizes.Length - 1, 1, 1);
            return(experiment);
        }
        /// <summary>
        /// Creates three experiments for measuring the makespan, visit times and data shipment of the distributed exact bisimulation algorithm.
        /// </summary>
        /// <typeparam name="TNode"></typeparam>
        /// <typeparam name="TLabel"></typeparam>
        /// <param name="graph"></param>
        /// <param name="M"></param>
        /// <returns></returns>
        public static Experiment[] MeasureDistributedPerformanceExact <TNode, TLabel>(MultiDirectedGraph <TNode, TLabel> graph, int M, Func <MultiDirectedGraph <TNode, TLabel>, int, Dictionary <TNode, int> > splitter, string splitterName)
        {
            var sequentialPartitioner  = new GraphPartitioner <TNode, TLabel>(graph);
            var distributedPartitioner = new DistributedGraphPartitioner <TNode, TLabel> [M];

            for (int i = 0; i < M; i++)
            {
                distributedPartitioner[i] = new DistributedGraphPartitioner <TNode, TLabel>(i + 1, graph);
            }

            var experiment = new Experiment(5)
            {
                Labels = new string[] { "Number of machines", "Sequential (ms)", "Distributed (ms)", "Visit times", "Data shipment" },
                Meta   = new string[] { splitterName, "Performance", "Exact", graph.Name },
                F      = i =>
                {
                    int m = Convert.ToInt32(i);
                    sequentialPartitioner.ExactBisimulationReduction();
                    var sequentialTime = sequentialPartitioner.ElapsedMilliseconds;
                    distributedPartitioner[m].ExactBisimulationReduction(splitter);
                    var distributedTime = distributedPartitioner[m].ElapsedMilliseconds;
                    var visitTimes      = distributedPartitioner[m].VisitTimes;
                    var dataShipment    = distributedPartitioner[m].DataShipment;

                    return(new double[] { m + 1, sequentialTime, distributedTime, visitTimes, dataShipment });
                },
            };

            experiment.Run(0, M - 1, 1, 10);

            var splits = new int[][]
            {
                new int[] { 0, 1, 2 },
                new int[] { 0, 3 },
                new int[] { 0, 4 }
            };

            var experiments = experiment.Split(splits);

            experiments[0].Meta = new string[] { splitterName, "Makespan", "Exact", graph.Name };
            experiments[1].Meta = new string[] { splitterName, "VisitTimes", "Exact", graph.Name };
            experiments[2].Meta = new string[] { splitterName, "DataShipment", "Exact", graph.Name };

            return(experiments);
        }
        /// <summary>
        /// Count the number of partition blocks in a graph.
        /// </summary>
        /// <typeparam name="TNode"></typeparam>
        /// <typeparam name="TLabel"></typeparam>
        /// <param name="graph"></param>
        /// <param name="labels"></param>
        /// <returns></returns>
        public static Experiment BisimulationPartitionSize <TNode, TLabel>(MultiDirectedGraph <TNode, TLabel> graph)
        {
            var partitioner = new GraphPartitioner <TNode, TLabel>(graph);
            var partitions  = partitioner.MultilevelExactBisimulationReduction();

            Experiment experiment = new Experiment(2)
            {
                Labels = new string[] { "k", "Number of blocks" },
                Meta   = new string[] { "Partition-size", graph.Name },
                F      = i =>
                {
                    var k = Convert.ToInt32(i);
                    var partitionCount = partitions[k].Values.Distinct().Count();

                    return(new double[] { k, partitionCount });
                },
            };

            experiment.Run(0, partitions.Count - 1, 1, 1);
            return(experiment);
            // experiment.Save(@"..\..\..\..\Analytics\BisimBlocks-" + graph.Name.ToLower() + ".tsv");
        }
        /// <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));
        }
Пример #5
0
        /// <summary>
        /// Entry point.
        /// </summary>
        /// <param name="args"></param>
        public static void Main(string[] args)
        {
            //*
            Dummy.Fix();
            return;

            //*/

            /*
             * AllPerformanceExperiments();
             * return;
             * //*/

            //*
            AllAnalyticsExperiments("Petrinet_no_labels");
            return;

            //*/

            // Ask for graph file
            string path    = Input("Please enter the path to the graph file", string.Copy);
            string outPath = Path.GetDirectoryName(path) + @"\..\Results";

            // Load graph and labels
            var graph = GraphLoader.LoadGraphML(path, int.Parse, int.Parse);

            /*
             * var partitioner = new GraphPartitioner<int, int>(graph);
             * var distributedPartitioner = new DistributedGraphPartitioner<int, int>(1, graph);
             * //*/

            /*
             * var estim = GraphGenerator.ReducedGraph(graph, distributedPartitioner.ExactBisimulationReduction);
             * var exact = GraphGenerator.ReducedGraph(graph, partitioner.EstimateBisimulationReduction);
             * //*/

            //*
            // GraphConverter.SaveToGraphML(estim, Path.GetDirectoryName(path) + @"\" + graph.Name + "_estim.xml");
            // GraphConverter.SaveToGraphML(exact, Path.GetDirectoryName(path) + @"\" + graph.Name + "_exact.xml");
            // GraphConverter.SaveToGraphML(coarse, Path.GetDirectoryName(path) + @"\" + graph.Name + "_coarse.xml");
            //*/

            // Samplers
            var samplers = new Func <double, MultiDirectedGraph <int, int> >[]
            {
                //* Normal samplers
                p => graph.Induce(graph.RN((int)(p * graph.NumNodes))),
                p => graph.Induce(graph.RE((int)(p * graph.NumEdges))),
                // p => graph.Induce(graph.LowDegreeFirst((int)(p * graph.NumNodes))),
                // p => graph.Induce(graph.GreedyLabels((int)(p * graph.NumNodes))),
                p => graph.Induce(graph.DistinctLabelsSB((int)(p * graph.NumNodes))),
                p => graph.Induce(graph.QueuedSampler <int, int, FifoQueue <int> >((int)(p * graph.NumNodes))),
                // p => graph.Induce(graph.QueuedSampler<int, int, LifoQueue<int>>((int)(p * graph.NumNodes))),
                // p => graph.Induce(graph.QueuedSampler<int, int, AiroQueue<int>>((int)(p * graph.NumNodes))),
                p => graph.Induce(graph.RandomWalkTeleport((int)(p * graph.NumNodes), 0.1)),
                //*/

                /* Approximation samplers
                 * p => estim.Induce(estim.RN((int)(p * graph.NumNodes))),
                 * p => estim.Induce(estim.RE((int)(p * graph.NumEdges))),
                 * // p => estim.Induce(estim.LowDegreeFirst((int)(p * graph.NumNodes))),
                 * // p => estim.Induce(estim.GreedyLabels((int)(p * graph.NumNodes))),
                 * p => estim.Induce(estim.DistinctLabelsSB((int)(p * graph.NumNodes))),
                 * p => estim.Induce(estim.QueuedSampler<int, int, FifoQueue<int>>((int)(p * graph.NumNodes))),
                 * // p => estim.Induce(estim.QueuedSampler<int, int, LifoQueue<int>>((int)(p * graph.NumNodes))),
                 * // p => estim.Induce(estim.QueuedSampler<int, int, AiroQueue<int>>((int)(p * graph.NumNodes))),
                 * p => estim.Induce(estim.RandomWalkTeleport((int)(p * graph.NumNodes), 0.1)),
                 * //*/
            };

            // Sampler names
            var samplerNames = new string[]
            {
                "RN",
                "RE",
                // "LDF",
                // "GL",
                "DLSB",
                "BFS",
                // "DFS",
                // "RFS",
                "RWT",
            };
            //*/

            //* Run many bisimulation experiments in batch
            var partitioner = new GraphPartitioner <int, int>(graph);
            var k_max       = partitioner.MultilevelExactBisimulationReduction().Count - 1;

            for (int k = 0; k <= k_max; k++)
            {
                for (int i = 0; i < samplers.Length; i++)
                {
                    var sampler     = samplers[i];
                    var samplerName = samplerNames[i];

                    // var experiment = Experiments.StandardBisimulationMetrics(graph, samplerName, sampler, k);
                    // Experiment.SaveSVG(outPath + @"\" + string.Join("_", experiment.Meta) + ".svg", experiment.Plot(0.0, 1.0));
                    // experiment.SaveTSV(outPath + @"\" + string.Join("_", experiment.Meta) + ".tsv");

                    var experiment = Experiments.WeightedBisimulationMetrics(graph, samplerName, sampler, k);
                    Experiment.SaveSVG(outPath + @"\" + string.Join("_", experiment.Meta) + ".svg", experiment.Plot(0.0, 1.0));
                    experiment.SaveTSV(outPath + @"\" + string.Join("_", experiment.Meta) + ".tsv");

                    Console.WriteLine("[" + DateTime.Now.ToString("HH:mm:ss") + "] k=" + k + " sampler=" + samplerName);
                }
                ;
            }
            //*/

            /*
             * // var experiment = Analytics.ReachabilityProbabilityMassFunction(graph);
             * // var experiment = Experiments.BisimulationPartitionBlockCounts(graph, labels);
             * // var experiment = Experiments.FindKMax(graph, labels);
             * // var experiment = Experiments.TreeGeneratorPartitionSize(1, 20);
             * PlotForm plotForm = new PlotForm();
             * plotForm.Display(experiment.Plot(double.NaN, double.NaN));
             * plotForm.ShowDialog();
             * //*/

            /* Get k
             * int k = Input("Please enter a value for k in k-bisimulation", int.Parse);
             * //*/

            /*
             * var experiment = Experiments.DistanceProbabilityMassFunction(graph);
             * Experiment.SaveSVG(outPath + @"\" + string.Join("_", experiment.Meta) + ".svg", experiment.Plot(0, double.NaN));
             * experiment.SaveTSV(outPath + @"\" + string.Join("_", experiment.Meta) + ".tsv");
             * //*/

            /* Run bisimulation experiment
             * var experiment = Experiments.StandardBisimulationMetrics(graph, labels, () => GraphSampler.Funny(graph, labels));
             * Experiment.SaveSVG(outPath + @"\" + string.Join("_", experiment.Meta) + ".svg", experiment.Plot(0.0, 1.0));
             * experiment.SaveTSV(outPath + @"\" + string.Join("_", experiment.Meta) + ".tsv");
             * //*/

            /*
             * var experiment = Experiments.BisimulationPartitionSize(graph, labels);
             * // var experiment = Experiments.PartitionBlockDistribution(graph, labels);
             * Experiment.SaveSVG(outPath + @"\" + string.Join("_", experiment.Meta) + ".svg", experiment.Plot(double.NaN, double.NaN));
             * experiment.SaveTSV(outPath + @"\" + string.Join("_", experiment.Meta) + ".tsv");
             * //*/

            /*
             * PlotForm plotForm = new PlotForm();
             * plotForm.Display(experiment.Plot(0, double.NaN));
             * plotForm.ShowDialog();
             * //*/
        }
Пример #6
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);
        }