public IsomorphicInfo IsIsomorphic(FiniteStateMachine <TInput, TOutput> other) { BidirectionalDictionary <FSMState <TInput, TOutput>, FSMState <TInput, TOutput> > statesCorrespondence = new BidirectionalDictionary <FSMState <TInput, TOutput>, FSMState <TInput, TOutput> >(); BidirectionalDictionary <TInput, TInput> inputCorrespondence = new BidirectionalDictionary <TInput, TInput>(); BidirectionalDictionary <TOutput, TOutput> outputCorrespondence = new BidirectionalDictionary <TOutput, TOutput>(); // У изоморфных автоматов должно совпадать: // - число состояний // - величина входного алфавита // - величина выходного автомата bool resultFlag = this.stateSet.Count == other.stateSet.Count && this.inputSet.Count == other.inputSet.Count && this.outputSet.Count == other.outputSet.Count; IsomorphicInfo result = null; if (resultFlag) { EventableDictionary <FSMState <TInput, TOutput>, StateInfo> ThisStatistics = new EventableDictionary <FSMState <TInput, TOutput>, StateInfo>(stateSet.Count); EventableDictionary <FSMState <TInput, TOutput>, StateInfo> OtherStatistics = new EventableDictionary <FSMState <TInput, TOutput>, StateInfo>(other.stateSet.Count); CalcStats(stateSet, ThisStatistics); CalcStats(other.stateSet, OtherStatistics); foreach (var statState in ThisStatistics) { foreach (var statOtherState in OtherStatistics) { if (statState.Value.InputCount == statOtherState.Value.InputCount && statState.Value.LoopCount == statOtherState.Value.LoopCount && statState.Value.OutputCount == statOtherState.Value.OutputCount) { statState.Value.Potential.Add(statOtherState.Key); statOtherState.Value.Potential.Add(statState.Key); } } if (statState.Value.Potential.Count == 0) { // Если у какого-нибудь состояния нет потенциальных вариантов на замену, то наша затея - фигня. resultFlag = false; break; } } if (resultFlag) { result = new IsomorphicInfo(); // Запихиваем в соответствия те пары состояний, про которые уже всё понятно foreach (var statItem in ThisStatistics) { if (statItem.Value.Potential.Count == 1) { if (!statesCorrespondence.ExistsFirst(statItem.Key) && !statesCorrespondence.ExistsSecond(statItem.Value.Potential[0])) { statesCorrespondence.AddAssociation(statItem.Key, statItem.Value.Potential[0]); } else { result = null; break; } } } if (result != null) { result.As.AddRange( stateSet.Select( s => ThisStatistics.Where(ss => ss.Key.StateCore == s.StateCore).First().Value)); result.Bs.AddRange( other.stateSet.Select( s => OtherStatistics.Where(ss => ss.Key.StateCore == s.StateCore).First().Value)); result.Zs.AddRange(inputSet.Select(i => new InputInfo(i))); result.Xs.AddRange(other.inputSet.Select(i => new InputInfo(i))); if (!RecursiveInput( new List <InputInfo>(inputSet.Select(i => new InputInfo(i))), new List <InputInfo>(other.inputSet.Select(i => new InputInfo(i))), result)) { result = null; } } } } return(result); }