The abstract chain.
Наследование: IBaseObject
        /// <summary>
        /// Reorganizes source chain.
        /// </summary>
        /// <param name="source">
        /// Source chain.
        /// </param>
        /// <returns>
        /// <see cref="AbstractChain"/>.
        /// </returns>
        /// <exception cref="InvalidOperationException">
        /// Thrown if level is less than 0.
        /// </exception>
        public override AbstractChain Reorganize(AbstractChain source)
        {
            if (level < 0)
            {
                throw new InvalidOperationException("Markov chain level can't be less than 0");
            }

            if (level == 0)
            {
                return source;
            }

            var result = new BaseChain();
            result.ClearAndSetNewLength(source.GetLength() + level);
            for (int i = 0; i < source.GetLength(); i++)
            {
                result[i] = source[i];
            }

            var iterator = new IteratorStart(source, level, 1);
            iterator.Reset();
            iterator.Next();
            AbstractChain addition = iterator.Current();
            for (int i = 0; i < addition.GetLength(); i++)
            {
                result[source.GetLength() + i] = addition[i];
            }

            return result;
        }
        /// <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;
        }
        /// <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 resent = new BaseChain();
            resent.ClearAndSetNewLength(source.GetLength());
            for (int i = 0; i < source.GetLength(); i++)
            {
                var phantom = source[i] as ValuePhantom;
                resent.Set(phantom != null ? phantom[0] : source[i], i);
            }

            return resent;
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="IteratorBase"/> class.
        /// </summary>
        /// <param name="source">
        /// Source chain.
        /// </param>
        /// <param name="length">
        /// Length of subsequence.
        /// </param>
        /// <param name="step">
        /// Shift of iterator.
        /// </param>
        /// <exception cref="ArgumentException">
        /// Thrown if one or more arguments are invalid.
        /// </exception>
        public IteratorBase(AbstractChain source, int length, int step)
        {
            if (source == null || length <= 0 || source.GetLength() < length)
            {
                throw new ArgumentException("Iterator arguments are invalid.");
            }

            Length = length;
            Step = step;
            Source = source;
            MaxPosition = Source.GetLength() - Length;
            Reset();
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="IteratorSimpleStart"/> class.
        /// </summary>
        /// <param name="source">
        /// Source chain.
        /// </param>
        /// <param name="step">
        /// Shift of iterator.
        /// </param>
        /// <exception cref="ArgumentException">
        /// Thrown if one or more arguments are invalid.
        /// </exception>
        public IteratorSimpleStart(AbstractChain source, int step)
        {
            if (source == null || source.GetLength() < 1)
            {
                throw new ArgumentException("Sequence for iteration is null or empty.", "source");
            }

            Length = 1;
            Step = step;
            Source = source;
            MaxPosition = Source.GetLength() - Length;
            Reset();
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="CustomIterator"/> class.
        /// </summary>
        /// <param name="source">
        /// The source.
        /// </param>
        /// <param name="starts">
        /// The starts.
        /// </param>
        /// <param name="lengthes">
        /// The lengthes.
        /// </param>
        /// <exception cref="ArgumentException">
        /// Thrown if arguments are invalid.
        /// </exception>
        public CustomIterator(AbstractChain source, List<List<int>> starts, List<List<int>> lengthes)
        {
            if (source == null || starts == null || lengthes == null)
            {
                throw new ArgumentException("Invalid iterator params.");
            }

            if (starts.Count != lengthes.Count)
            {
                throw new ArgumentException("Starts and lengthes arrays contains not equal amount of elements.");
            }

            for (int i = 0; i < starts.Count; i++)
            {
                if (starts[i].Count != lengthes[i].Count)
                {
                    throw new ArgumentException("Starts and lengthes inner arrays contains not equal amount of elements.");
                }
            }

            this.starts = starts;
            this.lengthes = lengthes;
            this.source = source;
        }
 /// <summary>
 /// Reorganizes <see cref="AbstractChain"/> into <see cref="AbstractChain"/>.
 /// </summary>
 /// <param name="source">
 /// Source chain.
 /// </param>
 /// <returns>
 /// The <see cref="AbstractChain"/>.
 /// </returns>
 public abstract AbstractChain Reorganize(AbstractChain source);
 /// <summary>
 /// Initializes a new instance of the <see cref="IteratorWritableEnd"/> class.
 /// Iterator returns single element and shifts by one element.
 /// </summary>
 /// <param name="source">
 /// Source chain.
 /// </param>
 /// <exception cref="ArgumentException">
 /// Thrown if one or more arguments are invalid.
 /// </exception>
 public IteratorWritableEnd(AbstractChain source)
     : base(source, 1, 1)
 {
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="IteratorStart"/> class.
 /// </summary>
 /// <param name="source">
 /// Source chain.
 /// </param>
 /// <param name="length">
 /// Length of subsequence.
 /// </param>
 /// <param name="step">
 /// Shift of iterator.
 /// </param>
 /// <exception cref="ArgumentException">
 /// Thrown if one or more arguments are invalid.
 /// </exception>
 public IteratorStart(AbstractChain source, int length, int step)
     : base(source, length, step)
 {
 }