public static Machine GetFromOptions(SMOptions options) { Machine stateMachine; if (options.Transitions.Any(tr => tr.IsEpsilon) || options.Transitions .GroupBy(tr => tr.StartState + tr.Token) .Any(gr => gr.Count() > 1)) { stateMachine = new MachineNonDetermined(); } else { stateMachine = new MachineDetermined(); } var statesNames = options.GetStates(); var statesDict = new Dictionary <string, State>(); foreach (var stateName in statesNames) { var state = new State(stateName, options.FinalStates.Contains(stateName)); statesDict.Add(stateName, state); stateMachine.AddState(state); } foreach (var transitionOptions in options.Transitions) { if (transitionOptions.IsEpsilon) { stateMachine.AddTransition(new Transition( statesDict[transitionOptions.StartState], statesDict[transitionOptions.EndState] )); } else { stateMachine.AddTransition(new Transition( statesDict[transitionOptions.StartState], transitionOptions.Token, statesDict[transitionOptions.EndState] )); } } stateMachine.Init(options.InitialState); return(stateMachine); }
public new MachineDetermined RenameToNormalNames(string startsWith) { startsWith ??= "q"; var renameDict = new Dictionary <State, State>(); var buffer = new List <State> { InitialState }; var n = 1; while (buffer.Any()) { var currentNode = buffer[0]; var nextStops = Transitions.Where(tr => Equals(tr.StartState, currentNode) && !buffer.Contains(tr.EndState) && !renameDict.Keys.Contains(tr.EndState)).Select(tr => tr.EndState).Distinct(new StatesComparer()).ToList(); if (nextStops.Any()) { buffer.AddRange(nextStops); } buffer.Remove(currentNode); renameDict.Add(currentNode, new State($"{startsWith}{n}", currentNode.IsFinal)); n++; } var renamedMachine = new MachineDetermined(); renamedMachine.AddStateRange(renameDict.Values); renamedMachine.AddTransitionRange(Transitions.Select(transition => new Transition(renameDict[transition.StartState], transition.Token, renameDict[transition.EndState]))); renamedMachine.Init(renameDict[InitialState].Id); return(renamedMachine); }
public override Machine Minimize() { var tokens = Transitions.Select(transition => transition.Token).Distinct().ToList(); tokens.Sort(); var currentSplitting = States.GroupBy(state => state.IsFinal ? "A0" : "B0").ToList(); for (int k = 1; k <= States.Count; ++k) { var newSplitting = new List <IGrouping <string, State> >(); foreach (var currentCategory in currentSplitting) { var subSplittingIntoCurrentCategory = currentCategory.GroupBy(checkedStartState => { var kLocal = k; var currentSplittingLocal = currentSplitting; var movementCategories = tokens.Select(checkedToken => { var endState = Transitions.Find(transition => Equals(transition.StartState, checkedStartState) && transition.Token == checkedToken) ?.EndState; if (endState == null) { return(""); } var endCategory = currentSplittingLocal.Find(suspectedCategory => suspectedCategory.Contains(endState)); var nameOfEndCategory = "{" + string.Join(",", endCategory) + "}" /* + "[" + kLocal + "]"*/; return(nameOfEndCategory); }); var movementsRow = string.Join("|", movementCategories); return(movementsRow); }).ToList(); newSplitting.AddRange(subSplittingIntoCurrentCategory); } currentSplitting = newSplitting; // If current splitting ans new splitting are equal // Then break; here [todo] } var minimizedStateMachine = new MachineDetermined(); var newStates = currentSplitting.Select(category => new { State = new State("{" + string.Join(",", category.Select(state => state.Id)) + "}", category.Any(state => state.IsFinal)), Category = category }).ToList(); minimizedStateMachine.AddStateRange(newStates.Select(state => state.State)); foreach (var startPoint in newStates) { var ways = startPoint.Category.Key.Split("|") .Zip(tokens, (endPoint, token) => new { Token = token, EndPoint = endPoint }) .Where(x => !string.IsNullOrEmpty(x.EndPoint)) .Select(x => { var endPointState = newStates.Find(state => state.State.Id == x.EndPoint); return(new Transition(startPoint.State, x.Token, endPointState.State)); // Null check?? }); minimizedStateMachine.AddTransitionRange(ways); } minimizedStateMachine.Init(newStates.Find(x => x.Category.Contains(InitialState))?.State.Id ?? throw new InitialStateIsNullException("null", minimizedStateMachine)); return(minimizedStateMachine); }
public override MachineDetermined Determine(bool verbose = false) { var determined = new MachineDetermined(); if (IsThereAnyEpsilonTransition || IsThereAnyMultiVariantTokenTransition) { var tokens = Transitions.Select(tr => tr.Token).Distinct().ToList(); tokens.Remove(null); tokens.Sort(); var initialClosure = EpsilonClosure(new List <State> { InitialState }); var buffer = new List <List <State> > { initialClosure }; var newStates = new List <List <State> >(); var tempMovements = new List <TempTransition>(); if (verbose) { Console.WriteLine("ε-closure({" + InitialState.Id + "}) = " + GetClosureName(initialClosure) + "\n"); } while (buffer.Any()) { var currentClosure = buffer[0]; buffer.Remove(currentClosure); newStates.Add(currentClosure); foreach (var token in tokens) { var nextStops = Transitions.Where(tr => !tr.IsEpsilon && currentClosure.Contains(tr.StartState) && tr.Token == token) .Select(tr => tr.EndState) .ToList(); var newClosure = EpsilonClosure(nextStops); if (verbose) { Console.Write($"Move({GetClosureName(currentClosure)}, {token}) = {GetClosureName(nextStops)};"); } if (newClosure.Any()) { tempMovements.Add(new TempTransition(GetClosureName(currentClosure), token, GetClosureName(newClosure))); } if (!newClosure.Any() || newStates.Select(GetClosureName).Contains(GetClosureName(newClosure)) || buffer.Select(GetClosureName).Contains(GetClosureName(newClosure))) { if (verbose) { Console.WriteLine(); } continue; } if (verbose) { Console.WriteLine($" ε-closure({GetClosureName(nextStops)}) = {GetClosureName(newClosure)}"); } buffer.Add(newClosure); } if (verbose) { Console.WriteLine(); } } var determinedStates = newStates.Select(state => new State(GetClosureName(state), state.Any(x => x.IsFinal))).ToList(); determined.AddStateRange(determinedStates); foreach (var startNewState in determinedStates) { foreach (var token in tokens) { var way = tempMovements.Find(mv => mv.Q0 == startNewState.Id && mv.Token == token); if (way == null) { continue; } var nextStop = determinedStates.Find(st => st.Id == way.Q1); determined.AddTransition(new Transition(startNewState, token, nextStop)); } } determined.Init(GetClosureName(initialClosure)); } else { determined.AddStateRange(States); determined.AddTransitionRange(Transitions); determined.Init(InitialState.Id); } return(determined); }