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