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 Plus(FA fa)
            {
                var clone = fa.ToNfa(true);

                Debug.Assert(clone.Final != null);

                clone.Final.Add(clone.Start);

                return(clone);
            }
Beispiel #3
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 #4
0
            public static FA Negate(FA dfa)
            {
                EnsureDfa(dfa);

                for (var i = 0; i < dfa.States.Count; ++i)
                {
                    dfa.States[i].IsFinal = !dfa.States[i].IsFinal;
                }

                return(dfa);
            }
Beispiel #5
0
        public static FA Or(FA first, params FA[] nexts)
        {
            var fa = first;

            foreach (var next in nexts)
            {
                fa = fa.Or(next);
            }

            return(fa);
        }
Beispiel #6
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 #7
0
                public FA Minimize(FA dfa)
                {
                    EnsureDfa(dfa);

                    dfa = MergeStates(dfa);
                    dfa = MergeTransitions(dfa);

                    var result = From(dfa.Start);

                    EnsureDfa(result);

                    return(result);
                }
Beispiel #8
0
 private static void EnsureDfa(FA dfa)
 {
     if (dfa.Final != null)
     {
         throw new Exception("DFA: dfa.Final must be null");
     }
     if (!dfa.Finals.Any())
     {
         throw new Exception("DFA: no final state");
     }
     if (dfa.States.Count < 1)
     {
         throw new Exception("DFA: at least on state");
     }
     EnsureDfaTransitions(dfa);
 }
Beispiel #9
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 #10
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 #11
0
                public static FA Build(FA dfa1, FA dfa2, Func <State, State, bool> isFinal)
                {
                    EnsureDfa(dfa1);
                    EnsureDfa(dfa2);

                    dfa1 = Complete(dfa1);
                    dfa2 = Complete(dfa2);

                    EnsureComplete(dfa1);
                    EnsureComplete(dfa2);

                    var cross = new State[dfa1.States.Count, dfa2.States.Count];

                    var t1 = dfa1.States.Select(s => GetTransitions(s)).ToList();
                    var t2 = dfa2.States.Select(s => GetTransitions(s)).ToList();

                    for (var n1 = 0; n1 < dfa1.States.Count; n1 += 1)
                    {
                        for (var n2 = 0; n2 < dfa2.States.Count; n2 += 1)
                        {
                            cross[n1, n2] = new State(isFinal(dfa1.States[n1], dfa2.States[n2]));
                        }
                    }

                    for (var n1 = 0; n1 < dfa1.States.Count; n1 += 1)
                    {
                        for (var n2 = 0; n2 < dfa2.States.Count; n2 += 1)
                        {
                            var state    = cross[n1, n2];
                            var ctranses = GetMerge(t1[n1], t2[n2]);
                            foreach (var ctrans in ctranses)
                            {
                                state.Add(Codepoints.From(ctrans.Range.Min, ctrans.Range.Max), cross[ctrans.Target1, ctrans.Target2]);
                            }
                        }
                    }

                    var dfa = From(cross[0, 0]);

                    EnsureComplete(dfa);

                    return(dfa.RemoveDead().Minimize());
                }
Beispiel #12
0
            public static FA ToNfa(FA dfa)
            {
                if (dfa.Final != null)
                {
                    return(dfa);
                }

                dfa.Final = new State();

                foreach (var final in dfa.Finals)
                {
                    final.Add(dfa.Final);
                }

                dfa.Final.Id = dfa.States.Count;
                dfa.States.Add(dfa.Final);
                foreach (var state in dfa.States)
                {
                    state.IsFinal = false;
                }

                return(dfa);
            }
Beispiel #13
0
            private static void EnsureComplete(FA dfa)
            {
                EnsureDfa(dfa);

                foreach (var state in dfa.States)
                {
                    var all = new Integers();
                    var sum = 0;
                    foreach (var transition in state.Transitions)
                    {
                        sum += transition.Set.Cardinality;
                        all.Add(transition.Set);
                    }
                    if (!UnicodeSets.IsAny(all))
                    {
                        throw new Exception("DFA: incomplete transition set (DFA is not `complete´)");
                    }
                    if (sum != all.Cardinality)
                    {
                        throw new Exception("DFA: overlapping transitions (DFA is not `sane´)");
                    }
                }
            }
Beispiel #14
0
 private static void EnsureDfa(FA dfa)
 {
     if (dfa.Final != null)
     {
         throw new Exception("DFA: dfa.Final must be null");
     }
     if (!dfa.Finals.Any())
     {
         throw new Exception("DFA: no final state");
     }
     if (dfa.States.Count < 1)
     {
         throw new Exception("DFA: at least on state");
     }
     for (var i = 0; i < dfa.States.Count; ++i)
     {
         if (dfa.States[i].Id != i)
         {
             throw new Exception("DFA: not properly numbered");
         }
     }
     EnsureDfaTransitions(dfa);
 }
Beispiel #15
0
            public static FA Complete(FA dfa)
            {
                EnsureDfa(dfa);

                State?sink = null;

                foreach (var state in dfa.States)
                {
                    var rest = UnicodeSets.Any();

                    foreach (var transition in state.Transitions)
                    {
                        rest = rest.ExceptWith(transition.Set);
                    }

                    if (!rest.IsEmpty)
                    {
                        if (sink == null)
                        {
                            sink = new State();
                            sink.Add(Integers.Any, sink);
                        }

                        state.Add(Integers.From(rest), sink);
                    }
                }

                if (sink != null)
                {
                    sink.Id = dfa.States.Count;
                    dfa.States.Add(sink);
                }

                EnsureComplete(dfa);

                return(dfa);
            }
Beispiel #16
0
            public static FA ToDfa(FA nfa)
            {
                if (nfa.Final == null)
                {
                    EnsureDfa(nfa);
                    return(nfa);
                }

                var once  = new UniqueQueue <Closure>();
                var start = new Closure(nfa.Start, nfa.Final);

                once.Enqueue(start);

                while (once.Count > 0)
                {
                    var closure     = once.Dequeue();
                    var transitions = closure.UnambiguateTransitions();

                    foreach (var transition in transitions)
                    {
                        var terminal      = transition.Key;
                        var targets       = transition.Value;
                        var targetClosure = new Closure(targets, nfa.Final);
                        once.Enqueue(targetClosure, out targetClosure);
                        var target = targetClosure.DfaState;

                        closure.DfaState.Add(Integers.From(terminal), target);
                    }
                }

                var dfa = From(start.DfaState);

                EnsureDfa(dfa);

                return(dfa);
            }
Beispiel #17
0
 public FA Difference(FA other, bool cloned = false)
 {
     return(Operations.Difference(CloneIf(cloned), other.CloneIf(cloned)));
 }
Beispiel #18
0
 public FA Substract(FA other, bool cloned = false)
 {
     return(Operations.Substract(CloneIf(cloned), other.CloneIf(cloned)));
 }
Beispiel #19
0
                public static FA Build(FA dfa1, FA dfa2, Func <State, State, bool> isFinal)
                {
                    EnsureDfa(dfa1);
                    EnsureDfa(dfa2);

                    dfa1 = Complete(dfa1);
                    dfa2 = Complete(dfa2);

                    EnsureComplete(dfa1);
                    EnsureComplete(dfa2);

                    var cross = new State[dfa1.States.Count, dfa2.States.Count];

                    var t1 = dfa1.States.Select(s => GetTransitions(s)).ToList();
                    var t2 = dfa2.States.Select(s => GetTransitions(s)).ToList();

                    for (var n1 = 0; n1 < dfa1.States.Count; n1 += 1)
                    {
                        var state1 = dfa1.States[n1];

                        for (var n2 = 0; n2 < dfa2.States.Count; n2 += 1)
                        {
                            var state2 = dfa2.States[n2];

                            var newState = new State(isFinal(state1, state2));
                            if (state1.IsPayload && !state2.IsPayload)
                            {
                                newState.AddPayload(state1);
                            }
                            else if (!state1.IsPayload && state2.IsPayload)
                            {
                                newState.AddPayload(state2);
                            }
                            else if (state1.IsPayload && state2.IsPayload)
                            {
                                Debug.Assert(true);
#if true
                                if (state1.Transitions.Count == 1 && state1.Transitions[0].Set.IsAny)
                                {
                                    newState.AddPayload(state1);
                                }
                                else if (state2.Transitions.Count == 1 && state2.Transitions[0].Set.IsAny)
                                {
                                    newState.AddPayload(state2);
                                }
                                else
                                {
                                    if (state1.Payload > state2.Payload)
                                    {
                                        newState.AddPayload(state1);
                                    }
                                    else
                                    {
                                        newState.AddPayload(state2);
                                    }
                                    //throw new InternalException("missing tie break");
                                }
#endif
                            }

                            cross[n1, n2] = newState;
                        }
                    }

                    for (var n1 = 0; n1 < dfa1.States.Count; n1 += 1)
                    {
                        for (var n2 = 0; n2 < dfa2.States.Count; n2 += 1)
                        {
                            var state    = cross[n1, n2];
                            var ctranses = GetMerge(t1[n1], t2[n2]);
                            foreach (var ctrans in ctranses)
                            {
                                state.Add(Integers.From(ctrans.Range.Min, ctrans.Range.Max), cross[ctrans.Target1, ctrans.Target2]);
                            }
                        }
                    }

                    var dfa = From(cross[0, 0]);

                    EnsureComplete(dfa);

                    dfa = dfa.RemoveDead();

                    dfa = dfa.Minimize();

                    dfa = dfa.RemoveDead();

                    return(dfa);
                }
Beispiel #20
0
 public static FA Difference(FA dfa1, FA dfa2)
 {
     return(CrossBuilder.Build(dfa1, dfa2, (s1, s2) => s1.Final && !s2.Final));
 }
Beispiel #21
0
 public static FA Intersect(FA dfa1, FA dfa2)
 {
     return(CrossBuilder.Build(dfa1, dfa2, (s1, s2) => s1.Final && s2.Final));
 }
Beispiel #22
0
 public static FA Union(FA dfa1, FA dfa2)
 {
     return(CrossBuilder.Build(dfa1, dfa2, (s1, s2) => s1.Final || s2.Final));
 }
Beispiel #23
0
            public static FA RemoveDead(FA dfa)
            {
                EnsureDfa(dfa);

                var closures = new Dictionary <State, HashSet <State> >();

                void Initial(State state)
                {
                    var set = new HashSet <State>()
                    {
                        state
                    };

                    foreach (var transition in state.Transitions)
                    {
                        set.Add(transition.Target);
                    }

                    closures.Add(state, set);
                }

                bool Close(State state)
                {
                    var set = closures[state];

                    var before = set.Count;

                    foreach (var buddy in set.Where(s => s != state).ToList())
                    {
                        var buddySet = closures[buddy];

                        set.UnionWith(buddySet);
                    }

                    var after = set.Count;

                    return(after > before);
                }

                foreach (var state in dfa.States)
                {
                    Initial(state);
                }

                var added = true;

                while (added)
                {
                    added = false;

                    foreach (var state in dfa.States)
                    {
                        added = added || Close(state);
                    }
                }

                var dead = new HashSet <State>();

                foreach (var state in dfa.States)
                {
                    var set = closures[state];

                    if (set.All(s => !s.Final))
                    {
                        dead.UnionWith(set);
                    }
                }

                return(RemoveDead(dfa, dead));
            }
Beispiel #24
0
 public FA And(FA other) => Builder.Concat(this, other);
Beispiel #25
0
 public static FA Substract(FA dfa1, FA dfa2)
 {
     return(CrossBuilder.Build(dfa1, dfa2, (s1, s2) => s1.IsFinal && !s2.IsFinal));
 }
Beispiel #26
0
 public static FA Minimize(FA dfa)
 {
     return(new Minimizer().Minimize(dfa));
 }
Beispiel #27
0
                public FA Minimize(FA dfa)
                {
                    EnsureDfa(dfa);
                    dfa = Complete(dfa);
                    EnsureComplete(dfa);

                    var s = dfa.States;
                    var n = s.Count;

                    var table = new bool[n, n];

                    for (var i = 0; i < n; ++i)
                    {
                        for (var j = 0; j < n; ++j)
                        {
                            if (i >= j)
                            {
                                continue;
                            }

                            table[i, j] = s[i].Final && !s[j].Final ||
                                          !s[i].Final && s[j].Final ||
                                          s[i].Final && s[j].Final && s[i].Payload != s[j].Payload;
                        }
                    }

                    bool more = true;

                    while (more)
                    {
                        more = false;
                        for (var i = 0; i < n; ++i)
                        {
                            for (var j = 0; j < n; ++j)
                            {
                                if (i >= j)
                                {
                                    continue;
                                }

                                if (!table[i, j])
                                {
                                    foreach (var ti in s[i].Transitions)
                                    {
                                        foreach (var tj in s[j].Transitions)
                                        {
                                            if (ti.Set.Overlaps(tj.Set))
                                            {
                                                var si = ti.Target.Id;
                                                var sj = tj.Target.Id;
                                                if (si == sj)
                                                {
                                                    continue;
                                                }
                                                if (si > sj)
                                                {
                                                    var tmp = si;
                                                    si = sj;
                                                    sj = tmp;

                                                    Debug.Assert(si < sj);
                                                }

                                                var before = more;
                                                if (table[si, sj])
                                                {
                                                    var isij = table[i, j];
                                                    more = more || !table[i, j];
                                                    if (!before && more)
                                                    {
                                                        Debug.Assert(true);
                                                    }
                                                    table[i, j] = true;
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }

                    var combines = new List <StateSet>();

                    for (var i = 0; i < n; ++i)
                    {
                        for (var j = 0; j < n; ++j)
                        {
                            if (i >= j)
                            {
                                continue;
                            }

                            if (!table[i, j])
                            {
                                combines.Add(new StateSet {
                                    s[i], s[j]
                                });
                            }
                        }
                    }

                    var current = 0;

                    while (current < combines.Count)
                    {
                        for (var i = current + 1; i < combines.Count;)
                        {
                            if (combines[current].Overlaps(combines[i]))
                            {
                                combines[current].Add(combines[i]);
                                combines.RemoveAt(i);
                            }
                            else
                            {
                                i += 1;
                            }
                        }
                        current += 1;
                    }


                    foreach (var set in combines)
                    {
                        var premium = set.First();

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

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

                        EnsureDistinctTransitions(premium);
                    }

                    var mini = From(dfa.Start);

                    mini = MergeTransitions(mini);

                    return(mini);
                }
Beispiel #28
0
 public FA Union(FA other, bool cloned = false)
 {
     return(Operations.Union(CloneIf(cloned), other.CloneIf(cloned)));
 }
Beispiel #29
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);
                }
Beispiel #30
0
 public FA Intersect(FA other, bool cloned = false)
 {
     return(Operations.Intersect(CloneIf(cloned), other.CloneIf(cloned)));
 }