void LoadHMM(HMM<distribution::GaussianDistribution>& hmm,
             util::SaveRestoreUtility& sr)
{
  std::string type;
  size_t states;

  sr.LoadParameter(type, "hmm_type");
  if (type != "gaussian")
  {
    Rcpp::Rcout << "Cannot load non-Gaussian HMM (of type " << type << ") as "
        << "a Gaussian HMM!" << std::endl;
  }

  sr.LoadParameter(states, "hmm_states");

  // Load transition matrix.
  sr.LoadParameter(hmm.Transition(), "hmm_transition");

  // Now each emission distribution.
  hmm.Emission().resize(states);
  for (size_t i = 0; i < states; ++i)
  {
    std::stringstream s;
    s << "hmm_emission_mean_" << i;
    sr.LoadParameter(hmm.Emission()[i].Mean(), s.str());

    s.str("");
    s << "hmm_emission_covariance_" << i;
    sr.LoadParameter(hmm.Emission()[i].Covariance(), s.str());
  }

  hmm.Dimensionality() = hmm.Emission()[0].Mean().n_elem;
}
void LoadHMM(HMM<distribution::DiscreteDistribution>& hmm,
             util::SaveRestoreUtility& sr)
{
  std::string type;
  size_t states;

  sr.LoadParameter(type, "hmm_type");
  if (type != "discrete")
  {
    Rcpp::Rcout << "Cannot load non-discrete HMM (of type " << type << ") as "
        << "discrete HMM!" << std::endl;
  }

  sr.LoadParameter(states, "hmm_states");

  // Load transition matrix.
  sr.LoadParameter(hmm.Transition(), "hmm_transition");

  // Now each emission distribution.
  hmm.Emission().resize(states);
  for (size_t i = 0; i < states; ++i)
  {
    std::stringstream s;
    s << "hmm_emission_distribution_" << i;
    sr.LoadParameter(hmm.Emission()[i].Probabilities(), s.str());
  }

  hmm.Dimensionality() = 1;
}
void LoadHMM(HMM<gmm::GMM<> >& hmm,
             util::SaveRestoreUtility& sr)
{
  std::string type;
  size_t states;

  sr.LoadParameter(type, "hmm_type");
  if (type != "gmm")
  {
    Rcpp::Rcout << "Cannot load non-GMM HMM (of type " << type << ") as "
        << "a Gaussian Mixture Model HMM!" << std::endl;
  }

  sr.LoadParameter(states, "hmm_states");

  // Load transition matrix.
  sr.LoadParameter(hmm.Transition(), "hmm_transition");

  // Now each emission distribution.
  hmm.Emission().resize(states, gmm::GMM<>(1, 1));
  for (size_t i = 0; i < states; ++i)
  {
    std::stringstream s;
    s << "hmm_emission_" << i << "_gaussians";
    size_t gaussians;
    sr.LoadParameter(gaussians, s.str());

    s.str("");
    // Extract dimensionality.
    arma::vec meanzero;
    s << "hmm_emission_" << i << "_gaussian_0_mean";
    sr.LoadParameter(meanzero, s.str());
    size_t dimensionality = meanzero.n_elem;

    // Initialize GMM correctly.
    hmm.Emission()[i].Gaussians() = gaussians;
    hmm.Emission()[i].Dimensionality() = dimensionality;

    for (size_t g = 0; g < gaussians; ++g)
    {
      s.str("");
      s << "hmm_emission_" << i << "_gaussian_" << g << "_mean";
      sr.LoadParameter(hmm.Emission()[i].Means()[g], s.str());

      s.str("");
      s << "hmm_emission_" << i << "_gaussian_" << g << "_covariance";
      sr.LoadParameter(hmm.Emission()[i].Covariances()[g], s.str());
    }

    s.str("");
    s << "hmm_emission_" << i << "_weights";
    sr.LoadParameter(hmm.Emission()[i].Weights(), s.str());
  }

  hmm.Dimensionality() = hmm.Emission()[0].Dimensionality();
}
void SaveHMM(const HMM<gmm::GMM<> >& hmm,
             util::SaveRestoreUtility& sr)
{
  std::string type = "gmm";
  size_t states = hmm.Transition().n_rows;

  sr.SaveParameter(type, "hmm_type");
  sr.SaveParameter(states, "hmm_states");
  sr.SaveParameter(hmm.Transition(), "hmm_transition");

  // Now the emissions.
  for (size_t i = 0; i < states; ++i)
  {
    // Generate name.
    std::stringstream s;
    s << "hmm_emission_" << i << "_gaussians";
    sr.SaveParameter(hmm.Emission()[i].Gaussians(), s.str());

    s.str("");
    s << "hmm_emission_" << i << "_weights";
    sr.SaveParameter(hmm.Emission()[i].Weights(), s.str());

    for (size_t g = 0; g < hmm.Emission()[i].Gaussians(); ++g)
    {
      s.str("");
      s << "hmm_emission_" << i << "_gaussian_" << g << "_mean";
      sr.SaveParameter(hmm.Emission()[i].Means()[g], s.str());

      s.str("");
      s << "hmm_emission_" << i << "_gaussian_" << g << "_covariance";
      sr.SaveParameter(hmm.Emission()[i].Covariances()[g], s.str());
    }
  }
}
void SaveHMM(const HMM<distribution::DiscreteDistribution>& hmm,
             util::SaveRestoreUtility& sr)
{
  std::string type = "discrete";
  size_t states = hmm.Transition().n_rows;

  sr.SaveParameter(type, "hmm_type");
  sr.SaveParameter(states, "hmm_states");
  sr.SaveParameter(hmm.Transition(), "hmm_transition");

  // Now the emissions.
  for (size_t i = 0; i < states; ++i)
  {
    // Generate name.
    std::stringstream s;
    s << "hmm_emission_distribution_" << i;
    sr.SaveParameter(hmm.Emission()[i].Probabilities(), s.str());
  }
}
void SaveHMM(const HMM<distribution::GaussianDistribution>& hmm,
             util::SaveRestoreUtility& sr)
{
  std::string type = "gaussian";
  size_t states = hmm.Transition().n_rows;

  sr.SaveParameter(type, "hmm_type");
  sr.SaveParameter(states, "hmm_states");
  sr.SaveParameter(hmm.Transition(), "hmm_transition");

  // Now the emissions.
  for (size_t i = 0; i < states; ++i)
  {
    // Generate name.
    std::stringstream s;
    s << "hmm_emission_mean_" << i;
    sr.SaveParameter(hmm.Emission()[i].Mean(), s.str());

    s.str("");
    s << "hmm_emission_covariance_" << i;
    sr.SaveParameter(hmm.Emission()[i].Covariance(), s.str());
  }
}
 void Load(const util::SaveRestoreUtility& n) { n.LoadParameter(probabilities, "probabilities"); }
/**
 * Save to SaveRestoreUtility.
 */
void DiscreteDistribution::Save(util::SaveRestoreUtility& n) const
{
  n.SaveParameter(probabilities, "probabilities");
  n.SaveParameter(Type(), "type");
}
/**
 * Load from SaveRestoreUtility.
 */
void GaussianDistribution::Load(const util::SaveRestoreUtility& sr)
{
  sr.LoadParameter(mean, "mean");
  sr.LoadParameter(covariance, "covariance");
}
/*&
 * Save to SaveRestoreUtility.
 */
void GaussianDistribution::Save(util::SaveRestoreUtility& sr) const
{
  sr.SaveParameter(Type(), "type");
  sr.SaveParameter(mean, "mean");
  sr.SaveParameter(covariance, "covariance");
}