private void clear() { var comparer1 = EqualityComparer <TLabel> .Default; var comparer2 = new Utils.HashSetEqualityComparer <Tuple <TLabel, int> >(); var comparer = new Utils.PairEqualityComparer <TLabel, HashSet <Tuple <TLabel, int> > >(comparer1, comparer2); partition = new Dictionary <TNode, int>(); partitionMap = new Dictionary <Tuple <TLabel, HashSet <Tuple <TLabel, int> > >, int>(comparer); int counter = 0; foreach (var node in graph.Nodes) { if (owner[node] == this) { var signature = Tuple.Create(graph.NodeLabel(node), new HashSet <Tuple <TLabel, int> >()); if (!partitionMap.ContainsKey(signature)) { partitionMap.Add(signature, counter++); } partition.Add(node, partitionMap[signature]); } } }
/// <summary> /// Partition a directed graph's nodes based on (bounded) k-bisimulation equivalence. /// </summary> /// <param name="k"></param> /// <returns></returns> public IDictionary <TNode, int> BoundedExactBisimulationReduction(int k) { var partitions = new Dictionary <TNode, int> [k + 1]; stopwatch.Reset(); stopwatch.Start(); { // Partition block counter (for uniqueness) int counter = 0; var comparer = new Utils.HashSetEqualityComparer <Tuple <TLabel, int> >(); // Base (k = 0) // Create a partition based solely on the labels of the nodes partitions[0] = new Dictionary <TNode, int>(); var labelIds = new Dictionary <TLabel, int>(); foreach (var label in graph.NodeLabels) { labelIds.Add(label, counter++); } // Assign block to each node foreach (var node in graph.Nodes) { partitions[0].Add(node, labelIds[graph.NodeLabel(node)]); } // Store the signatures and the block identifier associated with them var signatures = new Dictionary <TLabel, Dictionary <HashSet <Tuple <TLabel, int> >, int> >(); foreach (var label in graph.NodeLabels) { signatures.Add(label, null); } // Step (k > 0) for (int i = 1; i <= k; i++) { // Initialize partition partitions[i] = new Dictionary <TNode, int>(); // Initialize each entry in the signature storage foreach (var label in graph.NodeLabels) { // Use custom hash set for faster equivalence determination signatures[label] = new Dictionary <HashSet <Tuple <TLabel, int> >, int>(comparer); } foreach (var u in graph.Nodes) { // Label of node var label = graph.NodeLabel(u); // Compute signature (without label) of node u // This is the set of tuples (label(u, v), partition_i-1(v)) for every edge (u, v) var S = new HashSet <Tuple <TLabel, int> >(); foreach (var eo in graph.Out(u)) { var v = graph.Target(eo); var t = Tuple.Create(graph.EdgeLabel(eo), partitions[i - 1][v]); if (!S.Contains(t)) { S.Add(t); } } // Check if signature exists and create a new block if it does not if (!signatures[label].ContainsKey(S)) { signatures[label].Add(S, counter++); } // Set block of node u partitions[i].Add(u, signatures[label][S]); } } } stopwatch.Stop(); return(partitions[k]); }
protected override void OnReceive(AbstractMessage message) { TypeSwitch.On(message) .Case((CoordinatorMessage coordinatorMessage) => { k_max = 0; partition = new Dictionary <TNode, int>(); oldNumBlocks = 0; blocks = new HashSet <int>(); workers = coordinatorMessage.Workers; state = new Dictionary <AbstractMachine, WorkerState>(); var comparer1 = EqualityComparer <TLabel> .Default; var comparer2 = new Utils.HashSetEqualityComparer <Tuple <TLabel, int> >(); var comparer = new Utils.PairEqualityComparer <TLabel, HashSet <Tuple <TLabel, int> > >(comparer1, comparer2); signatures = new Dictionary <Tuple <TLabel, HashSet <Tuple <TLabel, int> > >, int>(comparer); counter = 0; foreach (var worker in workers) { state.Add(worker, WorkerState.Refining); worker.SendMe(new ClearMessage(this)); } }) .Case((ExactRefinedMessage <TLabel> refinedMessage) => { state[refinedMessage.Sender] = WorkerState.Waiting; var remap = new Dictionary <int, int>(); foreach (var kvp in refinedMessage.PartitionMap) { if (!signatures.ContainsKey(kvp.Key)) { signatures.Add(kvp.Key, counter++); } remap.Add(kvp.Value, signatures[kvp.Key]); } refinedMessage.Sender.SendMe(new RemapPartitionMessage(this, remap)); if (workers.All(worker => state[worker] == WorkerState.Waiting)) { signatures.Clear(); // All workers have refined, now perform a share step foreach (var worker in workers) { state[worker] = WorkerState.Sharing; worker.SendMe(new ShareMessage(this)); } } }) .Case((SharedMessage sharedMessage) => { state[sharedMessage.Sender] = WorkerState.Waiting; if (workers.All(worker => state[worker] == WorkerState.Waiting)) { // All workers have shared, now count the number of unqiue blocks oldNumBlocks = blocks.Count; blocks.Clear(); foreach (var worker in workers) { state[worker] = WorkerState.Counting; worker.SendMe(new CountMessage(this)); } } }) .Case((CountedMessage countedMessage) => { state[countedMessage.Sender] = WorkerState.Waiting; blocks.UnionWith(countedMessage.Blocks); if (workers.All(worker => state[worker] == WorkerState.Waiting)) { if (blocks.Count > oldNumBlocks) { // There was a change, continue refining k_max += 1; foreach (var worker in workers) { state[worker] = WorkerState.Refining; worker.SendMe(new RefineMessage(this)); } } else { // We're done, collect global partition k_max -= 1; foreach (var worker in workers) { state[worker] = WorkerState.Collecting; worker.SendMe(new SegmentRequestMessage(this)); } } } }) .Case((SegmentResponseMessage <TNode> segmentResponseMessage) => { state[segmentResponseMessage.Sender] = WorkerState.Waiting; foreach (var pair in segmentResponseMessage.Pairs) { partition.Add(pair.Key, pair.Value); } if (workers.All(worker => state[worker] == WorkerState.Waiting)) { onComplete(k_max, partition); } }); }