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())); }
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()); }
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()); }