public static void ExportToTemp(this IAcceptWord automat) { if (automat is IAutomat a2) { SaveAutomatImageToTemp(a2); } var formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(); var stream = new System.IO.FileStream(System.Environment.ExpandEnvironmentVariables($@"%temp%\automat\{automat.Name}.bin"), System.IO.FileMode.Create, System.IO.FileAccess.Write); formatter.Serialize(stream, automat); stream.Close(); }
internal static void AcceptWordConsoleLine(this IAcceptWord A, string w, bool onlytrue = false) { try { bool accepts = A.AcceptWord(w); if (accepts || !onlytrue) { System.Console.WriteLine($"{A.Name} accepts |{w.Length}| '{w}': {accepts}"); } } catch (Turing.TuringCycleException e) { System.Console.WriteLine($"{A.Name} {e.Message}"); } catch (ContextFree.PDAStackException e) { System.Console.WriteLine($"{A.Name} {e.Message}"); } }
public bool SameAlphabet(IAcceptWord A2) { if (this.Terminals.Length != A2.Alphabet.Length) { return(false); } for (int i = 0; i < this.Terminals.Length; i++) { if (this.Terminals[i] != A2.Alphabet[i]) { return(false); } } return(true); }
internal static void DebugMessage(string message, IAcceptWord a, Serpen.Uni.Utils.eDebugLogLevel level) { if (Serpen.Uni.Utils.DebugLogLevel >= level && System.Diagnostics.Debugger.IsAttached) { var stack = new System.Diagnostics.StackTrace(true); var sframe = stack.GetFrame(1); var smethod = sframe.GetMethod(); System.Diagnostics.Debug.WriteLine( smethod.DeclaringType.Name + "." + smethod.Name + ":" + sframe.GetFileLineNumber() + " " + (a != null ? "[" + a.Name + "] " : " ") + message); } }
public static bool TestEqualWithWords(IAcceptWord A1, IAcceptWord A2, int initialCount = 100) { int onceTrue = 0, onceFalse = 0; int passLevel = System.Math.Min(initialCount / 10, 5); string[] words = System.Array.Empty<string>(); int count = 0; if (A1 is CFGrammer cfg1) A1 = cfg1.ToChomskyNF(); if (A2 is CFGrammer cfg2) A2 = cfg2.ToChomskyNF(); while ((onceTrue < passLevel | onceFalse < passLevel) && count < initialCount * 2) { words = A1.GetRandomWords(initialCount / 2, 1, Serpen.Uni.Utils.Sqrt(initialCount), words); foreach (string w in words) { try { var erg1 = A1.AcceptWord(w); var erg2 = A2.AcceptWord(w); if (erg1) onceTrue++; else onceFalse++; if (erg1 != erg2) throw new Automat.Exception($"{count}. word '{w}' divides Automates", A1, A2); Utils.DebugMessage($"{count}. word '{w}' passes {erg1}", Uni.Utils.eDebugLogLevel.Verbose, A1, A2); count++; } catch (TuringCycleException) { } catch (PDAStackException) { } } } if (onceTrue >= passLevel && onceFalse >= passLevel) { Utils.DebugMessage($"{count} words passed ({onceTrue}/{onceFalse})", Uni.Utils.eDebugLogLevel.Verbose, A1, A2); return true; } else { if (A1.Equals(A2)) { Utils.DebugMessage($"{count} words passed, but not both tested ({onceTrue}/{onceFalse}), but Equals works", Uni.Utils.eDebugLogLevel.Verbose, A1, A2); return true; } else { Utils.DebugMessage($"{count} words passed, but not both tested ({onceTrue}/{onceFalse}), Equals not working", Uni.Utils.eDebugLogLevel.Normal, A1, A2); return true; } } }
public static bool InMyhillNerodeRelation(string w1, string w2, IAcceptWord automat, int count = 50) { var words = automat.GetRandomWords(count, 0, Serpen.Uni.Utils.Sqrt(count), System.Array.Empty<string>()); foreach (string w in words) { bool? erg1 = null, erg2 = null; try { erg1 = automat.AcceptWord(w1 + w); } catch (Turing.TuringCycleException) { } catch (ContextFree.PDAStackException) { } try { erg2 = automat.AcceptWord(w2 + w); } catch (Turing.TuringCycleException) { } catch (ContextFree.PDAStackException) { } if (erg1 != erg2) { Utils.DebugMessage($"word {w} divides {w1},{w2}", automat, Uni.Utils.eDebugLogLevel.Verbose); return false; } } return true; }
IAcceptWord JoinConcatUnion(IAcceptWord automat, JoinConcatUnionKind kind) { if (!(automat is PDA pda2)) throw new System.NotSupportedException(); if (kind != JoinConcatUnionKind.Join && !(automat is StatePDA)) throw new System.NotSupportedException(); if (this is StackPDA || automat is StackPDA) throw new System.NotImplementedException(); // TODO: investigate more, State PDA is perfect Stack PDA seems complicated // TODO: what if A1 or A2 has a StackStartsymbol set, should it be transformed // to a transform or applied uint offsetA1 = 0; // first state of A2 uint offsetA2 = this.StatesCount; // first state of A2 if (kind == JoinConcatUnionKind.Union) { offsetA1 = 1; offsetA2++; } char[] inputAlphabet = this.Alphabet.Union(pda2.Alphabet).ToArray(); char[] workAlphabet = this.WorkAlphabet.Union(pda2.WorkAlphabet).ToArray(); var pdat = new PDATransform(); uint startState; // Union: add new start state, with e to both starts if (kind == JoinConcatUnionKind.Union) { startState = 0; pdat.Add(0, null, null, null, this.StartState + offsetA1); pdat.AddM(0, null, null, null, pda2.StartState + offsetA2); } else startState = this.StartState; // add each D1 transform + offset of A1 foreach (var item in this.Transforms) foreach (var val in item.Value) pdat.AddM(item.Key.q + offsetA1, item.Key.ci, item.Key.cw, val.cw2, val.qNext + offsetA1); // add each D1 transform, + offset of A2 foreach (var item in pda2.Transforms) foreach (var val in item.Value) pdat.AddM(item.Key.q + offsetA2, item.Key.ci, item.Key.cw, val.cw2, val.qNext + offsetA2); uint[] accStates; if (kind == JoinConcatUnionKind.Concat) // Concat: has only accepted states from A2 accStates = new uint[pda2.AcceptedStates.Length]; else // Join, Union has A1, A2 accpted states accStates = new uint[this.AcceptedStates.Length + pda2.AcceptedStates.Length]; int i = 0; // store where D1 acc ends // iterate A1 acc for (; i < this.AcceptedStates.Length; i++) if (kind == JoinConcatUnionKind.Concat) // Concat: lead accepted states from A1 to A2 start pdat.AddM(this.AcceptedStates[i] + offsetA1, null, null, null, pda2.StartState + offsetA2); else // Join, Union: states from A1 are normal accepted accStates[i] = this.AcceptedStates[i] + offsetA1; if (kind == JoinConcatUnionKind.Concat) i = 0; // iterate A2 acs and + offsetA2 for (int j = 0; j < pda2.AcceptedStates.Length; j++) accStates[i + j] = (pda2.AcceptedStates[j] + offsetA2); if (this is StatePDA) return new StatePDA($"{kind.ToString()}({Name}+{pda2.Name})", this.StatesCount + pda2.StatesCount + offsetA1, inputAlphabet, workAlphabet, pdat, startState, pda2.StartSymbol, accStates); else if (this is StackPDA) return new StackPDA($"{kind.ToString()}({Name}+{pda2.Name})", this.StatesCount + pda2.StatesCount + offsetA1, inputAlphabet, workAlphabet, pdat, startState, pda2.StartSymbol); else throw new System.NotImplementedException(); }
CFGrammer Combine(IAcceptWord ia, string[] startBodysFormat, string nameExt) { if (!(ia is CFGrammer cfg2)) throw new System.NotSupportedException(); var newRules = new RuleSet(); List<char> finalVars = this.Variables.ToList(); List<char> finalTerms = this.Terminals.ToList(); char newStart = Utils.NextFreeCapitalLetter(this.VarAndTerm.Union(cfg2.VarAndTerm), this.StartSymbol); finalVars.Add(newStart); var translate = new Dictionary<char, char>(cfg2.VarAndTerm.Count); foreach (char V in cfg2.Variables) { if (!finalVars.Contains(V)) { finalVars.Add(V); translate.Add(V, V); } else { char newChar = Utils.NextFreeCapitalLetter(finalTerms.Union(finalVars), V); translate.Add(V, newChar); finalVars.Add(newChar); } } // assume char as terminal is equal when its equal foreach (char t in cfg2.Terminals) { if (!finalTerms.Contains(t)) { finalTerms.Add(t); } // else { // char newChar = Utils.NextFreeLowerLetter(finalTerms.Union(finalVars)); //against convention! // translate.Add(t, newChar); // finalTerms.Add(newChar); // } if (!translate.ContainsKey(t)) translate.Add(t, t); } for (int i = 0; i < startBodysFormat.Length; i++) startBodysFormat[i] = string.Format(startBodysFormat[i], this.StartSymbol, cfg2.StartSymbol, newStart); //New Start Rule, build newRules.Add(newStart, startBodysFormat); foreach (var r in this.Rules) { newRules.Add(r.Key, r.Value); } foreach (var r in cfg2.Rules) { var newVals = new List<string>(r.Value.Length); foreach (string body in r.Value) { var sw = new System.Text.StringBuilder(); foreach (char c in body) sw.Append(translate[c]); newVals.Add(sw.ToString()); } newRules.Add(translate[r.Key], newVals.ToArray()); } return new CFGrammer($"CFG_Combine({nameExt},{Name})", finalVars.ToArray(), finalTerms.ToArray(), newRules, newStart); }
IAcceptWord JoinConcatUnion(IAcceptWord automat, JoinConcatUnionKind unionConcatJoinKind) { if (!(automat is FABase fa2)) { throw new System.NotSupportedException(); } uint offsetA1 = 0; // first state of A2 uint offsetA2 = this.StatesCount; // first state of A2 if (unionConcatJoinKind == JoinConcatUnionKind.Union) { offsetA1 = 1; offsetA2++; } char[] inputAlphabet = this.Alphabet.Union(fa2.Alphabet).ToArray(); var neaeT = new NFAeTransform(); uint startState; // Union: add new start state, with e to both starts if (unionConcatJoinKind == JoinConcatUnionKind.Union) { startState = 0; neaeT.Add(0, null, this.StartState + offsetA1); neaeT.AddM(0, null, fa2.StartState + offsetA2); } else { startState = this.StartState; } // add each A1 transform + offset of A1 foreach (var item in this.Transforms) { foreach (var val in item.Value) { neaeT.AddM(item.Key.q + offsetA1, item.Key.c, val + offsetA1); } } // add each A1 transform, + offset of A2 foreach (var item in fa2.Transforms) { foreach (var val in item.Value) { neaeT.AddM(item.Key.q + offsetA2, item.Key.c, val + offsetA2); } } uint[] accStates; if (unionConcatJoinKind == JoinConcatUnionKind.Concat) { // Concat: has only accepted states from A2 accStates = new uint[fa2.AcceptedStates.Length]; } else { // Join, Union has A1, A2 accpted states accStates = new uint[this.AcceptedStates.Length + fa2.AcceptedStates.Length]; } int i = 0; // store where D1 acc ends // iterate A1 acc for (; i < this.AcceptedStates.Length; i++) { if (unionConcatJoinKind == JoinConcatUnionKind.Concat) { // Concat: lead accepted states from A1 to A2 start neaeT.AddM(this.AcceptedStates[i] + offsetA1, null, fa2.StartState + offsetA2); } else { // Join, Union: states from A1 are normal accepted accStates[i] = this.AcceptedStates[i] + offsetA1; } } if (unionConcatJoinKind == JoinConcatUnionKind.Concat) { i = 0; } // iterate A2 acs and + offsetA2 for (int j = 0; j < fa2.AcceptedStates.Length; j++) { accStates[i + j] = (fa2.AcceptedStates[j] + offsetA2); } return(new NFAe($"NEAe{unionConcatJoinKind.ToString()}({Name}+{fa2.Name})", this.StatesCount + fa2.StatesCount + offsetA1, inputAlphabet, neaeT, startState, accStates)); }