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