/// <summary>
        /// Construct a discrete HMM with the specified number of states.
        /// </summary>
        /// <param name="states">The number of states.</param>
        public HiddenMarkovModel(int states)
        {
            _items = null;
            pi = new double[states];
            _transitionProbability = EngineArray.AllocateDouble2D(states, states);
            _stateDistributions = new IStateDistribution[states];

            for (int i = 0; i < states; i++)
            {
                pi[i] = 1.0/states;

                _stateDistributions[i] = new ContinousDistribution(
                    StateCount);

                for (int j = 0; j < states; j++)
                {
                    _transitionProbability[i][j] = 1.0/states;
                }
            }
        }
        /// <inheritdoc/>
        public Object Read(Stream istream)
        {
            int states = 0;
            int[] items;
            double[] pi = null;
            Matrix transitionProbability = null;
            IDictionary<String, String> properties = null;
            IList<IStateDistribution> distributions = new List<IStateDistribution>();

            EncogReadHelper reader = new EncogReadHelper(istream);
            EncogFileSection section;

            while ((section = reader.ReadNextSection()) != null)
            {
                if (section.SectionName.Equals("HMM")
                        && section.SubSectionName.Equals("PARAMS"))
                {
                    properties = section.ParseParams();

                }
                if (section.SectionName.Equals("HMM")
                        && section.SubSectionName.Equals("CONFIG"))
                {
                    IDictionary<String, String> p = section.ParseParams();

                    states = EncogFileSection.ParseInt(p, HiddenMarkovModel.TAG_STATES);

                    if (p.ContainsKey(HiddenMarkovModel.TAG_ITEMS))
                    {
                        items = EncogFileSection.ParseIntArray(p, HiddenMarkovModel.TAG_ITEMS);
                    }
                    pi = section.ParseDoubleArray(p, HiddenMarkovModel.TAG_PI);
                    transitionProbability = EncogFileSection.ParseMatrix(p, HiddenMarkovModel.TAG_TRANSITION);
                }
                else if (section.SectionName.Equals("HMM")
                      && section.SubSectionName.StartsWith("DISTRIBUTION-"))
                {
                    IDictionary<String, String> p = section.ParseParams();
                    String t = p[HiddenMarkovModel.TAG_DIST_TYPE];
                    if ("ContinousDistribution".Equals(t))
                    {
                        double[] mean = section.ParseDoubleArray(p, HiddenMarkovModel.TAG_MEAN);
                        Matrix cova = EncogFileSection.ParseMatrix(p, HiddenMarkovModel.TAG_COVARIANCE);
                        ContinousDistribution dist = new ContinousDistribution(mean, cova.Data);
                        distributions.Add(dist);
                    }
                    else if ("DiscreteDistribution".Equals(t))
                    {
                        Matrix prob = EncogFileSection.ParseMatrix(p, HiddenMarkovModel.TAG_PROBABILITIES);
                        DiscreteDistribution dist = new DiscreteDistribution(prob.Data);
                        distributions.Add(dist);
                    }
                }
            }

            HiddenMarkovModel result = new HiddenMarkovModel(states);
            EngineArray.PutAll(properties, result.Properties);
            result.TransitionProbability = transitionProbability.Data;
            result.Pi = pi;
            int index = 0;
            foreach (IStateDistribution dist in distributions)
            {
                result.StateDistributions[index++] = dist;
            }

            return result;
        }