예제 #1
0
 public static IEnumerable <int> Step(this IAutomaton @this, IEnumerable <int> state, char character)
 {
     return(@this.GetEpsilonClosure(state.SelectMany(s => @this.TransitionsBySource
                                                     .GetOrDefault(s, EmptyTargets)
                                                     .ReadChar(character))
                                    .ToArray()));
 }
예제 #2
0
        public static bool Read(this IAutomaton @this, string input)
        {
            @this.Print();
            var state = new HashSet <int>(@this.GetEpsilonClosure(@this.StartState));

            foreach (var c in input)
            {
                state = new HashSet <int>(@this.Step(state, c));
                if (!state.Any())
                {
                    return(false);
                }
            }
            return(@this.AcceptingStates.Intersect(state).Any());
        }
예제 #3
0
        public static IAutomaton Determinize(this IAutomaton @this)
        {
            var builder     = new AutomatonBuilder();
            var newStates   = new Dictionary <decimal, int>();
            var start       = @this.GetEpsilonClosure(@this.StartState);
            var queue       = new Queue <IEnumerable <int> >();
            var transitions = new LinkedList <Tuple <decimal, ICharSet, decimal> >();

            queue.Enqueue(start);
            while (queue.Any())
            {
                var source     = queue.Dequeue();
                var sourceBits = source.ToBits();
                if (newStates.ContainsKey(sourceBits))
                {
                    continue;
                }
                var state = builder.AddState();
                newStates[sourceBits] = state;

                //define start and end
                if (source == start)
                {
                    builder.SetStartState(state);
                }
                if (source.Any(st => @this.AcceptingStates.Contains(st)))
                {
                    builder.AcceptState(state);
                }

                //get all possible inputs
                var inputs = new List <ICharSet>();
                foreach (var st in source)
                {
                    var transitionTargets = @this.TransitionsBySource.GetOrDefault(st);
                    if (transitionTargets == null)
                    {
                        continue;
                    }
                    foreach (var lhs in transitionTargets.GetKeys())
                    {
                        if (lhs != CharSet.Epsilon)
                        {
                            // A \ B
                            // B \ A
                            // A ^ B
                            var distinct = true;
                            inputs = inputs.SelectMany(rhs =>
                            {
                                var first  = lhs.Except(rhs);
                                var second = rhs.Except(lhs);
                                var third  = lhs.Intersect(rhs);
                                if (third.Any())
                                {
                                    distinct = false;
                                }
                                return(new[] { first, second, third }.Where(a => a.Length > 0));
                            }).ToList();
                            if (distinct)
                            {
                                inputs.Add(lhs);
                            }
                        }
                    }
                }

                //find target states (in epsilon closure)
                foreach (var c in inputs)
                {
                    var dfaState = new HashSet <int>();
                    foreach (var st in source)
                    {
                        var transition = @this.TransitionsBySource.GetOrDefault(st);
                        var targets    = transition?.ReadSet(c);
                        if (targets == null)
                        {
                            continue;
                        }
                        foreach (var target in targets)
                        {
                            dfaState.Add(target);
                        }
                    }
                    if (dfaState.Any())
                    {
                        var epsilonTarget = @this.GetEpsilonClosure(dfaState.ToArray());
                        var targetBits    = epsilonTarget.ToBits();
                        transitions.AddLast(new Tuple <decimal, ICharSet, decimal>(sourceBits, c, targetBits));
                        queue.Enqueue(epsilonTarget);
                    }
                }
            }
            //add all transitions
            foreach (var transition in transitions)
            {
                var source = newStates[transition.Item1];
                var target = newStates[transition.Item3];
                builder.AddTransition(source, transition.Item2, target);
            }
            return(builder.Build());
        }