/// <summary> /// Initializes a new instance of the <see cref="T:NondeterministicFiniteAutomaton`3"/> class by copying the states from the given <paramref name="origin"/>. /// </summary> /// <param name="origin">The given <see cref="T:NondeterministicFiniteAutomaton`3"/> from which the data is copied, must be effective.</param> /// <remarks> /// <para>The <see cref="T:IState`2"/> instances in the given <paramref name="origin"/> are not cloned: they are the same and modifications /// to the states in the original automaton can have effects in the new automaton and vice-versa.</para> /// </remarks> /// <exception cref="ArgumentNullException">The given automaton must be effective.</exception> protected NondeterministicFiniteAutomaton(NondeterministicFiniteAutomaton <TStateTag, TEdgeTag, TCollection> origin) { if (origin == null) { throw new ArgumentNullException("origin", "Origin must be effective"); } Contract.EndContractBlock(); this.stateDictionary = ((ICloneable <TagRegister <TStateTag, IState <TStateTag, TEdgeTag>, TCollection> >)origin.stateDictionary).Clone(); this.acceptingStateDictionary = ((ICloneable <TagRegister <TStateTag, IState <TStateTag, TEdgeTag>, TCollection> >)origin.acceptingStateDictionary).Clone(); this.initialState = origin.initialState; }
public void TestWriteDotText() { NondeterministicFiniteAutomaton <int, char> nfa = new NondeterministicFiniteAutomaton <int, char> ( new Tuple <int, char, int>[] { new Tuple <int, char, int>(0x01, 'a', 0x02) }, 0x01, new int[] { 0x02 } ); using (TextWriter tw = new StringWriter()) { nfa.WriteDotText(tw); tw.Close(); Console.Error.WriteLine(tw.ToString()); } }
/// <summary> /// Disjunct this nondeterministic finite automaton with the given one into a new one such that /// the resulting one accepts a sequence of data if and only if this sequence can be accepted by this automaton /// or by the <paramref name="other"/> automaton. /// </summary> /// <param name="other">The second <see cref="T:INondeterministicFiniteAutomaton`2"/> in the disjunction process.</param> /// <param name="nullTag">An edge tag used for transitions without the need to consume (or "eat") any characters.</param> /// <param name="startTag">The tag of an (optional) <see cref="T:IState`2"/> that must be constructed to disjunct this and the given automaton.</param> /// <remarks> /// <para>For some implementations, the <paramref name="nullTag"/> might be optional, in that case, any value can be passed.</para> /// <para>If the second automaton is not effective, this automaton will be cloned (not deeply, with the same <see cref="T:IState`2"/> instances).</para> /// <para>Although the return parameter only specifies <see cref="T:INondeterministicFiniteAutomaton`2"/>, the return type is always the same as this type.</para> /// </remarks> public INondeterministicFiniteAutomaton <TStateTag, TEdgeTag> Disjunction(INondeterministicFiniteAutomaton <TStateTag, TEdgeTag> other, TEdgeTag nullTag, TStateTag startTag) { NondeterministicFiniteAutomaton <TStateTag, TEdgeTag, TCollection> clone = this.Clone(); if (other != null) { IState <TStateTag, TEdgeTag> initState = new State <TStateTag, TEdgeTag> (startTag); initState.AddEdge(new Edge <TStateTag, TEdgeTag> (nullTag, this.initialState)); initState.AddEdge(new Edge <TStateTag, TEdgeTag> (nullTag, other.InitalState)); clone.stateDictionary.Add(initState); clone.initialState = initState; clone.stateDictionary.AddAll(other.States); clone.acceptingStateDictionary.AddAll(other.AcceptingStates); } return(clone); }
/// <summary> /// Calculate the Kleene star of this nondeterministic finite automaton such that a sequence is accepted by the /// resulting nondeterministic finite automaton if and only if the sequence can be subdivided in (possibly zero) /// subsequences such that every subsequence is accepted by this nondeterministic finite automaton. /// </summary> /// <param name="nullTag">An edge tag used for transitions without the need to consume (or "eat") any characters.</param> /// <param name="startTag">The tag of an (optional) <see cref="T:IState`2"/> that must be constructed to kleen star this and the given automaton.</param> /// <remarks> /// <para>For some implementations, the <paramref name="nullTag"/> might be optional, in that case, any value can be passed.</para> /// <para>Although the return parameter only specifies <see cref="T:INondeterministicFiniteAutomaton`2"/>, the return type is always the same as this type.</para> /// </remarks> public INondeterministicFiniteAutomaton <TStateTag, TEdgeTag> KleeneStar(TEdgeTag nullTag, TStateTag startTag) { NondeterministicFiniteAutomaton <TStateTag, TEdgeTag, TCollection> clone = this.Clone(); IState <TStateTag, TEdgeTag> init = new State <TStateTag, TEdgeTag> (startTag); init.AddEdge(new Edge <TStateTag, TEdgeTag> (nullTag, this.initialState)); IEdge <TStateTag, TEdgeTag> returnEdge = new Edge <TStateTag, TEdgeTag> (nullTag, init); IEnumerable <IState <TStateTag, TEdgeTag> > stateEnum = (IEnumerable <IState <TStateTag, TEdgeTag> >)clone.stateDictionary; foreach (IState <TStateTag, TEdgeTag> state in stateEnum) { state.AddEdge(returnEdge); } clone.initialState = init; clone.stateDictionary.Add(init); clone.acceptingStateDictionary.Add(init); return(clone); }
/// <summary> /// Concatenate this nondeterministic finite automaton with the given one into a new one such that /// the resulting one accepts a sequence of data if and only if it can be subdivded into two parts such /// that the first part is accepted by this automaton and the second by the <paramref name="other"/> automaton. /// </summary> /// <param name="other">The second <see cref="T:INondeterministicFiniteAutomaton`2"/> in the concatenation process.</param> /// <param name="nullTag">An edge tag used for transitions without the need to consume (or "eat") any characters.</param> /// <remarks> /// <para>For some implementations, the <paramref name="nullTag"/> might be optional, in that case, any value can be passed.</para> /// <para>If the second automaton is not effective, this automaton will be cloned (not deeply, with the same <see cref="T:IState`2"/> instances).</para> /// <para>Although the return parameter only specifies <see cref="T:INondeterministicFiniteAutomaton`2"/>, the return type is always the same as this type.</para> /// </remarks> public INondeterministicFiniteAutomaton <TStateTag, TEdgeTag> Concatenate(INondeterministicFiniteAutomaton <TStateTag, TEdgeTag> other, TEdgeTag nullTag) { NondeterministicFiniteAutomaton <TStateTag, TEdgeTag, TCollection> clone = this.Clone(); if (other != null) { IState <TStateTag, TEdgeTag> tostate = other.InitalState; IEdge <TStateTag, TEdgeTag> edge = new Edge <TStateTag, TEdgeTag> (nullTag, tostate); IEnumerable <IState <TStateTag, TEdgeTag> > acceptings = this.acceptingStateDictionary; foreach (IState <TStateTag, TEdgeTag> state in acceptings) { state.AddEdge(edge); } clone.stateDictionary.AddAll(other.States); clone.acceptingStateDictionary.Clear(); clone.acceptingStateDictionary.AddAll(other.AcceptingStates); } return(clone); }