public MacroTransition GetMacro (State state, byte read, bool facingRight) { var store = facingRight ? _MacroDeltaR : _MacroDeltaL; MacroTransition trans; if (store.TryGetValue (state, read, out trans)) { trans.UsageCount++; } return trans; }
public MacroTransition ( State source, byte read, bool facingRight, State q, byte write, short d, ulong shifts, byte[] readUnpacked, byte[] writeUnpacked) { if (source == null) throw new ArgumentNullException (); if (readUnpacked == null) throw new ArgumentNullException (); if (writeUnpacked == null) throw new ArgumentNullException (); Source = source; Read = read; StartFacingRight = facingRight; Next = q; Write = write; Direction = d; Shifts = shifts; _ReadUnpacked = readUnpacked; _WriteUnpacked = writeUnpacked; if (Next != null) { if (false || (StartFacingRight && Direction == readUnpacked.Length) || (!StartFacingRight && Direction == +1) ) { EndFacingRight = true; } else if (false || (!StartFacingRight && Direction == -readUnpacked.Length) || (StartFacingRight && Direction == -1) ) { EndFacingRight = false; } else { EndFacingRight = null; } } }
public TmDefinition (JsonTmDefinition def) { if (def == null) throw new ArgumentNullException (); Gamma = MapSymbols (def.Gamma, 0); Sigma = new Dictionary<byte, string> (); foreach (var sig in def.Sigma) { Sigma.Add (Gamma.Where (p => p.Value == sig).First ().Key, sig); } Func<string, State> createState = name => { var halting = false || def.AcceptingState == name || def.RefusingState == name; var ts = halting ? null : new SimpleTransition[Gamma.Count]; var q = new State (Q.Count, name, ts); Q.Add (name, q); return q; }; Q0 = createState (def.InitialState); foreach (var qs in def.NonfinalStates) { if (qs == def.InitialState) { continue; } createState (qs); } if (def.AcceptingState != null) { createState (def.AcceptingState); } if (def.RefusingState != null) { createState (def.RefusingState); } foreach (var t in def.Delta) { var qin = Q[t.From]; byte gin = Gamma.First (p => p.Value == t.Read).Key; var qout = Q[t.To]; byte gout = Gamma.First (p => p.Value == t.Write).Key; short dir; switch (t.Dir) { case "R": dir = 1; break; case "L": dir = -1; break; case "S": dir = 0; break; default: throw new Exception (); } var st = new SimpleTransition (qin, gin, qout, gout, dir); qin.Delta[gin] = st; qout.Sources.Add (st); } SuggestedMacroSize = def.SuggestedMacroSize; UpdateShortDefinitionString (); }
/// <summary> /// </summary> /// <param name="s"> /// Format: /// q0,q1,...; Q /// s0,s1,...; Sigma /// g0,g1,...; Gamma without Sigma /// q,i -> q',o,d; Single Delta transition, repeatable /// K=n; Suggested macro width, optional /// /* anywhere: comments in old C style allowed */ /// </param> public TmDefinition (string s) { if (s == null) throw new ArgumentNullException (); if (s.Count (c => c == ';') <= 1) { // todo: bug when ';' in comments s = DefinitionLibrary.CreateBeaverFromNote (s); } FullDefinitionString = s; s = StripComments (s); var split = s.Split (';').Select (x => x.Trim ()).ToList (); var sStates = split[0]; split.RemoveAt (0); var sHalting = split[0]; split.RemoveAt (0); var sSigma = split[0]; split.RemoveAt (0); var sGamma = split[0]; split.RemoveAt (0); /* * Sigma/Gamma */ var sigmasplit = sSigma.Split (','); var gammasplit = sGamma.Split (','); Sigma = MapSymbols (sigmasplit, 1); Gamma = MapSymbols (gammasplit.Skip (1), 1 + Sigma.Count); Gamma.Add (0, gammasplit[0]); foreach (var sig in Sigma) { Gamma.Add (sig.Key, sig.Value); } /* * Q * (can only be constructed once Gamma is known) */ var statessplit = sStates.Split (','); foreach (var p in statessplit.Select (x => x.Trim ())) { if (p == "") { continue; } if (Q.Count >= 255) { throw new Exception (); } var q = new State ((byte) Q.Count, p, new SimpleTransition[Gamma.Count]); Q.Add (p, q); if (Q0 == null) { Q0 = q; } } foreach (var p in sHalting.Split (',').Select (x => x.Trim ())) { if (p == "") { continue; } if (Q.Count >= 255) { throw new Exception (); } var q = new State ((byte) Q.Count, p, null); Q.Add (p, q); if (Q0 == null) { Q0 = q; } } var haltingStates = Q.Values.Where (q => q.Delta == null).ToArray (); if (haltingStates.Length == 0) { var nonhaltingStates = Q.OrderBy (x => x.Key).Select (x => x.Value).ToArray (); Qa = nonhaltingStates[nonhaltingStates.Length - 2]; Qr = nonhaltingStates[nonhaltingStates.Length - 1]; } else if (haltingStates.Length == 1) { Qa = haltingStates[0]; Qr = null; } else { Qa = haltingStates[0]; Qr = haltingStates[1]; } // Here be dragons /* * Delta */ while (split.Any ()) { var d = split[0]; d = d.TrimStart (' ', '\t'); split.RemoveAt (0); if (d == "") { continue; } if (d.StartsWith ("K=")) { d = d.Substring (2); SuggestedMacroSize = Unlog.Util.StringCutting.CutInt (ref d); split.Insert (0, d); continue; } var parts = d.Split (new[] { "->" }, 2, StringSplitOptions.None); var input = parts[0].Split (',').Select (x => x.Trim ()).ToArray (); var output = parts[1].Split (',').Select (x => x.Trim ()).ToArray (); var sqin = input[0]; var stin = input[1]; var sqout = output[0]; var stout = output[1]; var sd = output[2].ToUpperInvariant (); // Check different notation if (sd != "L" && sd != "R") { if (stout == "L" || stout == "R") { var tmp = sd; sd = stout; stout = sqout; sqout = tmp; } } var qin = Q[sqin]; byte gin = Gamma.First (p => p.Value == stin).Key; var qout = Q[sqout]; byte gout = Gamma.First (p => p.Value == stout).Key; short dir; switch (sd) { case "R": dir = 1; break; case "L": dir = -1; break; case "S": dir = 0; break; default: throw new Exception (); } var t = new SimpleTransition (qin, gin, qout, gout, dir); qin.Delta[gin] = t; qout.Sources.Add (t); } UpdateShortDefinitionString (); }
public static MacroTransition CreateSingleMacroTransition ( TmDefinition def, State q, byte readPacked, bool facingRight, MacroPacker packerInfo) { if (def == null) throw new ArgumentNullException (); if (q == null) throw new ArgumentNullException (); if (packerInfo == null) throw new ArgumentNullException (); var readUnpacked = packerInfo.Decode (readPacked); var left = facingRight ? new byte[0] : readUnpacked.SubArray (0, readUnpacked.Length - 1); var right = facingRight ? readUnpacked : readUnpacked.SubArray (readUnpacked.Length - 1, 1); var tape = new LimitedBasicTape (left, right, def.Gamma); short dir; var tm = new SimpleTmRun (def, tape, new LimitedBasicTape (tape, def.Gamma), q); tm.AfterStep += new DetectTapeTooSmall ().Detect; tm.Options.AllowCreateMissingTransitionBranches = false; try { TmPrintOptions.Push (); TmPrintOptions.PrintTapeSteps = false; TmPrintOptions.PrintTransitionLevel = PrintTransitionLevel.None; var prevPos = (short) tape.Position; tm.Run (); dir = (short) (tape.Position - prevPos); } catch (TransitionNotDefinedException) { // Intentional throw. Let the caller handle this. throw; } finally { TmPrintOptions.Pop (); } Debug.Assert (tm.Result.Halted.HasValue != tape.ExitsOnLeftSide.HasValue); if (tm.Result.Halted == false) { return new MacroTransition (q, readPacked, facingRight, null, readPacked, 0, tm.Shifts, readUnpacked, readUnpacked); } else { var writeUnpacked = tape.Tape; var writePacked = packerInfo.Encode (writeUnpacked); return new MacroTransition (q, readPacked, facingRight, tm.Q, writePacked, dir, tm.Shifts, readUnpacked, writeUnpacked); } }