예제 #1
0
 private void CalcStats(IEnumerable <FSMState <TInput, TOutput> > states, EventableDictionary <FSMState <TInput, TOutput>, StateInfo> statistics)
 {
     foreach (var state in states)
     {
         StateInfo thisInfo = new StateInfo(state);
         statistics.TryAdd(state, ref thisInfo);
         foreach (var outgoing in state.Outgoing)
         {
             StateInfo info      = new StateInfo(outgoing.Value.GetTransRes(random).DestState);
             var       destState = outgoing.Value.GetTransRes(random).DestState;
             if (!statistics.TryAdd(destState, ref info))
             {
                 info = statistics[destState];
             }
             ++info.InputCount;
             if (destState.StateCore == state.StateCore)
             {
                 ++info.LoopCount;
             }
             //thisInfo = info;
         }
         thisInfo.OutputCount = state.Outgoing.Count;
     }
 }
예제 #2
0
        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);
        }