Example #1
0
    // Removes the states that are not on a successful path in the automaton.
    public static Fsa Trim(this Fsa automaton)
    {
        var transitiveClosure = automaton.Transitions
                                .Select(t => (t.From, t.To))
                                .ToHashSet()
                                .TransitiveClosure();

        var reachableFromInitial = automaton.Initial
                                   .Union(transitiveClosure
                                          .Where(x => automaton.Initial.Contains(x.Item1))
                                          .Select(x => x.Item2));
        var leadingToFinal = automaton.Final
                             .Union(transitiveClosure
                                    .Where(x => automaton.Final.Contains(x.Item2))
                                    .Select(x => x.Item1));
        var states = reachableFromInitial.Intersect(leadingToFinal).ToList();

        var transitions = automaton.Transitions
                          .Where(t => states.Contains(t.From) && states.Contains(t.To))
                          .Select(t => (
                                      states.IndexOf(t.From),
                                      t.Label,
                                      states.IndexOf(t.To)));

        var newInitial = states.Intersect(automaton.Initial);
        var newFinal   = states.Intersect(automaton.Final);

        return(new Fsa(
                   states.Select(s => states.IndexOf(s)),
                   newInitial.Select(s => states.IndexOf(s)),
                   newFinal.Select(s => states.IndexOf(s)),
                   transitions));
    }
Example #2
0
    public static Fsa Concat(this Fsa first, Fsa second)
    {
        var firstFinalStates = first.Final;

        second = Remap(second, first.States);
        var secondInitialStates = second.Initial;

        var initialStates = first.Initial.Intersect(first.Final).Any()
            ? first.Initial.Union(second.Initial)
            : first.Initial;

        var transitions = first.Transitions.Union(second.Transitions).ToList();

        foreach (var tr in first.Transitions.Where(t => first.Final.Contains(t.To)))
        {
            foreach (var state in second.Initial)
            {
                transitions.Add((tr.From, tr.Label, state));
            }
        }

        return(new Fsa(
                   states: first.States.Union(second.States),
                   initialStates,
                   second.Final,
                   transitions));
    }
Example #3
0
    // Convert to a classical Fsa where each transition label has length <= 1
    public static Fsa Expand(this Fsa automaton)
    {
        var multiSymbolTransitions = automaton.Transitions.Where(t => t.Label.Length > 1);

        var newStates      = automaton.States.ToList();
        var newTransitions = automaton.Transitions.Except(multiSymbolTransitions).ToHashSet();

        foreach (var tr in multiSymbolTransitions)
        {
            var wordLen            = tr.Label.Length;
            var intermediateStates = KNewStates(wordLen - 1, newStates);
            var stateSeq           = new[] { tr.From }
            .Concat(intermediateStates)
            .Concat(new[] { tr.To })
            .ToList();

            newStates.AddRange(intermediateStates);
            var path = Enumerable.Range(0, stateSeq.Count - 1)
                       .Select(i => (stateSeq[i], tr.Label[i].ToString(), stateSeq[i + 1]));

            newTransitions.UnionWith(path);
        }

        return(new Fsa(newStates, automaton.Initial, automaton.Final, newTransitions));
    }
Example #4
0
    public static Fsa Union(this Fsa first, Fsa second)
    {
        second = Remap(second, first.States);

        return(new Fsa(
                   states: first.States.Concat(second.States),
                   initial: first.Initial.Concat(second.Initial),
                   final: first.Final.Concat(second.Final),
                   transitions: first.Transitions.Concat(second.Transitions)));
    }
Example #5
0
    // Clones the finite automaton by renaming the states
    static Fsa Remap(this Fsa automaton, IReadOnlyCollection <int> states)
    {
        var k = states.Count;

        return(new Fsa(
                   automaton.States.Select(s => s + k),
                   automaton.Initial.Select(s => s + k),
                   automaton.Final.Select(s => s + k),
                   automaton.Transitions.Select(t => (t.From + k, t.Label, t.To + k))));
    }
Example #6
0
    public static Fsa Optional(this Fsa automaton)
    {
        var state = new[] { NewState(automaton.States) };

        return(new Fsa(
                   automaton.States.Union(state),
                   automaton.Initial.Union(state),
                   automaton.Final.Union(state),
                   automaton.Transitions));
    }
Example #7
0
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Test void shouldFailGracefullyWhenPathCannotBeCreated()
        internal virtual void ShouldFailGracefullyWhenPathCannotBeCreated()
        {
            Path = new FileAnonymousInnerClass(this, TestDirectory.directory(), System.Guid.randomUUID().ToString());

            IOException exception = assertThrows(typeof(IOException), () => Fsa.mkdirs(Path));

            assertFalse(Fsa.fileExists(Path));
            string expectedMessage = format(UNABLE_TO_CREATE_DIRECTORY_FORMAT, Path);

            assertThat(exception.Message, @is(expectedMessage));
        }
Example #8
0
    /* Removes the epsilon transitions and preserves the automaton's language but
     * does not preserve the language of the individual states */
    public static Fsa EpsilonFree(this Fsa automaton)
    {
        var initial = automaton.Initial.SelectMany(automaton.EpsilonClosure);

        var transitions = automaton.Transitions
                          .Where(t => !string.IsNullOrEmpty(t.Label))
                          .SelectMany(t =>
                                      automaton
                                      .EpsilonClosure(t.To)
                                      .Select(es => (t.From, t.Label, es)));

        return(new Fsa(automaton.States, initial, automaton.Final, transitions));
    }
Example #9
0
    public static Dfsa Determinize(this Fsa automaton)
    {
        var fsa          = automaton.EpsilonFree().Expand();
        var subsetStates = new List <ISet <int> > {
            fsa.Initial.ToHashSet()
        };
        var dfsaTransitions    = new Dictionary <(int, char), int>();
        var stateTransitionMap = fsa.Transitions
                                 .GroupBy(t => t.From, t => (t.Label, t.To))
                                 .ToDictionary(g => g.Key, g => g.ToList());

        for (var n = 0; n < subsetStates.Count; n++)                            // we break from the loop when there is no unexamined state
        {
            var symbolToStates = subsetStates[n]                                // take the last unexamined subset state
                                 .Where(s => stateTransitionMap.ContainsKey(s)) // keep only the items with outgoing transitions
                                 .SelectMany(s => stateTransitionMap[s])        // flatten into a set of (symbol, target) pairs
                                 .GroupBy(p => p.Label.Single(), p => p.To)     // group them by symbol (fsa has only symbol transitions becase of "Expand")
                                 .ToDictionary(g => g.Key, g => g.ToHashSet()); // convert to dictionary of type <symbol, set of states>

            foreach (var kvp in symbolToStates)
            {
                var state = kvp.Value; // the newly formed state sets are in the Dfsa
                var label = kvp.Key;

                if (!subsetStates.Any(ss => ss.SetEquals(state))) // check if it has been added
                {
                    subsetStates.Add(state);
                }

                dfsaTransitions.Add(
                    (n, label),                                         // n is the index of the currently examined subset state, pair.Key (symbol) is the trans. label
                    subsetStates.FindIndex(ss => ss.SetEquals(state))); // goes to the index of the subset
            }
        }

        // DFA state names are the indices of the state subsets
        var renamedStates = Enumerable.Range(0, subsetStates.Count);

        // if a state subset contains a final state from the original automaton
        // then it is marked as final in the deterministic automaton
        var finalStates = renamedStates
                          .Where(index => subsetStates[index].Intersect(fsa.Final).Any());

        return(new Dfsa(renamedStates, 0, finalStates, dfsaTransitions));
    }
Example #10
0
    public static Fsa Plus(this Fsa automaton)
    {
        var initial        = NewState(automaton.States);
        var initialStates  = new int[] { initial };
        var newTransitions = new List <(int, string, int)>();

        foreach (var state in automaton.Initial)
        {
            newTransitions.Add((initial, string.Empty, state));
        }

        foreach (var state in automaton.Final)
        {
            newTransitions.Add((state, string.Empty, initial));
        }

        return(new Fsa(
                   automaton.States.Concat(initialStates),
                   initialStates,
                   automaton.Final,
                   automaton.Transitions.Concat(newTransitions)));
    }
Example #11
0
 public static Fsa Union(this Fsa fsa, params Fsa[] automata) =>
 automata.Aggregate(fsa, Union);
Example #12
0
 public static Fsa Concat(this Fsa fsa, params Fsa[] automata) =>
 automata.Aggregate(fsa, Concat);
Example #13
0
    public static Fst Product(this Fsa first, Fsa second)
    {
        var firstTransWithEpsilon = first.Transitions.Union(
            first.States.Select(s => (From: s, Label: string.Empty, To: s)));
        var secondTransWithEpsilon = second.Transitions.Union(
            second.States.Select(s => (From: s, Label: string.Empty, To: s)));

        var firstTransitionsPerState = firstTransWithEpsilon
                                       .GroupBy(t => t.From)
                                       .ToDictionary(g => g.Key, g => g);
        var secondTransitionsPerState = secondTransWithEpsilon
                                        .GroupBy(t => t.From)
                                        .ToDictionary(g => g.Key, g => g);

        var productStates = new List <(int, int)>();

        foreach (var i1 in first.Initial)
        {
            foreach (var i2 in second.Initial)
            {
                productStates.Add((i1, i2));
            }
        }

        var transitions = new HashSet <(int, string, string, int)>();

        for (int n = 0; n < productStates.Count; n++)
        {
            var(p1, p2) = productStates[n];
            var p1Trans      = firstTransitionsPerState[p1];
            var p2Trans      = secondTransitionsPerState[p2];
            var productTrans = new List <(string, string, int, int)>();

            foreach (var tr1 in p1Trans)
            {
                foreach (var tr2 in p2Trans)
                {
                    productTrans.Add((tr1.Label, tr2.Label, tr1.To, tr2.To));
                }
            }

            foreach (var(_, _, s1, s2) in productTrans)
            {
                if (!productStates.Contains((s1, s2)))
                {
                    productStates.Add((s1, s2));
                }
            }

            foreach (var tr in productTrans)
            {
                transitions.Add((n, tr.Item1, tr.Item2, productStates.IndexOf((tr.Item3, tr.Item4))));
            }
        }

        var states = Enumerable.Range(0, productStates.Count);

        var initial = states.Where(s =>
                                   first.Initial.Contains(productStates[s].Item1) &&
                                   second.Initial.Contains(productStates[s].Item2));

        var final = states.Where(s =>
                                 first.Final.Contains(productStates[s].Item1) &&
                                 second.Final.Contains(productStates[s].Item2));

        return(new Fst(states, initial, final, transitions).EpsilonFree().Trim());
    }
Example #14
0
 static Fsa XIgnoreX(Fsa fsa, ISet <char> fsaAlphabet, ISet <char> symbols) =>
 fsa.Identity()
 .Compose(XintroX(fsaAlphabet, symbols))
 .Range();
Example #15
0
 /* For a given automaton L and a set of symbols S, construct the automaton
 *   which recognizes all words from L with freely introduced symbols from S */
 static Fsa Ignore(Fsa fsa, ISet <char> fsaAlphabet, ISet <char> symbols) =>
 fsa.Identity()
 .Compose(Intro(fsaAlphabet, symbols))
 .Range();