root/library/bdm/estim/arx.h @ 1383

Revision 1383, 12.6 kB (checked in by sindj, 13 years ago)

Program update, kontrola vypoctu provedena, integruje spravne v nedegenerovanem pripade. JS

  • Property svn:eol-style set to native
Line 
1/*!
2  \file
3  \brief Bayesian Filtering for generalized autoregressive (ARX) model
4  \author Vaclav Smidl.
5
6  -----------------------------------
7  BDM++ - C++ library for Bayesian Decision Making under Uncertainty
8
9  Using IT++ for numerical operations
10  -----------------------------------
11*/
12
13#ifndef AR_H
14#define AR_H
15
16#include "../math/functions.h"
17#include "../stat/exp_family.h"
18#include "../base/user_info.h"
19//#include "../estim/kalman.h"
20#include "arx_straux.h"
21
22namespace bdm {
23
24/*!
25* \brief Linear Autoregressive model with Gaussian noise
26
27Regression of the following kind:
28\f[
29y_t =     heta_1 \psi_1 +     heta_2 + \psi_2 +\ldots +     heta_n \psi_n + r e_t
30\f]
31where unknown parameters \c rv are \f$[    heta r]\f$, regression vector \f$\psi=\psi(y_{1:t},u_{1:t})\f$ is a known function of past outputs and exogeneous variables \f$u_t\f$. Distrubances \f$e_t\f$ are supposed to be normally distributed:
32\f[
33e_t \sim \mathcal{N}(0,1).
34\f]
35
36See \ref tut_arx for mathematical treatment.
37
38The easiest way how to use the class is:
39\include arx_simple.cpp
40
41            odo sort out constant terms - bayes should accept vec without additional 1s
42*/
43class ARX: public BMEF {
44protected:
45    //! switch if constant is modelled or not
46    bool have_constant;
47    //! vector of dyadic update
48    vec dyad;
49    //! RV of regressor
50    RV rgr;
51    //! length of the regressor (without optional constant)
52    int rgrlen;
53    //! posterior density
54    egiw est;
55    //! Alternative estimate of parameters, used in stabilized forgetting, see [Kulhavy]
56    egiw alter_est;
57public:
58    //! \name Constructors
59    //!@{
60    ARX ( const double frg0 = 1.0 ) : BMEF ( frg0 ),  have_constant ( true ), dyad(), rgrlen(),est(), alter_est() {};
61    ARX ( const ARX &A0 ) : BMEF ( A0 ),  have_constant ( A0.have_constant ), dyad ( A0.dyad ),rgrlen(A0.rgrlen), est ( A0.est ), alter_est ( A0.alter_est ) { };
62
63    ARX* _copy() const; 
64
65    void set_frg ( double frg0 ) {
66        frg = frg0;
67    }
68    void set_constant ( bool const0 ) {
69        have_constant = const0;
70    }
71    void set_statistics ( int dimy0, const ldmat V0, double nu0 = -1.0 ) {
72        est.set_parameters ( dimy0, V0, nu0 );
73        est.validate();
74        last_lognc = est.lognc();
75        dimy = dimy0;
76    }
77    //!@}
78
79    //! Set sufficient statistics
80    void set_statistics ( const BMEF* BM0 );
81
82    //!\name Mathematical operations
83    //!@{
84
85    //! Weighted Bayes \f$ dt = [y_t psi_t] \f$.
86    void bayes_weighted ( const vec &yt, const vec &cond = empty_vec, const double w = 1.0 );
87    void bayes ( const vec &yt, const vec &cond = empty_vec ) {
88        bayes_weighted ( yt, cond, 1.0 );
89    };
90        double logpred ( const vec &yt, const vec &cond ) const;
91        vec samplepred (  const vec &cond ) ;
92        void flatten ( const BMEF* B , double weight );
93    //! Conditioned version of the predictor
94    enorm<ldmat>* epredictor ( const vec &rgr ) const;
95        estudent<ldmat>* epredictor_student ( const vec &rgr ) const;
96        //! conditional version of the predictor
97    template<class sq_T>
98    shared_ptr<mlnorm<sq_T> > ml_predictor() const;
99    //! fast version of predicto
100    template<class sq_T>
101    void ml_predictor_update ( mlnorm<sq_T> &pred ) const;
102    mlstudent* predictor() const;
103    //! Brute force structure estimation.\return indices of accepted regressors.
104    ivec structure_est ( const egiw &Eg0 );
105    //! Smarter structure estimation by Ludvik Tesar.\return indices of accepted regressors.
106    ivec structure_est_LT ( const egiw &Eg0 );
107    //! reduce structure to the given ivec of matrix V
108    void reduce_structure(ivec &inds_in_V) {
109        ldmat V = posterior()._V();
110        if (max(inds_in_V)>=V.rows()) {
111            bdm_error("Incompatible structure");
112        }
113
114        ldmat newV(V,inds_in_V);
115        est.set_parameters(dimy,newV, posterior()._nu());
116
117        if (have_constant) {
118            ivec rgr_elem= find(inds_in_V<(V.rows()-1)); // < -- find non-constant
119            rgr = rgr.subselect(rgr_elem);
120            rgrlen = rgr_elem.length();
121        } else {
122            rgr = rgr.subselect(inds_in_V);
123        }
124        validate();
125    }
126    //!@}
127
128    //!\name Access attributes
129    //!@{
130    //! return correctly typed posterior (covariant return)
131    const egiw& posterior() const {
132        return est;
133    }
134    //!@}
135
136    /*! Create object from the following structure
137
138    \code
139    class = 'ARX';
140    rgr = RV({'names',...},[sizes,...],[times,...]);   % description of regressor variables
141    --- optional fields ---   
142    prior = configuration of bdm::egiw;                % any offspring of eqiw for prior density, bdm::egiw::from_setting
143    alternative = configuration of bdm::egiw;          % any offspring of eqiw for alternative density in stabilized estimation of prior density   
144    constant = [];                                     % 0/1 switch if the constant term is modelled or not
145    --- inherited fields ---
146    bdm::BMEF::from_setting
147    \endcode
148    If the optional fields are not given, they will be filled as follows:
149    \code
150    prior = posterior;                                % when prior is not given the posterior is used (TODO it is unclear)
151    alternative = prior;                              % when alternative is not given the prior is used
152    constant = 1;                                     % constant term is modelled on default
153    \endcode
154    */
155    void from_setting ( const Setting &set );
156
157    void validate() {
158        BMEF::validate();
159        est.validate();
160
161        // When statistics is defined, it has priority
162        if(posterior()._dimx()>0) {//statistics is assigned
163            dimy = posterior()._dimx();
164            rgrlen=posterior()._V().rows() - dimy - int ( have_constant == true );
165            dimc = rgrlen;
166        } else { // statistics is not assigned - build it from dimy and rgrlen
167            bdm_assert(dimy>0,"No way to validate egiw: empty statistics and empty dimy");
168            est.set_parameters(dimy, zeros(dimy+rgrlen+int(have_constant==true)));
169            set_prior_default(est);
170        }
171        if (alter_est.dimension()==0) alter_est=est;
172
173        dyad = ones ( est._V().rows() );
174    }
175    //! function sets prior and alternative density
176    void set_prior ( const epdf *prior );
177    //! build default prior and alternative when all values are set
178    void set_prior_default ( egiw &prior ) {
179        //assume
180        vec dV0 ( prior._V().rows() );
181        dV0.set_subvector ( 0, prior._dimx() - 1, 1.0 );
182        if (dV0.length()>prior._dimx())
183            dV0.set_subvector ( prior._dimx(), dV0.length() - 1, 1e-5 );
184
185        prior.set_parameters ( prior._dimx(), ldmat ( dV0 ) );
186        prior.validate();
187    }
188
189    void to_setting ( Setting &set ) const
190    {
191        BMEF::to_setting( set ); // takes care of rv, yrv, rvc
192        UI::save(rgr, set, "rgr");
193        int constant = have_constant ? 1 : 0;
194        UI::save(constant, set, "constant");
195        UI::save(&alter_est, set, "alternative");
196        UI::save(&posterior(), set, "posterior");
197
198    }
199    //! access function
200    RV & _rgr() {
201        return rgr;
202    }
203    bool _have_constant() {
204        return have_constant;
205    }
206    int _rgrlen() {
207        return rgrlen;
208    }
209};
210UIREGISTER ( ARX );
211SHAREDPTR ( ARX );
212
213//! \brief ARX moidel with parameters in LS form
214class ARXls : public BMEF{
215  public:
216        egw_ls<ldmat> est;
217       
218        egw_ls<ldmat> alternative;
219       
220        const egw_ls<ldmat>& posterior() {return est;};
221       
222        void bayes(const vec &dt, const vec &psi){
223//        ldmat &Pbeta = est.P;
224//        ldmat &Palpha = alternative.P;
225         
226         
227        }
228};
229
230/*! \brief ARX model conditined by knowledge of the forgetting factor
231\f[ f(    heta| d_1 \ldots d_t , \phi_t) \f]
232
233The symbol \f$ \phi \f$ is assumed to be the last of the conditioning variables.
234*/
235class ARXfrg : public ARX {
236public:
237    ARXfrg() : ARX() {};
238    //! copy constructor
239    ARXfrg ( const ARXfrg &A0 ) : ARX ( A0 ) {};
240    virtual ARXfrg* _copy() const {
241        ARXfrg *A = new ARXfrg ( *this );
242        return A;
243    }
244
245    void bayes ( const vec &val, const vec &cond ) {
246        bdm_assert_debug(cond.size()>rgrlen, "ARXfrg: Insufficient conditioning, frg not given.");
247        frg = cond ( rgrlen); // the first part after rgrlen
248        ARX::bayes ( val, cond.left(rgrlen) );
249    }
250    void validate() {
251        ARX::validate();
252        rvc.add ( RV ( "{phi }", vec_1 ( 1 ) ) );
253        dimc += 1;
254    }
255};
256UIREGISTER ( ARXfrg );
257
258/*! \brief ARX model with fixed maxent forgetting on increments,
259 * \f[ f(    heta| d_1 \ldots d_t , \phi_t) \f]
260 *
261 * The symbol \f$ \phi \f$ is not interpreted as exponentila forgetting but foreggting of incoming data!!
262 */
263class ARXmaxent : public ARX {
264protected:
265        double maxent_frg;
266public:
267        ARXmaxent() : ARX() {};
268        //! copy constructor
269        ARXmaxent ( const ARXmaxent &A0 ) : ARX ( A0 ),maxent_frg(A0.maxent_frg) {};
270        virtual ARXmaxent* _copy() const {
271                ARXmaxent *A = new ARXmaxent ( *this );
272                return A;
273        }
274       
275        void bayes ( const vec &val, const vec &cond ) {
276                ARX::bayes_weighted ( val, cond, maxent_frg );
277        }
278        void from_setting(const Setting &set){
279                ARX::from_setting(set);
280                maxent_frg=frg;
281                frg = 1.0;
282        }
283};
284       
285UIREGISTER ( ARXmaxent );
286
287/*! \brief ARX model with fixed-length window - old entries are removed
288 * \f[ f(    heta| d_1 \ldots d_t) \f]
289 *
290 */
291class ARXwin : public ARX {
292protected:
293        mat Y;
294        mat Cond;
295       
296        int win_length;
297        ldmat V0;
298        double nu0;
299public:
300        ARXwin() : ARX() {};
301        //! copy constructor
302        void set_parameters(const int win_length0){ 
303                win_length=win_length0;
304        }
305        ARXwin ( const ARXwin &A0 ) : ARX(A0), Y( A0.Y), Cond(A0.Cond) {};
306       
307        virtual ARXwin* _copy() const {
308                ARXwin *A = new ARXwin ( *this );
309                return A;
310        }
311       
312        void bayes ( const vec &val, const vec &cond ) {
313               
314                if(cond.size()>0)
315                {
316                        // fill window
317                        Y.append_col(val);
318                        Cond.append_col(cond);         
319                        if (Y.cols()>win_length){
320                                // shift the buffer
321                                Y=Y.get_cols(1,Y.cols()-1);
322                                Cond=Cond.get_cols(1,Cond.cols()-1);
323                        }
324                       
325                        est._V()=V0;
326                        est._nu()=nu0;
327                        for ( int t = 0; t < Y.cols(); t++ ) {
328                                ARX::bayes ( Y.get_col ( t ), Cond.get_col ( t ) );
329                        }
330                }
331                else
332                {
333                        Y.append_col(val);
334
335                        if (Y.cols()>win_length){
336                                // shift the buffer
337                                Y=Y.get_cols(1,Y.cols()-1);                             
338                        }
339
340                        est._V()=V0;
341                        est._nu()=nu0;
342
343                        for ( int t = 0; t < Y.cols(); t++ ) {
344                                ARX::bayes (Y.get_col ( t ));
345                        }
346                }
347               
348        }
349
350        void from_setting(const Setting &set){
351                ARX::from_setting(set);
352                UI::get(win_length,set,"win_length",UI::compulsory);
353        }
354        void validate() {
355                ARX::validate();
356                V0=est._V();
357                nu0=est._nu();
358        }
359};
360       
361UIREGISTER ( ARXwin );
362       
363
364
365/*! \brief ARX with partial forgetting
366
367Implements partial forgetting when <tt>bayes(const vec &yt, const vec &cond=empty_vec)</tt> is called, where \c cond is a vector <em>(regressor', forg.factor')</em>.
368
369Note, that the weights have the same order as hypotheses in partial forgetting, and follow this scheme:
370\li 0 means that the parameter doesn't change,
371\li 1 means that the parameter varies.
372
373The combinations of parameters are described binary:
374\f{bmatrix}[
375  0 & 0 & 0 & \ldots \\
376  1 & 0 & 0 & \ldots \\
377  0 & 1 & 0 & \ldots \\
378  1 & 1 & 0 & \ldots \\
379  \vdots & \vdots & \vdots & \vdots
380\f{bmatrix}]
381Notice, that each n-th column has altering n-tuples of 1's and 0's, n = 0,...,number of params. Hence, the first forg. factor relates to the situation when no parameter changes, the second one when the first parameter changes etc.
382
383See ARX class for more information about ARX.
384*/
385class ARXpartialforg : public ARX {
386public:
387    ARXpartialforg() : ARX(1.0) {};
388    //! copy constructor
389    ARXpartialforg ( const ARXpartialforg &A0 ) : ARX ( A0 ) {};
390    virtual ARXpartialforg* _copy() const {
391        ARXpartialforg *A = new ARXpartialforg ( *this );
392        return A;
393    }
394
395    void bayes ( const vec &val, const vec &cond );
396
397    void validate() {
398        ARX::validate();
399        int philen = 1 << (est._V().cols() - 1);
400        rvc.add ( RV ( "{phi }", vec_1(philen) ) ); // pocet 2^parametru
401        dimc += philen;
402    }
403};
404UIREGISTER ( ARXpartialforg );
405
406
407////////////////////
408template<class sq_T>
409shared_ptr< mlnorm<sq_T> > ARX::ml_predictor ( ) const {
410    shared_ptr< mlnorm<sq_T> > tmp = new mlnorm<sq_T> ( );
411    tmp->set_rv ( yrv );
412    tmp->set_rvc ( _rvc() );
413
414    ml_predictor_update ( *tmp );
415    tmp->validate();
416    return tmp;
417}
418
419template<class sq_T>
420void ARX::ml_predictor_update ( mlnorm<sq_T> &pred ) const {
421    mat mu ( dimy, posterior()._V().rows() - dimy );
422    mat R ( dimy, dimy );
423
424    est.mean_mat ( mu, R ); //mu =
425    mu = mu.T();
426    //correction for student-t  -- TODO check if correct!!
427
428    if ( have_constant ) { // constant term
429        //Assume the constant term is the last one:
430        pred.set_parameters ( mu.get_cols ( 0, mu.cols() - 2 ), mu.get_col ( mu.cols() - 1 ), sq_T ( R ) );
431    } else {
432        pred.set_parameters ( mu, zeros ( dimy ), sq_T ( R ) );
433    }
434}
435
436};
437#endif // AR_H
438
Note: See TracBrowser for help on using the browser.