root/library/bdm/estim/particles.h @ 1193

Revision 1192, 27.0 kB (checked in by smidl, 14 years ago)

fixes ob ProdBM

  • Property svn:eol-style set to native
Line 
1/*!
2  \file
3  \brief Bayesian Filtering using stochastic sampling (Particle Filters)
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 PARTICLES_H
14#define PARTICLES_H
15
16
17#include "../estim/arx_ext.h"
18#include "../stat/emix.h"
19
20namespace bdm {
21
22//! \brief Abstract class for Marginalized Particles
23class MarginalizedParticleBase : public BM {
24protected:
25    //! discrte particle
26    dirac est_emp;
27    //! internal Bayes Model
28    shared_ptr<BM> bm;
29
30    //! \brief Internal class for custom posterior - product of empirical and exact part
31    class eprod_2:public eprod_base {
32    protected:
33        MarginalizedParticleBase &mp;
34    public:
35                eprod_2(MarginalizedParticleBase &m):mp(m) {}
36                const epdf* factor(int i) const {
37            return (i==0) ? &mp.bm->posterior() : &mp.est_emp;
38        }
39        const int no_factors() const {
40            return 2;
41        }
42    } est;
43
44public:
45    MarginalizedParticleBase():est(*this) {};
46    MarginalizedParticleBase(const MarginalizedParticleBase &m2):BM(m2),est(*this) {
47        bm = m2.bm->_copy();
48        est_emp = m2.est_emp;
49        est.validate();
50        validate();
51    };
52    void bayes(const vec &dt, const vec &cond) NOT_IMPLEMENTED_VOID;
53
54    const eprod_2& posterior() const {
55        return est;
56    }
57
58    void set_prior(const epdf *pdf0) {
59        const eprod *ep=dynamic_cast<const eprod*>(pdf0);
60        if (ep) { // full prior
61            bdm_assert(ep->no_factors()==2,"Incompatible prod");
62            bm->set_prior(ep->factor(0));
63            est_emp.set_point(ep->factor(1)->sample());
64        } else {
65            // assume prior is only for emp;
66            est_emp.set_point(pdf0->sample());
67        }
68    }
69
70
71    /*! Create object from the following structure
72
73    \code
74    class = "MarginalizedParticleBase";
75    bm = configuration of bdm::BM;          % any offspring of BM, bdm::BM::from_setting
76    --- inherited fields ---
77    bdm::BM::from_setting
78    \endcode
79    */
80    void from_setting(const Setting &set) {
81        BM::from_setting ( set );
82        bm = UI::build<BM> ( set, "bm", UI::compulsory );
83    }
84    void validate() {
85        BM::validate();
86        //est.validate(); --pdfs not known
87        bdm_assert(bm,"Internal BM is not given");
88    }
89};
90
91//! \brief Particle with marginalized subspace, used in PF
92class MarginalizedParticle : public MarginalizedParticleBase {
93protected:
94    //! pdf with for transitional par
95    shared_ptr<pdf> par; // pdf for non-linear part
96    //! link from this to bm
97    shared_ptr<datalink_part> cond2bm;
98    //! link from cond to par
99    shared_ptr<datalink_part> cond2par;
100    //! link from emp 2 par
101    shared_ptr<datalink_part> emp2bm;
102    //! link from emp 2 par
103    shared_ptr<datalink_part> emp2par;
104
105public:
106    BM* _copy() const {
107        return new MarginalizedParticle(*this);
108    };
109    void bayes(const vec &dt, const vec &cond) {
110        vec par_cond(par->dimensionc());
111        cond2par->filldown(cond,par_cond); // copy ut
112        emp2par->filldown(est_emp._point(),par_cond); // copy xt-1
113
114        //sample new particle
115        est_emp.set_point(par->samplecond(par_cond));
116        //if (evalll)
117        vec bm_cond(bm->dimensionc());
118        cond2bm->filldown(cond, bm_cond);// set e.g. ut
119        emp2bm->filldown(est_emp._point(), bm_cond);// set e.g. ut
120        bm->bayes(dt, bm_cond);
121        ll=bm->_ll();
122    }
123
124    /*! Create object from the following structure
125
126    \code
127    class = "MarginalizedParticle";
128    parameter_pdf = configuration of bdm::epdf;          % any offspring of epdf, bdm::epdf::from_setting
129    --- inherited fields ---
130    bdm::MarginalizedParticleBase::from_setting
131    \endcode
132    */   
133    void from_setting(const Setting &set) {
134        MarginalizedParticleBase::from_setting ( set );
135        par = UI::build<pdf> ( set, "parameter_pdf", UI::compulsory );
136    }
137
138    void to_setting(Setting &set)const {
139        MarginalizedParticleBase::to_setting(set);
140        UI::save(par,set,"parameter_pdf");
141                UI::save(bm,set,"bm");
142    }
143    void validate() {
144        MarginalizedParticleBase::validate();
145        est_emp.set_rv(par->_rv());
146        if (est_emp.point.length()!=par->dimension())
147            est_emp.set_point(zeros(par->dimension()));
148        est.validate();
149
150        yrv = bm->_yrv();
151        dimy = bm->dimensiony();
152        set_rv( concat(bm->_rv(), par->_rv()));
153        set_dim( par->dimension()+bm->dimension());
154
155        rvc = par->_rvc();
156        rvc.add(bm->_rvc());
157        rvc=rvc.subt(par->_rv());
158        rvc=rvc.subt(par->_rv().copy_t(-1));
159        rvc=rvc.subt(bm->_rv().copy_t(-1)); //
160
161        cond2bm=new datalink_part;
162        cond2par=new datalink_part;
163        emp2bm  =new datalink_part;
164        emp2par =new datalink_part;
165        cond2bm->set_connection(bm->_rvc(), rvc);
166        cond2par->set_connection(par->_rvc(), rvc);
167        emp2bm->set_connection(bm->_rvc(), par->_rv());
168        emp2par->set_connection(par->_rvc(), par->_rv().copy_t(-1));
169
170        dimc = rvc._dsize();
171    };
172};
173UIREGISTER(MarginalizedParticle);
174
175//! Internal class which is used in PF
176class BootstrapParticle : public BM {
177    dirac est;
178    shared_ptr<pdf> par;
179    shared_ptr<pdf> obs;
180    shared_ptr<datalink_part> cond2par;
181    shared_ptr<datalink_part> cond2obs;
182    shared_ptr<datalink_part> xt2obs;
183    shared_ptr<datalink_part> xtm2par;
184public:
185    BM* _copy() const {
186        return new BootstrapParticle(*this);
187    };
188    void bayes(const vec &dt, const vec &cond) {
189        vec par_cond(par->dimensionc());
190        cond2par->filldown(cond,par_cond); // copy ut
191        xtm2par->filldown(est._point(),par_cond); // copy xt-1
192
193        //sample new particle
194        est.set_point(par->samplecond(par_cond));
195        //if (evalll)
196        vec obs_cond(obs->dimensionc());
197        cond2obs->filldown(cond, obs_cond);// set e.g. ut
198        xt2obs->filldown(est._point(), obs_cond);// set e.g. ut
199        ll=obs->evallogcond(dt,obs_cond);
200    }
201    const dirac& posterior() const {
202        return est;
203    }
204
205    void set_prior(const epdf *pdf0) {
206        est.set_point(pdf0->sample());
207    }
208
209    /*! Create object from the following structure
210    \code
211    class = "BootstrapParticle";
212    parameter_pdf = configuration of bdm::epdf;      % any offspring of epdf, bdm::epdf::from_setting
213    observation_pdf = configuration of bdm::epdf;    % any offspring of epdf, bdm::epdf::from_setting
214    --- inherited fields ---
215    bdm::BM::from_setting
216    \endcode
217    */
218    void from_setting(const Setting &set) {
219        BM::from_setting ( set );
220        par = UI::build<pdf> ( set, "parameter_pdf", UI::compulsory );
221        obs = UI::build<pdf> ( set, "observation_pdf", UI::compulsory );
222    }
223
224    void validate() {
225        yrv = obs->_rv();
226        dimy = obs->dimension();
227        set_rv( par->_rv());
228        set_dim( par->dimension());
229
230        rvc = par->_rvc().subt(par->_rv().copy_t(-1));
231        rvc.add(obs->_rvc()); //
232
233        cond2obs=new datalink_part;
234        cond2par=new datalink_part;
235        xt2obs  =new datalink_part;
236        xtm2par =new datalink_part;
237        cond2obs->set_connection(obs->_rvc(), rvc);
238        cond2par->set_connection(par->_rvc(), rvc);
239        xt2obs->set_connection(obs->_rvc(), _rv());
240        xtm2par->set_connection(par->_rvc(), _rv().copy_t(-1));
241
242        dimc = rvc._dsize();
243    };
244};
245UIREGISTER(BootstrapParticle);
246
247
248/*!
249* \brief Trivial particle filter with proposal density equal to parameter evolution model.
250
251Posterior density is represented by a weighted empirical density (\c eEmp ).
252*/
253
254class PF : public BM {
255    //! \var log_level_enums logweights
256    //! all weightes will be logged
257
258    //! \var log_level_enums logmeans
259    //! means of particles will be logged
260    LOG_LEVEL(PF,logweights,logmeans,logvars);
261
262    class pf_mix: public emix_base {
263        Array<BM*> &bms;
264    public:
265        pf_mix(vec &w0, Array<BM*> &bms0):emix_base(w0),bms(bms0) {}
266        const epdf* component(const int &i)const {
267            return &(bms(i)->posterior());
268        }
269        int no_coms() const {
270            return bms.length();
271        }
272    };
273protected:
274    //!number of particles;
275    int n;
276    //!posterior density
277    pf_mix est;
278    //! weights;
279    vec w;
280    //! particles
281    Array<BM*> particles;
282    //! internal structure storing loglikelihood of predictions
283    vec lls;
284
285    //! which resampling method will be used
286    RESAMPLING_METHOD resmethod;
287    //! resampling threshold; in this case its meaning is minimum ratio of active particles
288    //! For example, for 0.5 resampling is performed when the numebr of active aprticles drops belo 50%.
289    double res_threshold;
290
291    //! \name Options
292    //!@{
293    //!@}
294
295public:
296    //! \name Constructors
297    //!@{
298    PF ( ) : est(w,particles) { };
299
300    void set_parameters ( int n0, double res_th0 = 0.5, RESAMPLING_METHOD rm = SYSTEMATIC ) {
301        n = n0;
302        res_threshold = res_th0;
303        resmethod = rm;
304    };
305    void set_model ( const BM *particle0, const epdf *prior) {
306        if (n>0) {
307            particles.set_length(n);
308            for (int i=0; i<n; i++) {
309                particles(i) = particle0->_copy();
310                particles(i)->set_prior(prior);
311            }
312        }
313        // set values for posterior
314        est.set_rv ( particle0->posterior()._rv() );
315    };
316    void set_statistics ( const vec w0, const epdf &epdf0 ) {
317        //est.set_statistics ( w0, epdf0 );
318    };
319    /*    void set_statistics ( const eEmp &epdf0 ) {
320            bdm_assert_debug ( epdf0._rv().equal ( par->_rv() ), "Incompatible input" );
321            est = epdf0;
322        };*/
323    //!@}
324
325    //! bayes compute weights of the
326    virtual void bayes_weights();
327    //! important part of particle filtering - decide if it is time to perform resampling
328    virtual bool do_resampling() {
329        double eff = 1.0 / ( w * w );
330        return eff < ( res_threshold*n );
331    }
332    void bayes ( const vec &yt, const vec &cond );
333    //!access function
334    vec& _lls() {
335        return lls;
336    }
337    //!access function
338    RESAMPLING_METHOD _resmethod() const {
339        return resmethod;
340    }
341    //! return correctly typed posterior (covariant return)
342    const pf_mix& posterior() const {
343        return est;
344    }
345
346    /*! configuration structure for basic PF
347    \code
348    particle        = bdm::BootstrapParticle;       % one bayes rule for each point in the empirical support
349      - or -        = bdm::MarginalizedParticle;    % (in case of Marginalized Particle filtering
350    prior           = epdf_class;                   % prior probability density on the empirical variable
351    --- optional ---
352    n               = 10;                           % number of particles
353    resmethod       = 'systematic', or 'multinomial', or 'stratified'
354                                                    % resampling method
355    res_threshold   = 0.5;                          % resample when active particles drop below 50%
356    \endcode
357    */
358    void from_setting ( const Setting &set ) {
359        BM::from_setting ( set );
360        UI::get ( log_level, set, "log_level", UI::optional );
361
362        shared_ptr<BM> bm0 = UI::build<BM>(set, "particle",UI::compulsory);
363
364        n =0;
365        UI::get(n,set,"n",UI::optional);;
366        if (n>0) {
367            particles.set_length(n);
368            for(int i=0; i<n; i++) {
369                particles(i)=bm0->_copy();
370            }
371            w = ones(n)/n;
372        }
373        shared_ptr<epdf> pri = UI::build<epdf>(set,"prior");
374        set_prior(pri.get());
375        // set resampling method
376        resmethod_from_set ( set );
377        //set drv
378
379        rvc = bm0->_rvc();
380        dimc = bm0->dimensionc();
381        BM::set_rv(bm0->_rv());
382        yrv=bm0->_yrv();
383        dimy = bm0->dimensiony();
384    }
385   
386    void to_setting(Setting &set) const{
387                BM::to_setting(set);
388                UI::save(particles, set,"particles");
389                UI::save(w,set,"w");
390        }
391
392    void log_register ( bdm::logger& L, const string& prefix ) {
393        BM::log_register(L,prefix);
394        if (log_level[logweights]) {
395            L.add_vector( log_level, logweights, RV ( particles.length()), prefix);
396        }
397        if (log_level[logmeans]) {
398            for (int i=0; i<particles.length(); i++) {
399                L.add_vector( log_level, logmeans, RV ( particles(i)->dimension() ), prefix , i);
400            }
401        }
402        if (log_level[logvars]) {
403            for (int i=0; i<particles.length(); i++) {
404                L.add_vector( log_level, logvars, RV ( particles(i)->dimension() ), prefix , i);
405            }
406        }
407    };
408    void log_write ( ) const {
409        BM::log_write();
410                // weigths are before resamplign -- bayes
411        if (log_level[logmeans]) {
412            for (int i=0; i<particles.length(); i++) {
413                log_level.store( logmeans, particles(i)->posterior().mean(), i);
414            }
415        }
416        if (log_level[logvars]) {
417            for (int i=0; i<particles.length(); i++) {
418                log_level.store( logvars, particles(i)->posterior().variance(), i);
419            }
420        }
421
422    }
423
424    void set_prior(const epdf *pri) {
425        const emix_base *emi=dynamic_cast<const emix_base*>(pri);
426        if (emi) {
427            bdm_assert(particles.length()>0, "initial particle is not assigned");
428            n = emi->_w().length();
429            int old_n = particles.length();
430            if (n!=old_n) {
431                particles.set_length(n,true);
432            }
433            for(int i=old_n; i<n; i++) {
434                particles(i)=particles(0)->_copy();
435            }
436
437            for (int i =0; i<n; i++) {
438                particles(i)->set_prior(emi->_com(i));
439            }
440        } else {
441            // try to find "n"
442            bdm_assert(n>0, "Field 'n' must be filled when prior is not of type emix");
443            for (int i =0; i<n; i++) {
444                particles(i)->set_prior(pri);
445            }
446
447        }
448    }
449    //! auxiliary function reading parameter 'resmethod' from configuration file
450    void resmethod_from_set ( const Setting &set ) {
451        string resmeth;
452        if ( UI::get ( resmeth, set, "resmethod", UI::optional ) ) {
453            if ( resmeth == "systematic" ) {
454                resmethod = SYSTEMATIC;
455            } else  {
456                if ( resmeth == "multinomial" ) {
457                    resmethod = MULTINOMIAL;
458                } else {
459                    if ( resmeth == "stratified" ) {
460                        resmethod = STRATIFIED;
461                    } else {
462                        bdm_error ( "Unknown resampling method" );
463                    }
464                }
465            }
466        } else {
467            resmethod = SYSTEMATIC;
468        };
469        if ( !UI::get ( res_threshold, set, "res_threshold", UI::optional ) ) {
470            res_threshold = 0.9;
471        }
472        //validate();
473    }
474
475    void validate() {
476        BM::validate();
477        est.validate();
478        bdm_assert ( n>0, "empty particle pool" );
479        n = w.length();
480        lls = zeros ( n );
481
482        if ( particles(0)->_rv()._dsize() > 0 ) {
483            bdm_assert (  particles(0)->_rv()._dsize() == est.dimension(), "MPF:: Mismatch of RV " +particles(0)->_rv().to_string() +
484                          " of size (" +num2str(particles(0)->_rv()._dsize())+") and dimension of posterior ("+num2str(est.dimension()) + ")" );
485        }
486    }
487    //! resample posterior density (from outside - see MPF)
488    void resample ( ) {
489        ivec ind = zeros_i ( n );
490        bdm::resample(w,ind,resmethod);
491        // copy the internals according to ind
492        for (int i = 0; i < n; i++ ) {
493            if ( ind ( i ) != i ) {
494                delete particles(i);
495                particles( i ) = particles( ind ( i ) )->_copy();
496            }
497            w ( i ) = 1.0 / n;
498        }
499    }
500    //! access function
501    Array<BM*>& _particles() {
502        return particles;
503    }
504    ~PF() {
505        for (int i=0; i<particles.length(); i++) {
506            delete particles(i);
507        }
508    }
509
510};
511UIREGISTER ( PF );
512
513/*! Marginalized particle for state-space models with unknown parameters of distribuution of residues on \f$v_t\f$.
514
515\f{eqnarray*}{
516    x_t &=& g(x_{t-1}) + v_t,\\
517    y_t &\sim &fy(x_t),
518    \f}
519
520    This particle is a only a shell creating the residues calling internal estimator of their parameters. The internal estimator can be of any compatible type, e.g. ARX for Gaussian residues with unknown mean and variance.
521
522    */
523class NoiseParticleX : public MarginalizedParticleBase {
524protected:
525    //! function transforming xt, ut -> x_t+1
526    shared_ptr<fnc> g; // pdf for non-linear part
527    //! function transforming xt,ut -> yt
528    shared_ptr<pdf> fy; // pdf for non-linear part
529
530    RV rvx;
531    RV rvxc;
532    RV rvyc;
533
534    //!link from condition to f
535    datalink_part cond2g;
536    //!link from condition to h
537    datalink_part cond2fy;
538    //!link from xt to f
539    datalink_part x2g;
540    //!link from xt to h
541    datalink_part x2fy;
542
543public:
544    BM* _copy() const {
545        return new NoiseParticleX(*this);
546    };
547    void bayes(const vec &dt, const vec &cond) {
548        //shared_ptr<epdf> pred_v=bm->epredictor();
549
550        //vec vt=pred_v->sample();
551                vec vt = bm->samplepred();
552
553        //new sample
554        vec &xtm=est_emp.point;
555        vec g_args(g->dimensionc());
556        x2g.filldown(xtm,g_args);
557        cond2g.filldown(cond,g_args);
558        vec xt = g->eval(g_args) + vt;
559        est_emp.point=xt;
560
561        // the vector [v_t] updates bm,
562        bm->bayes(vt);
563
564        // residue of observation
565        vec fy_args(fy->dimensionc());
566        x2fy.filldown(xt,fy_args);
567        cond2fy.filldown(cond,fy_args);
568
569        ll= fy->evallogcond(dt,fy_args);
570    }
571    void from_setting(const Setting &set) {
572        MarginalizedParticleBase::from_setting(set); //reads bm, yrv,rvc, bm_rv, etc...
573
574        g=UI::build<fnc>(set,"g",UI::compulsory);
575        fy=UI::build<pdf>(set,"fy",UI::compulsory);
576        UI::get(rvx,set,"rvx",UI::compulsory);
577        est_emp.set_rv(rvx);
578
579        UI::get(rvxc,set,"rvxc",UI::compulsory);
580        UI::get(rvyc,set,"rvyc",UI::compulsory);
581
582    }
583    void to_setting (Setting &set) const {
584                MarginalizedParticleBase::to_setting(set); //reads bm, yrv,rvc, bm_rv, etc...
585                UI::save(g,set,"g");
586                UI::save(fy,set,"fy");
587                UI::save(bm,set,"bm");
588        }
589    void validate() {
590        MarginalizedParticleBase::validate();
591
592        dimy = fy->dimension();
593        bm->set_yrv(rvx);
594
595        est_emp.set_rv(rvx);
596        est_emp.set_dim(rvx._dsize());
597        est.validate();
598        //
599        //check dimensions
600        rvc = rvxc.subt(rvx.copy_t(-1));
601        rvc.add( rvyc);
602        rvc=rvc.subt(rvx);
603
604        bdm_assert(g->dimension()==rvx._dsize(),"rvx is not described");
605        bdm_assert(g->dimensionc()==rvxc._dsize(),"rvxc is not described");
606        bdm_assert(fy->dimensionc()==rvyc._dsize(),"rvyc is not described");
607
608        bdm_assert(bm->dimensiony()==g->dimension(),
609                   "Incompatible noise estimator of dimension " +
610                   num2str(bm->dimensiony()) + " does not match dimension of g , " +
611                   num2str(g->dimension()));
612
613        dimc = rvc._dsize();
614
615        //establish datalinks
616        x2g.set_connection(rvxc, rvx.copy_t(-1));
617        cond2g.set_connection(rvxc, rvc);
618
619        x2fy.set_connection(rvyc, rvx);
620        cond2fy.set_connection(rvyc, rvc);
621    }
622};
623UIREGISTER(NoiseParticleX);
624
625
626/*! Marginalized particle for state-space models with unknown parameters of distribuution of residues on \f$v_t\f$ and \f$ w_t \f$.
627
628\f{eqnarray*}{
629        x_t &=& g(x_{t-1}) + v_t,\\
630        y_t &= &h(x_t)+w_t,
631        \f}
632       
633        This particle is a only a shell creating the residues calling internal estimator of their parameters. The internal estimator can be of any compatible type, e.g. ARX for Gaussian residues with unknown mean and variance.
634       
635        */
636class NoiseParticleXY : public BM {
637        //! discrte particle
638        dirac est_emp;
639        //! internal Bayes Model
640        shared_ptr<BM> bmx;
641        shared_ptr<BM> bmy;
642       
643        //! \brief Internal class for custom posterior - product of empirical and exact part
644        class eprod_3:public eprod_base {
645                protected:
646                        NoiseParticleXY &mp;
647                public:
648                        eprod_3(NoiseParticleXY &m):mp(m) {}
649                        const epdf* factor(int i) const {
650                                if (i==0) return &mp.bmx->posterior() ;
651                                if(i==1) return &mp.bmy->posterior();
652                                return &mp.est_emp;
653                        }
654                        const int no_factors() const {
655                                return 3;
656                        }
657        } est;
658
659        protected:
660                //! function transforming xt, ut -> x_t+1
661                shared_ptr<fnc> g; // pdf for non-linear part
662                //! function transforming xt,ut -> yt
663                shared_ptr<fnc> h; // pdf for non-linear part
664               
665                RV rvx;
666                RV rvxc;
667                RV rvyc;
668               
669                //!link from condition to f
670                datalink_part cond2g;
671                //!link from condition to h
672                datalink_part cond2h;
673                //!link from xt to f
674                datalink_part x2g;
675                //!link from xt to h
676                datalink_part x2h;
677               
678        public:
679                NoiseParticleXY():est(*this) {};
680                NoiseParticleXY(const NoiseParticleXY &m2):BM(m2),est(*this),g(m2.g),h(m2.h), rvx(m2.rvx),rvxc(m2.rvxc),rvyc(m2.rvyc) {
681                        bmx = m2.bmx->_copy();
682                        bmy = m2.bmy->_copy();
683                        est_emp = m2.est_emp;
684                        //est.validate();
685                        validate();
686                };
687               
688                const eprod_3& posterior() const {
689                        return est;
690                }
691               
692                void set_prior(const epdf *pdf0) {
693                        const eprod *ep=dynamic_cast<const eprod*>(pdf0);
694                        if (ep) { // full prior
695                                bdm_assert(ep->no_factors()==2,"Incompatible prod");
696                                bmx->set_prior(ep->factor(0));
697                                bmy->set_prior(ep->factor(1));
698                                est_emp.set_point(ep->factor(2)->sample());
699                        } else {
700                                // assume prior is only for emp;
701                                est_emp.set_point(pdf0->sample());
702                        }
703                }
704                               
705                BM* _copy() const {
706                        return new NoiseParticleXY(*this);
707                };
708               
709                void bayes(const vec &dt, const vec &cond) {
710                        //shared_ptr<epdf> pred_v=bm->epredictor();
711                       
712                        //vec vt=pred_v->sample();
713                        vec vt = bmx->samplepred();
714                       
715                        //new sample
716                        vec &xtm=est_emp.point;
717                        vec g_args(g->dimensionc());
718                        x2g.filldown(xtm,g_args);
719                        cond2g.filldown(cond,g_args);
720                        vec xt = g->eval(g_args) + vt;
721                        est_emp.point=xt;
722                       
723                        // the vector [v_t] updates bm,
724                        bmx->bayes(vt);
725                       
726                        // residue of observation
727                        vec h_args(h->dimensionc());
728                        x2h.filldown(xt,h_args);
729                        cond2h.filldown(cond,h_args);
730
731                        vec z_y =h->eval(h_args)-dt;
732//                      ARX *abm = dynamic_cast<ARX*>(bmy.get());
733/*                      double ll2;
734                        if (abm){ //ARX
735                                shared_ptr<epdf> pr_y(abm->epredictor_student(empty_vec));
736                                ll2=pr_y->evallog(z_y);
737                        } else{
738                                shared_ptr<epdf> pr_y(bmy->epredictor(empty_vec));
739                                ll2=pr_y->evallog(z_y);
740                        }*/
741                       
742                        bmy->bayes(z_y);
743                        // test _lls
744                        ll= bmy->_ll();
745                }
746                void from_setting(const Setting &set) {
747                        BM::from_setting(set); //reads bm, yrv,rvc, bm_rv, etc...
748                        bmx = UI::build<BM>(set,"bmx",UI::compulsory);
749                       
750                        bmy = UI::build<BM>(set,"bmy",UI::compulsory);
751                        g=UI::build<fnc>(set,"g",UI::compulsory);
752                        h=UI::build<fnc>(set,"h",UI::compulsory);
753                        UI::get(rvx,set,"rvx",UI::compulsory);
754                        est_emp.set_rv(rvx);
755                       
756                        UI::get(rvxc,set,"rvxc",UI::compulsory);
757                        UI::get(rvyc,set,"rvyc",UI::compulsory);
758                       
759                }
760                void to_setting (Setting &set) const {
761                        BM::to_setting(set); //reads bm, yrv,rvc, bm_rv, etc...
762                        UI::save(g,set,"g");
763                        UI::save(h,set,"h");
764                        UI::save(bmx,set,"bmx");
765                        UI::save(bmy,set,"bmy");
766                }
767                void validate() {
768                        BM::validate();
769                       
770                        dimy = h->dimension();
771//                      bmx->set_yrv(rvx);
772//                      bmy->
773                       
774                        est_emp.set_rv(rvx);
775                        est_emp.set_dim(rvx._dsize());
776                        est.validate();
777                        //
778                        //check dimensions
779                        rvc = rvxc.subt(rvx.copy_t(-1));
780                        rvc.add( rvyc);
781                        rvc=rvc.subt(rvx);
782                       
783                        bdm_assert(g->dimension()==rvx._dsize(),"rvx is not described");
784                        bdm_assert(g->dimensionc()==rvxc._dsize(),"rvxc is not described");
785                        bdm_assert(h->dimensionc()==rvyc._dsize(),"rvyc is not described");
786                       
787                        bdm_assert(bmx->dimensiony()==g->dimension(),
788                                           "Incompatible noise estimator of dimension " +
789                                           num2str(bmx->dimensiony()) + " does not match dimension of g , " +
790                                           num2str(g->dimension())
791                                           );
792                                           
793                        dimc = rvc._dsize();
794                       
795                        //establish datalinks
796                        x2g.set_connection(rvxc, rvx.copy_t(-1));
797                        cond2g.set_connection(rvxc, rvc);
798                       
799                        x2h.set_connection(rvyc, rvx);
800                        cond2h.set_connection(rvyc, rvc);
801                }               
802               
803};
804UIREGISTER(NoiseParticleXY);
805
806/*! Marginalized particle for state-space models with unknown parameters of residues distribution
807
808\f{eqnarray*}{
809    x_t &=& g(x_{t-1}) + v_t,\\
810    z_t &= &h(x_{t-1}) + w_t,
811    \f}
812
813    This particle is a only a shell creating the residues calling internal estimator of their parameters. The internal estimator can be of any compatible type, e.g. ARX for Gaussian residues with unknown mean and variance.
814
815    */
816class NoiseParticle : public MarginalizedParticleBase {
817protected:
818    //! function transforming xt, ut -> x_t+1
819    shared_ptr<fnc> g; // pdf for non-linear part
820    //! function transforming xt,ut -> yt
821    shared_ptr<fnc> h; // pdf for non-linear part
822
823    RV rvx;
824    RV rvxc;
825    RV rvyc;
826
827    //!link from condition to f
828    datalink_part cond2g;
829    //!link from condition to h
830    datalink_part cond2h;
831    //!link from xt to f
832    datalink_part x2g;
833    //!link from xt to h
834    datalink_part x2h;
835
836public:
837    BM* _copy() const {
838        return new NoiseParticle(*this);
839    };
840    void bayes(const vec &dt, const vec &cond) {
841        shared_ptr<epdf> pred_vw=bm->epredictor();
842        shared_ptr<epdf> pred_v = pred_vw->marginal(rvx);
843
844        vec vt=pred_v->sample();
845
846        //new sample
847        vec &xtm=est_emp.point;
848        vec g_args(g->dimensionc());
849        x2g.filldown(xtm,g_args);
850        cond2g.filldown(cond,g_args);
851        vec xt = g->eval(g_args) + vt;
852        est_emp.point=xt;
853
854        // residue of observation
855        vec h_args(h->dimensionc());
856        x2h.filldown(xt,h_args);
857        cond2h.filldown(cond,h_args);
858        vec wt = dt-h->eval(h_args);
859        // the vector [v_t,w_t] is now complete
860        bm->bayes(concat(vt,wt));
861        ll=bm->_ll();
862    }
863    void from_setting(const Setting &set) {
864        MarginalizedParticleBase::from_setting(set); //reads bm, yrv,rvc, bm_rv, etc...
865
866        UI::get(g,set,"g",UI::compulsory);
867        UI::get(h,set,"h",UI::compulsory);
868        UI::get(rvx,set,"rvx",UI::compulsory);
869        est_emp.set_rv(rvx);
870
871        UI::get(rvxc,set,"rvxc",UI::compulsory);
872        UI::get(rvyc,set,"rvyc",UI::compulsory);
873
874    }
875    void validate() {
876        MarginalizedParticleBase::validate();
877
878        dimy = h->dimension();
879        bm->set_yrv(concat(rvx,yrv));
880
881        est_emp.set_rv(rvx);
882        est_emp.set_dim(rvx._dsize());
883        est.validate();
884        //
885        //check dimensions
886        rvc = rvxc.subt(rvx.copy_t(-1));
887        rvc.add( rvyc);
888        rvc=rvc.subt(rvx);
889
890        bdm_assert(g->dimension()==rvx._dsize(),"rvx is not described");
891        bdm_assert(g->dimensionc()==rvxc._dsize(),"rvxc is not described");
892        bdm_assert(h->dimension()==rvyc._dsize(),"rvyc is not described");
893
894        bdm_assert(bm->dimensiony()==g->dimension()+h->dimension(),
895                   "Incompatible noise estimator of dimension " +
896                   num2str(bm->dimensiony()) + " does not match dimension of g and h, " +
897                   num2str(g->dimension())+" and "+ num2str(h->dimension()) );
898
899        dimc = rvc._dsize();
900
901        //establish datalinks
902        x2g.set_connection(rvxc, rvx.copy_t(-1));
903        cond2g.set_connection(rvxc, rvc);
904
905        x2h.set_connection(rvyc, rvx);
906        cond2h.set_connection(rvyc, rvc);
907    }
908};
909UIREGISTER(NoiseParticle);
910
911
912}
913#endif // KF_H
914
Note: See TracBrowser for help on using the browser.