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

Revision 1187, 27.1 kB (checked in by smidl, 14 years ago)

logging of weights + old computing of weights

  • 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/*! Marginalized particle for state-space models with unknown parameters of distribuution of residues on \f$v_t\f$ and \f$ w_t \f$.
626
627\f{eqnarray*}{
628        x_t &=& g(x_{t-1}) + v_t,\\
629        y_t &= &h(x_t)+w_t,
630        \f}
631       
632        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.
633       
634        */
635class NoiseParticleXY : public BM {
636        //! discrte particle
637        dirac est_emp;
638        //! internal Bayes Model
639        shared_ptr<BM> bmx;
640        shared_ptr<BM> bmy;
641       
642        //! \brief Internal class for custom posterior - product of empirical and exact part
643        class eprod_3:public eprod_base {
644                protected:
645                        NoiseParticleXY &mp;
646                public:
647                        eprod_3(NoiseParticleXY &m):mp(m) {}
648                        const epdf* factor(int i) const {
649                                if (i==0) return &mp.bmx->posterior() ;
650                                if(i==1) return &mp.bmy->posterior();
651                                return &mp.est_emp;
652                        }
653                        const int no_factors() const {
654                                return 3;
655                        }
656        } est;
657
658        protected:
659                //! function transforming xt, ut -> x_t+1
660                shared_ptr<fnc> g; // pdf for non-linear part
661                //! function transforming xt,ut -> yt
662                shared_ptr<fnc> h; // pdf for non-linear part
663               
664                RV rvx;
665                RV rvxc;
666                RV rvyc;
667               
668                //!link from condition to f
669                datalink_part cond2g;
670                //!link from condition to h
671                datalink_part cond2h;
672                //!link from xt to f
673                datalink_part x2g;
674                //!link from xt to h
675                datalink_part x2h;
676               
677        public:
678                NoiseParticleXY():est(*this) {};
679                NoiseParticleXY(const NoiseParticleXY &m2):BM(m2),est(*this),g(m2.g),h(m2.h), rvx(m2.rvx),rvxc(m2.rvxc),rvyc(m2.rvyc) {
680                        bmx = m2.bmx->_copy();
681                        bmy = m2.bmy->_copy();
682                        est_emp = m2.est_emp;
683                        //est.validate();
684                        validate();
685                };
686               
687                const eprod_3& posterior() const {
688                        return est;
689                }
690               
691                void set_prior(const epdf *pdf0) {
692                        const eprod *ep=dynamic_cast<const eprod*>(pdf0);
693                        if (ep) { // full prior
694                                bdm_assert(ep->no_factors()==2,"Incompatible prod");
695                                bmx->set_prior(ep->factor(0));
696                                bmy->set_prior(ep->factor(1));
697                                est_emp.set_point(ep->factor(2)->sample());
698                        } else {
699                                // assume prior is only for emp;
700                                est_emp.set_point(pdf0->sample());
701                        }
702                }
703                               
704                BM* _copy() const {
705                        return new NoiseParticleXY(*this);
706                };
707               
708                void bayes(const vec &dt, const vec &cond) {
709                        //shared_ptr<epdf> pred_v=bm->epredictor();
710                       
711                        //vec vt=pred_v->sample();
712                        vec vt = bmx->samplepred();
713                       
714                        //new sample
715                        vec &xtm=est_emp.point;
716                        vec g_args(g->dimensionc());
717                        x2g.filldown(xtm,g_args);
718                        cond2g.filldown(cond,g_args);
719                        vec xt = g->eval(g_args) + vt;
720                        est_emp.point=xt;
721                       
722                        // the vector [v_t] updates bm,
723                        bmx->bayes(vt);
724                       
725                        // residue of observation
726                        vec h_args(h->dimensionc());
727                        x2h.filldown(xt,h_args);
728                        cond2h.filldown(cond,h_args);
729
730                        vec z_y =h->eval(h_args)-dt;
731//                      ARX *abm = dynamic_cast<ARX*>(bmy.get());
732/*                      double ll2;
733                        if (abm){ //ARX
734                                shared_ptr<epdf> pr_y(abm->epredictor_student(empty_vec));
735                                ll2=pr_y->evallog(z_y);
736                        } else{
737                                shared_ptr<epdf> pr_y(bmy->epredictor(empty_vec));
738                                ll2=pr_y->evallog(z_y);
739                        }*/
740                       
741                        bmy->bayes(z_y);
742                        // test _lls
743                        ll= bmy->_ll();
744                }
745                void from_setting(const Setting &set) {
746                        BM::from_setting(set); //reads bm, yrv,rvc, bm_rv, etc...
747                        bmx = UI::build<BM>(set,"bmx",UI::compulsory);
748                       
749                        bmy = UI::build<BM>(set,"bmy",UI::compulsory);
750                        g=UI::build<fnc>(set,"g",UI::compulsory);
751                        h=UI::build<fnc>(set,"h",UI::compulsory);
752                        UI::get(rvx,set,"rvx",UI::compulsory);
753                        est_emp.set_rv(rvx);
754                       
755                        UI::get(rvxc,set,"rvxc",UI::compulsory);
756                        UI::get(rvyc,set,"rvyc",UI::compulsory);
757                       
758                }
759                void to_setting (Setting &set) const {
760                        BM::to_setting(set); //reads bm, yrv,rvc, bm_rv, etc...
761                        UI::save(g,set,"g");
762                        UI::save(h,set,"h");
763                        UI::save(bmx,set,"bmx");
764                        UI::save(bmy,set,"bmy");
765                }
766                void validate() {
767                        BM::validate();
768                       
769                        dimy = h->dimension();
770//                      bmx->set_yrv(rvx);
771//                      bmy->
772                       
773                        est_emp.set_rv(rvx);
774                        est_emp.set_dim(rvx._dsize());
775                        est.validate();
776                        //
777                        //check dimensions
778                        rvc = rvxc.subt(rvx.copy_t(-1));
779                        rvc.add( rvyc);
780                        rvc=rvc.subt(rvx);
781                       
782                        bdm_assert(g->dimension()==rvx._dsize(),"rvx is not described");
783                        bdm_assert(g->dimensionc()==rvxc._dsize(),"rvxc is not described");
784                        bdm_assert(h->dimensionc()==rvyc._dsize(),"rvyc is not described");
785                       
786                        bdm_assert(bmx->dimensiony()==g->dimension(),
787                                           "Incompatible noise estimator of dimension " +
788                                           num2str(bmx->dimensiony()) + " does not match dimension of g , " +
789                                           num2str(g->dimension())
790                                           );
791                                           
792                        dimc = rvc._dsize();
793                       
794                        //establish datalinks
795                        x2g.set_connection(rvxc, rvx.copy_t(-1));
796                        cond2g.set_connection(rvxc, rvc);
797                       
798                        x2h.set_connection(rvyc, rvx);
799                        cond2h.set_connection(rvyc, rvc);
800                }               
801               
802};
803UIREGISTER(NoiseParticleXY);
804
805/*! Marginalized particle for state-space models with unknown parameters of residues distribution
806
807\f{eqnarray*}{
808    x_t &=& g(x_{t-1}) + v_t,\\
809    z_t &= &h(x_{t-1}) + w_t,
810    \f}
811
812    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.
813
814    */
815class NoiseParticle : public MarginalizedParticleBase {
816protected:
817    //! function transforming xt, ut -> x_t+1
818    shared_ptr<fnc> g; // pdf for non-linear part
819    //! function transforming xt,ut -> yt
820    shared_ptr<fnc> h; // pdf for non-linear part
821
822    RV rvx;
823    RV rvxc;
824    RV rvyc;
825
826    //!link from condition to f
827    datalink_part cond2g;
828    //!link from condition to h
829    datalink_part cond2h;
830    //!link from xt to f
831    datalink_part x2g;
832    //!link from xt to h
833    datalink_part x2h;
834
835public:
836    BM* _copy() const {
837        return new NoiseParticle(*this);
838    };
839    void bayes(const vec &dt, const vec &cond) {
840        shared_ptr<epdf> pred_vw=bm->epredictor();
841        shared_ptr<epdf> pred_v = pred_vw->marginal(rvx);
842
843        vec vt=pred_v->sample();
844
845        //new sample
846        vec &xtm=est_emp.point;
847        vec g_args(g->dimensionc());
848        x2g.filldown(xtm,g_args);
849        cond2g.filldown(cond,g_args);
850        vec xt = g->eval(g_args) + vt;
851        est_emp.point=xt;
852
853        // residue of observation
854        vec h_args(h->dimensionc());
855        x2h.filldown(xt,h_args);
856        cond2h.filldown(cond,h_args);
857        vec wt = dt-h->eval(h_args);
858        // the vector [v_t,w_t] is now complete
859        bm->bayes(concat(vt,wt));
860        ll=bm->_ll();
861    }
862    void from_setting(const Setting &set) {
863        MarginalizedParticleBase::from_setting(set); //reads bm, yrv,rvc, bm_rv, etc...
864
865        UI::get(g,set,"g",UI::compulsory);
866        UI::get(h,set,"h",UI::compulsory);
867        UI::get(rvx,set,"rvx",UI::compulsory);
868        est_emp.set_rv(rvx);
869
870        UI::get(rvxc,set,"rvxc",UI::compulsory);
871        UI::get(rvyc,set,"rvyc",UI::compulsory);
872
873    }
874    void validate() {
875        MarginalizedParticleBase::validate();
876
877        dimy = h->dimension();
878        bm->set_yrv(concat(rvx,yrv));
879
880        est_emp.set_rv(rvx);
881        est_emp.set_dim(rvx._dsize());
882        est.validate();
883        //
884        //check dimensions
885        rvc = rvxc.subt(rvx.copy_t(-1));
886        rvc.add( rvyc);
887        rvc=rvc.subt(rvx);
888
889        bdm_assert(g->dimension()==rvx._dsize(),"rvx is not described");
890        bdm_assert(g->dimensionc()==rvxc._dsize(),"rvxc is not described");
891        bdm_assert(h->dimension()==rvyc._dsize(),"rvyc is not described");
892
893        bdm_assert(bm->dimensiony()==g->dimension()+h->dimension(),
894                   "Incompatible noise estimator of dimension " +
895                   num2str(bm->dimensiony()) + " does not match dimension of g and h, " +
896                   num2str(g->dimension())+" and "+ num2str(h->dimension()) );
897
898        dimc = rvc._dsize();
899
900        //establish datalinks
901        x2g.set_connection(rvxc, rvx.copy_t(-1));
902        cond2g.set_connection(rvxc, rvc);
903
904        x2h.set_connection(rvyc, rvx);
905        cond2h.set_connection(rvyc, rvc);
906    }
907};
908UIREGISTER(NoiseParticle);
909
910
911}
912#endif // KF_H
913
Note: See TracBrowser for help on using the browser.