// Copyright (C) 2010  Davis E. King (davis@dlib.net)
// License: Boost Software License   See LICENSE.txt for the full license.
#undef DLIB_ONE_VS_ALL_DECISION_FUnCTION_ABSTRACT_H__
#ifdef DLIB_ONE_VS_ALL_DECISION_FUnCTION_ABSTRACT_H__


#include "../serialize.h"
#include <map>
#include "../any/any_decision_function_abstract.h"
#include "one_vs_all_trainer_abstract.h"
#include "null_df.h"

namespace dlib
{

// ----------------------------------------------------------------------------------------

    template <
        typename one_vs_all_trainer,
        typename DF1 = null_df, typename DF2 = null_df, typename DF3 = null_df,
        typename DF4 = null_df, typename DF5 = null_df, typename DF6 = null_df,
        typename DF7 = null_df, typename DF8 = null_df, typename DF9 = null_df,
        typename DF10 = null_df
        >
    class one_vs_all_decision_function
    {
        /*!
            REQUIREMENTS ON one_vs_all_trainer
                This should be an instantiation of the one_vs_all_trainer template.  
                It is used to infer which types are used for various things, such as 
                representing labels.

            REQUIREMENTS ON DF*
                These types can either be left at their default values or set
                to any kind of decision function object capable of being
                stored in an any_decision_function<sample_type,scalar_type>
                object.  These types should also be serializable.

            WHAT THIS OBJECT REPRESENTS
                This object represents a multiclass classifier built out of a set of 
                binary classifiers.  Each binary classifier is used to vote for the 
                correct multiclass label using a one vs. all strategy.  Therefore, 
                if you have N classes then there will be N binary classifiers inside 
                this object.

                Note that the DF* template arguments are only used if you want
                to serialize and deserialize one_vs_all_decision_function objects. 
                Specifically, all the types of binary decision function contained
                within a one_vs_all_decision_function must be listed in the
                template arguments if serialization and deserialization is to
                be used.
        !*/
    public:

        typedef typename one_vs_all_trainer::label_type label_type;
        typedef typename one_vs_all_trainer::sample_type sample_type;
        typedef typename one_vs_all_trainer::scalar_type scalar_type;
        typedef typename one_vs_all_trainer::mem_manager_type mem_manager_type;

        typedef std::map<label_type, any_decision_function<sample_type, scalar_type> > binary_function_table;

        one_vs_all_decision_function(
        );
        /*!
            ensures
                - #number_of_classes() == 0
                - #get_binary_decision_functions().size() == 0
                - #get_labels().size() == 0
        !*/

        explicit one_vs_all_decision_function(
            const binary_function_table& decision_functions
        ); 
        /*!
            ensures
                - #get_binary_decision_functions() == decision_functions
                - #get_labels() == a list of all the labels which appear in the
                  given set of decision functions
                - #number_of_classes() == #get_labels().size() 
        !*/

        template <
            typename df1, typename df2, typename df3, typename df4, typename df5,
            typename df6, typename df7, typename df8, typename df9, typename df10
            >
        one_vs_all_decision_function (
            const one_vs_all_decision_function<one_vs_all_trainer, 
                                               df1, df2, df3, df4, df5,
                                               df6, df7, df8, df9, df10>& item
        ); 
        /*!
            ensures
                - #*this will be a copy of item
                - #number_of_classes() == item.number_of_classes()
                - #get_labels() == item.get_labels()
                - #get_binary_decision_functions() == item.get_binary_decision_functions()
        !*/

        const binary_function_table& get_binary_decision_functions (
        ) const;
        /*!
            ensures
                - returns the table of binary decision functions used by this
                  object.  The label given to a test sample is computed by
                  determining which binary decision function has the largest
                  (i.e. most positive) output and returning the label associated
                  with that decision function.
        !*/

        const std::vector<label_type> get_labels (
        ) const;
        /*!
            ensures
                - returns a vector containing all the labels which can be
                  predicted by this object.
        !*/

        unsigned long number_of_classes (
        ) const;
        /*!
            ensures
                - returns get_labels().size()
                  (i.e. returns the number of different labels/classes predicted by
                  this object)
        !*/

        label_type operator() (
            const sample_type& sample
        ) const
        /*!
            requires
                - number_of_classes() != 0
            ensures
                - evaluates all the decision functions in get_binary_decision_functions()
                  and returns the predicted label.
        !*/
    };

// ----------------------------------------------------------------------------------------

    template <
        typename T,
        typename DF1, typename DF2, typename DF3,
        typename DF4, typename DF5, typename DF6,
        typename DF7, typename DF8, typename DF9,
        typename DF10 
        >
    void serialize(
        const one_vs_all_decision_function<T,DF1,DF2,DF3,DF4,DF5,DF6,DF7,DF8,DF9,DF10>& item, 
        std::ostream& out
    );
    /*!
        ensures
            - writes the given item to the output stream out.
        throws
            - serialization_error.  
              This is thrown if there is a problem writing to the ostream or if item 
              contains a type of decision function not listed among the DF* template 
              arguments.
    !*/

// ----------------------------------------------------------------------------------------

    template <
        typename T,
        typename DF1, typename DF2, typename DF3,
        typename DF4, typename DF5, typename DF6,
        typename DF7, typename DF8, typename DF9,
        typename DF10 
        >
    void deserialize(
        one_vs_all_decision_function<T,DF1,DF2,DF3,DF4,DF5,DF6,DF7,DF8,DF9,DF10>& item, 
        std::istream& in 
    );
    /*!
        ensures
            - deserializes a one_vs_all_decision_function from in and stores it in item.
        throws
            - serialization_error.  
              This is thrown if there is a problem reading from the istream or if the
              serialized data contains decision functions not listed among the DF*
              template arguments.
    !*/

// ----------------------------------------------------------------------------------------

}

#endif // DLIB_ONE_VS_ALL_DECISION_FUnCTION_ABSTRACT_H__