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