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