/// <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)); }
/// <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(); * //*/ }
/// <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); }