//                                               -*- C++ -*-
/**
 *  @file  MixtureClassifier.cxx
 *  @brief K-Fold cross validation
 *
 *  (C) Copyright 2005-2012 EDF-EADS-Phimeca
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License.
 *
 *  This library is distributed in the hope that it will be useful
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 *
 *  @author schueller
 *  @date   2010-11-09 13:44:00 +0100 (Tue, 09 Nov 2010)
 */

#include "MixtureClassifier.hxx"
#include "PersistentObjectFactory.hxx"

BEGIN_NAMESPACE_OPENTURNS



CLASSNAMEINIT(MixtureClassifier);


static Factory<MixtureClassifier> RegisteredFactory("MixtureClassifier");

/* Default constructor */
MixtureClassifier::MixtureClassifier()
  : ClassifierImplementation()
{
}

/* Default constructor */
MixtureClassifier::MixtureClassifier(const Mixture & mixture)
  : ClassifierImplementation(),
    distributionCollection_(mixture.getDistributionCollection())
{
}

/* Virtual constructor */
MixtureClassifier * MixtureClassifier::clone() const
{
  return new MixtureClassifier( *this );
}

/* String converter */
String MixtureClassifier::__repr__() const
{
  return OSS() << "class=" << GetClassName()
         << " distributionCollection_=" << distributionCollection_;
}

UnsignedLong MixtureClassifier::classify(const NumericalPoint& inP) const
{
  UnsignedLong size = distributionCollection_.getSize();
  UnsignedLong bestClass = 0;
  NumericalScalar bestGrade = -1.0;
  for ( UnsignedLong i = 0; i < size; ++ i )
  {
    NumericalScalar grade = distributionCollection_[i].getWeight() * distributionCollection_[i].computePDF( inP );
    if ( grade > bestGrade )
    {
      bestClass = i;
      bestGrade = grade;
    }
  }
  return bestClass;
}

NumericalScalar MixtureClassifier::grade(const NumericalPoint& inP, UnsignedLong outC) const
{
  UnsignedLong size = distributionCollection_.getSize();
  if (outC >= size)
    throw InvalidDimensionException(HERE) << "Class number (=" << outC << ") must be lower than size (=" << size << ").";
  return distributionCollection_[outC].getWeight() * distributionCollection_[outC].computePDF( inP );
}

/* Method save() stores the object through the StorageManager */
void MixtureClassifier::save(Advocate & adv) const
{
  ClassifierImplementation::save(adv);
  adv.saveAttribute( "distributionCollection_", distributionCollection_ );
}

/* Method load() reloads the object from the StorageManager */
void MixtureClassifier::load(Advocate & adv)
{
  ClassifierImplementation::load(adv);
  adv.loadAttribute( "distributionCollection_", distributionCollection_ );
}


END_NAMESPACE_OPENTURNS
