/*!
  \file
  \brief Bayesian Filtering for extensions of autoregressive (ARX) model
  \author Vaclav Smidl.

*/

#ifndef AREX_H
#define AREX_H

#include "../math/functions.h"
#include "arx.h"

namespace bdm {

/*!
* \brief Non-linear transformation + Gaussian noise

Regression of the following kind:
\f[
y_t = g(\psi_t ) + r e_t
\f]
where unknown parameters \c rv are \f$[r]\f$, regression vector \f$\psi_t=\psi(y_{1:t},u_{1:t})\f$ is propagated through a known function \c g. Distrubances \f$e_t\f$ are supposed to be normally distributed:
\f[
e_t \sim \mathcal{N}(0,1).
\f]

*/
class ARXg: public ARX {
protected:
    //! function g
    shared_ptr<fnc> g;
public:
    //! \name Constructors
    //!@{
    ARXg (): ARX() {}
    ARXg (const ARXg &A0): ARX(A0),g(A0.g) {}
    ARXg* _copy() const {
        return new ARXg(*this);
    }
    //!@}

    //!\name Mathematical operations
    //!@{

    //! Weighted Bayes \f$ dt = [y_t psi_t] \f$.
    void bayes_weighted ( const vec &yt, const vec &cond = empty_vec, const double w = 1.0 ) {
        int dimc_store =dimc;
        dimc =0;
		int rgrlen_store = rgrlen;
		rgrlen =0;
        ARX::bayes_weighted(yt - g->eval(cond), empty_vec, w);
        dimc = dimc_store;
		rgrlen=rgrlen_store;
    };
    //!@}

    /*! UI for ARXg estimator

    \code
    class = 'ARXg';
    yrv   = RV({names_of_dt} )                 // description of output variables
    rgr   = RV({names_of_regressors}, [-1,-2]} // description of regressor variables
    constant = 1;                              // 0/1 switch if the constant term is modelled or not
    g     = {class='my_function',...}          // function transforming regressor

    --- optional ---
    prior = {class='egiw',...};                // Prior density, when given default is used instead
    alternative = {class='egiw',...};          // Alternative density in stabilized estimation, when not given prior is used

    frg   = 1.0;                               // forgetting, default frg=1.0

    rv    = RV({names_of_parameters}}          // description of parametetr names
    \endcode
    */
    void from_setting ( const Setting &set ) {
        ARX::from_setting(set);
        g=UI::build<fnc>(set,"g",UI::compulsory);
    }

    void validate() {
        ARX::validate();//if dimc not set set it from V
        bdm_assert(g->dimension()==dimensiony(),"incompatible g");
        bdm_assert(g->dimensionc()==dimensionc(),"incompatible g");
    }

    void to_setting ( Setting &set ) const
    {
        ARX::to_setting( set ); // takes care of rv, yrv, rvc
        UI::save(g,set,"g");
    }
};
UIREGISTER ( ARXg );
SHAREDPTR ( ARXg );

};
#endif // AREX_H


