public void TestUnorderedPairEquals() { IPair a = new UnorderedPair(1, 2); Assert.IsTrue(a.Equals(a)); Assert.IsTrue(!a.Equals(null)); IPair b = new UnorderedPair(1, 2); Assert.IsTrue(a.Equals(b)); Assert.IsTrue(b.Equals(a)); Assert.IsTrue(a.GetHashCode() == b.GetHashCode()); IPair c = new UnorderedPair(2, 1); Assert.IsTrue(a.Equals(c)); Assert.IsTrue(c.Equals(a)); Assert.IsTrue(a.GetHashCode() == c.GetHashCode()); }
// done! internal static void UnweightedMinimizeOld <T, S>(DFSA <T, S> dfsa) { ICollection <DFSAState <T, S> > states = dfsa.States(); IDictionary <UnorderedPair <DFSAState <T, S>, DFSAState <T, S> >, IList <UnorderedPair <DFSAState <T, S>, DFSAState <T, S> > > > stateUPairToDependentUPairList = Generics.NewHashMap(states.Count * states.Count / 2 + 1); IDictionary <UnorderedPair <DFSAState <T, S>, DFSAState <T, S> >, bool> stateUPairToDistinguished = Generics.NewHashMap(states.Count * states.Count / 2 + 1); int[] c = new int[states.Count * states.Count / 2 + 1]; int streak = 0; int collisions = 0; int entries = 0; long time = Runtime.CurrentTimeMillis(); if (debug) { time = Runtime.CurrentTimeMillis(); log.Info("Starting on " + dfsa.dfsaID); log.Info(" -- " + states.Count + " states."); } // initialize grid int numDone = 0; foreach (DFSAState <T, S> state1 in states) { foreach (DFSAState <T, S> state2 in states) { UnorderedPair <DFSAState <T, S>, DFSAState <T, S> > up = new UnorderedPair <DFSAState <T, S>, DFSAState <T, S> >(state1, state2); if (state1.Equals(state2)) { continue; } if (stateUPairToDistinguished.Contains(up)) { continue; } int bucket = (up.GetHashCode() & unchecked ((int)(0x7FFFFFFF))) % (states.Count * states.Count / 2 + 1); c[bucket]++; entries++; if (c[bucket] > 1) { collisions++; streak = 0; } else { streak++; } if (state1.IsAccepting() != state2.IsAccepting()) { //log.info(Utils.pad((String)state1.stateID, 20)+" "+state2.stateID); stateUPairToDistinguished[up] = true; } else { stateUPairToDistinguished[up] = false; } } //stateUPairToDependentUPairList.put(up, new ArrayList()); numDone++; if (numDone % 20 == 0) { log.Info("\r" + numDone + " " + ((double)collisions / (double)entries)); } } if (debug) { log.Info("\nInitialized: " + (Runtime.CurrentTimeMillis() - time)); time = Runtime.CurrentTimeMillis(); } // visit each undistinguished pair foreach (UnorderedPair <DFSAState <T, S>, DFSAState <T, S> > up_1 in stateUPairToDistinguished.Keys) { DFSAState <T, S> state1_1 = up_1.first; DFSAState <T, S> state2 = up_1.second; if (stateUPairToDistinguished[up_1].Equals(true)) { continue; } // check if some input distinguishes this pair ICollection <T> inputs = Generics.NewHashSet(state1_1.ContinuingInputs()); Sharpen.Collections.AddAll(inputs, state2.ContinuingInputs()); bool distinguishable = false; ICollection <UnorderedPair <DFSAState <T, S>, DFSAState <T, S> > > pendingUPairs = Generics.NewHashSet(); IEnumerator <T> inputI = inputs.GetEnumerator(); while (inputI.MoveNext() && !distinguishable) { T input = inputI.Current; DFSATransition <T, S> transition1 = state1_1.Transition(input); DFSATransition <T, S> transition2 = state2.Transition(input); if ((transition1 == null) != (transition2 == null)) { distinguishable = true; } if (transition1 != null && transition2 != null) { DFSAState <T, S> target1 = transition1.GetTarget(); DFSAState <T, S> target2 = transition2.GetTarget(); UnorderedPair <DFSAState <T, S>, DFSAState <T, S> > targetUPair = new UnorderedPair <DFSAState <T, S>, DFSAState <T, S> >(target1, target2); if (!target1.Equals(target2)) { if (stateUPairToDistinguished[targetUPair].Equals(true)) { distinguishable = true; } else { pendingUPairs.Add(targetUPair); } } } } // if the pair is distinguishable, record that if (distinguishable) { IList <UnorderedPair <DFSAState <T, S>, DFSAState <T, S> > > markStack = new List <UnorderedPair <DFSAState <T, S>, DFSAState <T, S> > >(); markStack.Add(up_1); while (!markStack.IsEmpty()) { UnorderedPair <DFSAState <T, S>, DFSAState <T, S> > upToMark = markStack[markStack.Count - 1]; markStack.Remove(markStack.Count - 1); stateUPairToDistinguished[upToMark] = true; IList <UnorderedPair <DFSAState <T, S>, DFSAState <T, S> > > addList = stateUPairToDependentUPairList[upToMark]; if (addList != null) { Sharpen.Collections.AddAll(markStack, addList); stateUPairToDependentUPairList[upToMark].Clear(); } } } else { // otherwise add it to any pending pairs foreach (UnorderedPair <DFSAState <T, S>, DFSAState <T, S> > pendingUPair in pendingUPairs) { IList <UnorderedPair <DFSAState <T, S>, DFSAState <T, S> > > dependentList = stateUPairToDependentUPairList[pendingUPair]; if (dependentList == null) { dependentList = new List <UnorderedPair <DFSAState <T, S>, DFSAState <T, S> > >(); stateUPairToDependentUPairList[pendingUPair] = dependentList; } dependentList.Add(up_1); } } } if (debug) { log.Info("All pairs marked: " + (Runtime.CurrentTimeMillis() - time)); time = Runtime.CurrentTimeMillis(); } // decide what canonical state each state will map to... IDisjointSet <DFSAState <T, S> > stateClasses = new FastDisjointSet <DFSAState <T, S> >(states); foreach (UnorderedPair <DFSAState <T, S>, DFSAState <T, S> > up_2 in stateUPairToDistinguished.Keys) { if (stateUPairToDistinguished[up_2].Equals(false)) { DFSAState <T, S> state1_1 = up_2.first; DFSAState <T, S> state2 = up_2.second; stateClasses.Union(state1_1, state2); } } IDictionary <DFSAState <T, S>, DFSAState <T, S> > stateToRep = Generics.NewHashMap(); foreach (DFSAState <T, S> state in states) { DFSAState <T, S> rep = stateClasses.Find(state); stateToRep[state] = rep; } if (debug) { log.Info("Canonical states chosen: " + (Runtime.CurrentTimeMillis() - time)); time = Runtime.CurrentTimeMillis(); } // reduce the DFSA by replacing transition targets with their reps foreach (DFSAState <T, S> state_1 in states) { if (!state_1.Equals(stateToRep[state_1])) { continue; } foreach (DFSATransition <T, S> transition in state_1.Transitions()) { transition.target = stateClasses.Find(transition.target); } } dfsa.initialState = stateClasses.Find(dfsa.initialState); if (debug) { log.Info("Done: " + (Runtime.CurrentTimeMillis() - time)); } }