public override IAcceptWord Join(IJoin A) { if (!(A is DFA D2)) throw new NotSupportedException(); if (!this.SameAlphabet(D2)) throw new NotImplementedException("Different Alphabets are not implemented"); var deat = new DFATransform(); var accStates = new List<uint>(this.AcceptedStates.Length + D2.AcceptedStates.Length); uint sc = this.StatesCount; foreach (var t in (DFATransform)Transforms) deat.Add(t.Key.q, t.Key.c.Value, t.Value[0]); foreach (var t in (DFATransform)D2.Transforms) deat.Add(t.Key.q + sc, t.Key.c.Value, t.Value[0] + sc); accStates.AddRange(this.AcceptedStates); for (int i = 0; i < D2.AcceptedStates.Length; i++) accStates.Add(D2.AcceptedStates[i] + sc); accStates.Sort(); return new DFA($"DFA_Join({Name}+{A.Name})", (D2.StatesCount + sc), this.Alphabet, deat, this.StartState, accStates.ToArray()); }
/// <summary> /// Minimize DFA with TableFillingAlg /// </summary> /// <returns></returns> public DFA Minimize() { var tfEqClasses = TableFillingAlgEqClasses(this); // half matrix TF var State2eqClass = new uint[this.StatesCount]; // Fill state to eqClass matching for (uint i = 0; i < tfEqClasses.Length; i++) for (int j = 0; j < tfEqClasses[i].Length; j++) State2eqClass[tfEqClasses[i][j]] = i; // generate Transform, and modify to eqclasses var deaT = new DFATransform(); foreach (var item in Transforms) { // q,qnext EqClass uint tSrcEqClass = State2eqClass[item.Key.q]; uint tDstEqClass = State2eqClass[item.Value[0]]; deaT.TryAdd(tSrcEqClass, item.Key.c.Value, tDstEqClass); } // add eqClasses of accepted states var acc = new List<uint>(AcceptedStates.Length); for (uint i = 0; i < AcceptedStates.Length; i++) acc.Add(State2eqClass[AcceptedStates[i]]); acc.Sort(); // give each onging state its eqClass states[] as name string[] names = new string[tfEqClasses.Length]; for (uint i = 0; i < tfEqClasses.Length; i++) names[i] = string.Join(',', tfEqClasses[i]); return new DFA($"DFA_Minimized({Name})", names, this.Alphabet, deaT, State2eqClass[this.StartState], acc.Distinct().ToArray()); }
public override IAutomat PurgeStates() { (uint[] translate, string[] names, uint[] aStates) = base.RemovedStateTranslateTables(); var newT = new DFATransform(); foreach (var t2 in Transforms) if (translate.Contains(t2.Key.q)) foreach (var v in t2.Value) if (translate.Contains(v)) newT.Add(translate.ArrayIndex(t2.Key.q), t2.Key.c.Value, translate.ArrayIndex(v)); return new DFA($"{Name}_purged", names, Alphabet, newT, translate.ArrayIndex(StartState), aStates); }
} // end StatesEqual #region "Operations" public override IAutomat HomomorphismChar(Dictionary<char, char> Translate) { var deat = new DFATransform(); var Alp = (char[])this.Alphabet.Clone(); foreach (var dt in (DFATransform)Transforms) if (Translate.ContainsKey(dt.Key.c.Value)) deat.Add(dt.Key.q, Translate[dt.Key.c.Value], dt.Value[0]); else deat.Add(dt.Key.q, dt.Key.c.Value, dt.Value[0]); for (int i = 0; i < this.Alphabet.Length; i++) if (Translate.ContainsKey(this.Alphabet[i])) Alp[i] = Translate[this.Alphabet[i]]; return new DFA($"DFA_HomomorphismChar({Name})", this.StatesCount, Alp, deat, this.StartState, this.AcceptedStates); }
public static DFA GenerateRandom() { const byte MAX_STATES = 20; const byte MAX_CHAR = 7; var rnd = Uni.Utils.RND; int stateCount = rnd.Next(1, MAX_STATES); char[] alphabet = RandomGenerator.RandomAlphabet(1, MAX_CHAR); uint[] accState = RandomGenerator.RandomAcceptedStates(1, stateCount / 3, stateCount); var t = new DFATransform(); for (uint i = 0; i < stateCount; i++) { char[] rndAlph = alphabet.Randomize(); for (int j = 0; j < rndAlph.Length; j++) t.Add(i, alphabet[j], (uint)rnd.Next(0, stateCount)); } var ret = new DFA("DFA_Random", (uint)stateCount, alphabet, t, (uint)rnd.Next(0, stateCount), accState); ret.Name = $"DFA_Random_q{stateCount}_a{alphabet.Length}_{ret.GetHashCode()}"; return ret; }
public static DFA ProductDea(DFA D1, DFA D2, eProductDeaMode mode) { uint len = (D1.StatesCount * D2.StatesCount); char[] newAlphabet = D1.Alphabet.Union(D2.Alphabet).ToArray(); // if (!D1.SameAlphabet(D2)) // throw new NotImplementedException("Different Alphabets are not implemented"); var accStates = new List<uint>(D1.AcceptedStates.Length + D2.AcceptedStates.Length); string[] stateNames = new string[len]; var deat = new DFATransform(); // iterate Cross D1xD2, chars for (uint i = 0; i < D1.StatesCount; i++) { for (uint j = 0; j < D2.StatesCount; j++) { // index of state in matrix uint index = (i * D2.StatesCount + j); stateNames[index] = $"{i},{j}"; foreach (char c in newAlphabet) { // Transform exists, out qNext bool exist1 = ((DFATransform)D1.Transforms).TryGetValue(i, c, out uint qNext1); bool exist2 = ((DFATransform)D2.Transforms).TryGetValue(j, c, out uint qNext2); // same calc logic for dstIndex in Matrix uint dstIndex; if (exist1 & exist2) dstIndex = (qNext1 * D2.StatesCount + qNext2); else if (exist1) dstIndex = (qNext1 * D2.StatesCount + qNext1); else if (exist2) dstIndex = qNext2; else throw new ApplicationException(); // add non existing tuple if (!deat.ContainsKey(index, c)) // & exist1 & exist2) deat.Add(index, c, dstIndex); else throw new ApplicationException(); if (mode == eProductDeaMode.Intersect) { // add to accStates if both dea state ist acc if (D1.IsAcceptedState(i) & D2.IsAcceptedState(j)) accStates.Add(index); } else if (mode == eProductDeaMode.Union) { // add to accStates if one dea state ist acc if (D1.IsAcceptedState(i) | D2.IsAcceptedState(j)) accStates.Add(index); } else if (mode == eProductDeaMode.Diff) { // add to accStates if first and not second accepted if (D1.IsAcceptedState(i) & !D2.IsAcceptedState(j)) accStates.Add(index); } } } } return new DFA($"DEA_Product{mode}({D1.Name}+{D2.Name})", stateNames, newAlphabet, deat, 0, accStates.Distinct().ToArray()); }
public DFA(string name, string[] states, char[] alphabet, DFATransform transform, uint startState, params uint[] acceptedStates) : base(name, states, alphabet, transform, startState, acceptedStates) { }