/// <summary>
        /// Reorganizes <see cref="AbstractChain"/> into <see cref="AbstractChain"/>.
        /// </summary>
        /// <param name="source">
        /// Source chain.
        /// </param>
        /// <returns>
        /// The <see cref="AbstractChain"/>.
        /// </returns>
        public override AbstractChain Reorganize(AbstractChain source)
        {
            var result = source.Clone() as AbstractChain;
            if (result != null)
            {
                return result;
            }

            result = new BaseChain();
            result.ClearAndSetNewLength(source.GetLength());

            var iteratorRead = new IteratorSimpleStart(source, 1);
            var iteratorWrite = new IteratorWritableStart(result);
            iteratorRead.Reset();
            iteratorWrite.Reset();
            iteratorRead.Next();
            iteratorWrite.Next();

            for (int i = 0; i < source.GetLength(); i++)
            {
                iteratorWrite.WriteValue(iteratorRead.Current());
                iteratorRead.Next();
                iteratorWrite.Next();
            }

            return result;
        }
        public void FourthTest()
        {
            var resultChain = new BaseChain(10);
            var iterator = new IteratorWritableStart(resultChain);
            iterator.Reset();
            while (iterator.Next())
            {
                iterator.WriteValue(mother.PhantomMessageBc);
            }

            var gen = new PhantomChainGenerator(resultChain, new SimpleGenerator());
            List<BaseChain> res = gen.Generate(1000);
            int counter = 0;
            for (int i = 0; i < 999; i++)
            {
                for (int j = i + 1; j < 1000; j++)
                {
                    if (res[i].Equals(res[j]))
                    {
                        counter++;
                    }
                }
            }

            Assert.AreEqual(0, counter);
        }
        public void WriteTest()
        {
            var messages = new List<ValueString>(12)
                               {
                                   new ValueString('1'),
                                   new ValueString('2'),
                                   new ValueString('1'),
                                   new ValueString('3'),
                                   new ValueString('3'),
                                   new ValueString('1'),
                                   new ValueString('2'),
                                   new ValueString('1'),
                                   new ValueString('2'),
                                   new ValueString('2'),
                                   new ValueString('3'),
                                   new ValueString('1')
                               };

            var toWrite = new Chain(12);
            var iteratorWrite = new IteratorWritableStart(toWrite);
            int i = 0;
            while (iteratorWrite.Next())
            {
                iteratorWrite.WriteValue(messages[i++]);
            }

            Assert.AreEqual(chainToIterate, toWrite);
        }
        /// <summary>
        /// Generates sequence.
        /// </summary>
        /// <param name="length">
        /// Length of generated sequence.
        /// </param>
        /// <param name="chainRank">
        /// Rank of used markov chain.
        /// </param>
        /// <returns>
        /// Generated sequence as <see cref="BaseChain"/>.
        /// </returns>
        public override BaseChain Generate(int length, int chainRank)
        {
            var temp = new BaseChain();
            temp.ClearAndSetNewLength(length);
            var read = Rank > 1 ? new IteratorStart(temp, Rank - 1, 1) : null;
            var write = new IteratorWritableStart(temp);
            if (read != null)
            {
                read.Reset();
                read.Next();
            }

            write.Reset();
            Generator.Reset();

            int m = 0;
            for (int j = 0; j < length; j++)
            {
                if (m == HeterogeneityRank + 1)
                {
                    m = 0;
                }

                m += 1;

                write.Next();

                if (j >= Rank)
                {
                    if (read != null)
                    {
                        read.Next();
                    }
                }

                if (read != null)
                {
                    BaseChain chain = (BaseChain)read.Current();
                    var indexedChain = new int[chain.GetLength()];
                    for (int k = 0; k < chain.GetLength(); k++)
                    {
                        indexedChain[k] = Alphabet.IndexOf(chain[k]);
                    }

                    write.WriteValue(GetObject(ProbabilityMatrixes[m - 1].GetProbabilityVector(Alphabet, indexedChain)));
                }
            }

            return temp;
        }
        public void ThirdTest()
        {
            var resultChain = new BaseChain(63);
            var iter = new IteratorWritableStart(resultChain);
            iter.Reset();
            while (iter.Next())
            {
                iter.WriteValue(mother.PhantomMessageBc);
            }

            var gen = new PhantomChainGenerator(resultChain, new SimpleGenerator());
            List<BaseChain> res = gen.Generate(3000);
            Assert.AreEqual(res.Count, 3000);
        }