/*!
  \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;
		ARX::bayes_weighted(yt - g->eval(cond), empty_vec, w);
		dimc = dimc_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


