Beispiel #1
0
            public static FA Single(Integers terminal)
            {
                var start = new State();
                var end   = new State();

                start.Add(terminal, end);

                return(FA.From(start, end));
            }
Beispiel #2
0
            public static FA None()
            {
                var start   = new State();
                var illegal = new State();

                start.Add(Integers.Any, illegal);
                illegal.Add(Integers.Any, illegal);

                return(FA.From(start, start));
            }
Beispiel #3
0
            public static FA Concat(FA fa, FA other)
            {
                var first = fa.ToNfa(true);

                Debug.Assert(first.Final != null);
                other = other.ToNfa(true);
                Debug.Assert(other.Final != null);

                first.Final.Add(other.Start);

                return(FA.From(first.Start, other.Final));
            }
Beispiel #4
0
            public static FA From(string sequence)
            {
                Debug.Assert(!string.IsNullOrEmpty(sequence));

                var start   = new State();
                var current = start;
                var next    = (State?)null;

                foreach (var ch in sequence)
                {
                    next = new State();
                    current.Add(Integers.From(ch), next);
                    current = next;
                }

                Debug.Assert(next != null);
                return(FA.From(start, next));
            }
Beispiel #5
0
            public static FA Or(FA fa, FA other)
            {
                var first = fa.ToNfa(true);

                Debug.Assert(first.Final != null);
                var second = other.ToNfa(true);

                Debug.Assert(second.Final != null);
                var newEnd = new State();

                first.Start.Add(second.Start);

                first.Final.Add(newEnd);
                second.Final.Add(newEnd);


                return(FA.From(first.Start, newEnd));
            }
Beispiel #6
0
                private FA MergeStates(FA dfa)
                {
                    //
                    // https://en.wikipedia.org/wiki/DFA_minimization
                    // Hopcroft's algorithm
                    //

#if true
                    var nons = new StateSet(dfa.Nons.ToList());
                    var all  = dfa.States.ToList();

                    var partitions = new List <StateSet> {
                        nons
                    };
                    var working = new List <StateSet> {
                        nons
                    };

                    var fgroups = from state in dfa.Finals group state by state.Payload;

                    foreach (var fgroup in fgroups)
                    {
                        partitions.Add(new StateSet(fgroup));
                    }
#else
                    var finals = new StateSet(dfa.Finals.ToList());
                    var nons   = new StateSet(dfa.Nons.ToList());
                    var all    = dfa.States.ToList();

                    var partitions = new List <StateSet> {
                        finals, nons
                    };
                    var working = new List <StateSet> {
                        finals
                    };
#endif

                    var terminals = new HashSet <Integers>(all.SelectMany(state => state.Transitions).Select(transition => transition.Set));

                    while (working.Count > 0)
                    {
                        var a = working[0];
                        working.RemoveAt(0);

                        foreach (var terminal in terminals)
                        {
                            var x = new StateSet();
                            foreach (var state in all)
                            {
                                foreach (var transition in state.Transitions)
                                {
                                    if (transition.Set.Overlaps(terminal))
                                    {
                                        if (a.Contains(transition.Target))
                                        {
                                            x.Add(state);
                                            break;
                                        }
                                    }
                                }
                            }

                            var i = 0;

                            while (i < partitions.Count)
                            {
                                var y             = partitions[i];
                                var x_intersect_y = x.IntersectWith(y);

                                var y_without_x = y.ExceptWith(x);

                                if (x_intersect_y.IsEmpty || y_without_x.IsEmpty)
                                {
                                    i += 1;
                                    continue;
                                }
                                partitions[i] = x_intersect_y;
                                i            += 1;
                                partitions.Insert(i, y_without_x);
                                i += 1;

                                var j = 0;
                                while (j < working.Count)
                                {
                                    if (working[j] == y)
                                    {
                                        working.RemoveAt(j);
                                        working.Add(x_intersect_y);
                                        working.Add(y_without_x);
                                        break;
                                    }

                                    j += 1;
                                }

                                if (j == working.Count)
                                {
                                    // ReSharper disable once ConvertIfStatementToConditionalTernaryExpression
                                    if (x_intersect_y.Count <= y_without_x.Count)
                                    {
                                        working.Add(x_intersect_y);
                                    }
                                    else
                                    {
                                        working.Add(y_without_x);
                                    }
                                }
                            }
                        }
                    }

                    foreach (var partition in partitions)
                    {
                        if (partition.Count >= 1)
                        {
#if true
                            var groups = from s in partition group s by s.Payload;

                            foreach (var group in groups)
                            {
                                List <State> dfaStates = group.ToList();

                                var premium = dfaStates.First();

                                var remove = dfaStates.Skip(1).ToList();

                                foreach (var state in all)
                                {
                                    foreach (var transition in state.Transitions)
                                    {
                                        if (remove.Contains(transition.Target))
                                        {
                                            transition.Retarget(premium);
                                        }
                                    }
                                }

                                EnsureDistinctTransitions(premium);
                            }
#else
                            List <State> dfaStates = partition.ToList();

                            var premium = dfaStates.First();

                            var remove = dfaStates.Skip(1).ToList();

                            foreach (var state in all)
                            {
                                foreach (var transition in state.Transitions)
                                {
                                    if (remove.Contains(transition.Target))
                                    {
                                        transition.Retarget(premium);
                                    }
                                }
                            }

                            EnsureDistinctTransitions(premium);
#endif
                        }
                    }

                    var result = FA.From(dfa.Start);

                    EnsureDfa(result);

                    return(result);
                }