private bool CheckCorrespondence(IsomorphicInfo isomorphicInfo)
        {
            bool result = true;

            foreach (var a in isomorphicInfo.As)
            {
                foreach (var outgoingPair in a.State.Outgoing)
                {
                    var isOk = isomorphicInfo.StatesCorrespondence.GetSecond(outgoingPair.Value.GetTransRes(random).DestState) ==
                               isomorphicInfo.StatesCorrespondence.GetSecond(outgoingPair.Value.FromState).Outgoing.
                               Where(
                        o =>
                        o.Value.ActionCore ==
                        isomorphicInfo.InputCorrespondence.GetSecond(
                            new InputInfo(outgoingPair.Value.ActionCore)).Input).FirstOrDefault().Value.GetTransRes(random).DestState;

                    if (isOk)
                    {
                        var w  = outgoingPair.Value.GetTransRes(random).Output;
                        var w1 =
                            isomorphicInfo.StatesCorrespondence.GetSecond(a.State).Outgoing.Where(
                                o =>
                                o.Value.ActionCore ==
                                isomorphicInfo.InputCorrespondence.GetSecond(
                                    new InputInfo(outgoingPair.Value.ActionCore)).Input).FirstOrDefault().Value.GetTransRes(random).Output;
                        isomorphicInfo.OutputCorrespondence.AddAssociation(w, w1);
                    }
                    else
                    {
                        result = false;
                        break;
                    }
                }
                if (!result)
                {
                    break;
                }
            }
            return(result);
        }
        private bool RecursiveInput(
            List <InputInfo> Zs,
            List <InputInfo> Xs,
            IsomorphicInfo isomorphicInfo)
        {
            bool result = false;

            if (Zs.Count > 0)
            {
                var z = Zs[0];
                var x = z.GetFirst(Xs);
                if (x != null)
                {
                    isomorphicInfo.InputCorrespondence.AddAssociation(z, x);
                    result = RecursiveInput(
                        new List <InputInfo>(Zs.Where(i => i.Input != z.Input)),//.Skip(1)),
                        new List <InputInfo>(Xs.Where(i => i.Input != x.Input)),
                        isomorphicInfo);
                    if (!result)
                    {
                        z.Rejected.Add(x.Input);
                        isomorphicInfo.InputCorrespondence.RemoveAssociationFirst(z);
                        foreach (var zz in Zs.Skip(1))
                        {
                            zz.Rejected.Clear();
                        }
                        result = RecursiveInput(Zs, Xs, isomorphicInfo);
                    }
                }
            }
            else
            {
                result = RecursiveState(
                    isomorphicInfo.As,
                    isomorphicInfo.Bs,
                    isomorphicInfo);
            }
            return(result);
        }
        private bool RecursiveState(
            List <StateInfo> As,
            List <StateInfo> Bs,
            IsomorphicInfo isomorphicInfo)
        {
            bool result = false;

            if (As.Count > 0)
            {
                var a = As[0];
                var b = a.GetFirstPotential(Bs);
                if (b != null)
                {
                    isomorphicInfo.StatesCorrespondence.AddAssociation(a.State, b.State);
                    result = RecursiveState(new List <StateInfo>(As.Where(s => s.State.StateCore != a.State.StateCore)),//Skip(1)),
                                            new List <StateInfo>(Bs.Where(s => s.State.StateCore != b.State.StateCore)),
                                            isomorphicInfo);
                    if (!result)
                    {
                        a.Rejected.Add(b.State);
                        isomorphicInfo.StatesCorrespondence.RemoveAssociationFirst(a.State);
                        foreach (var aa in As.Skip(1))
                        {
                            aa.Rejected.Clear();
                        }
                        result = RecursiveState(As, Bs, isomorphicInfo);
                    }
                }
            }
            else
            {
                if (isomorphicInfo.StatesCorrespondence.Count() == isomorphicInfo.As.Count)
                {
                    result = CheckCorrespondence(isomorphicInfo);
                }
            }
            return(result);
        }
        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);
        }