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

Revision 1077, 21.9 kB (checked in by mido, 14 years ago)

another update of doc - all bayesian models until bdm::MultiModel? finished
also MixEF::MixEF_options renamed just to MixEF::Options

  • 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 Internal class used in PF
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 Internal class used in PF (surely?)
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) {
139        MarginalizedParticleBase::to_setting(set);
140        UI::save(par,set,"parameter_pdf");
141    }
142    void validate() {
143        MarginalizedParticleBase::validate();
144        est_emp.set_rv(par->_rv());
145        if (est_emp.point.length()!=par->dimension())
146            est_emp.set_point(zeros(par->dimension()));
147        est.validate();
148
149        yrv = bm->_yrv();
150        dimy = bm->dimensiony();
151        set_rv( concat(bm->_rv(), par->_rv()));
152        set_dim( par->dimension()+bm->dimension());
153
154        rvc = par->_rvc();
155        rvc.add(bm->_rvc());
156        rvc=rvc.subt(par->_rv());
157        rvc=rvc.subt(par->_rv().copy_t(-1));
158        rvc=rvc.subt(bm->_rv().copy_t(-1)); //
159
160        cond2bm=new datalink_part;
161        cond2par=new datalink_part;
162        emp2bm  =new datalink_part;
163        emp2par =new datalink_part;
164        cond2bm->set_connection(bm->_rvc(), rvc);
165        cond2par->set_connection(par->_rvc(), rvc);
166        emp2bm->set_connection(bm->_rvc(), par->_rv());
167        emp2par->set_connection(par->_rvc(), par->_rv().copy_t(-1));
168
169        dimc = rvc._dsize();
170    };
171};
172UIREGISTER(MarginalizedParticle);
173
174//! Internal class which is used in PF
175class BootstrapParticle : public BM {
176    dirac est;
177    shared_ptr<pdf> par;
178    shared_ptr<pdf> obs;
179    shared_ptr<datalink_part> cond2par;
180    shared_ptr<datalink_part> cond2obs;
181    shared_ptr<datalink_part> xt2obs;
182    shared_ptr<datalink_part> xtm2par;
183public:
184    BM* _copy() const {
185        return new BootstrapParticle(*this);
186    };
187    void bayes(const vec &dt, const vec &cond) {
188        vec par_cond(par->dimensionc());
189        cond2par->filldown(cond,par_cond); // copy ut
190        xtm2par->filldown(est._point(),par_cond); // copy xt-1
191
192        //sample new particle
193        est.set_point(par->samplecond(par_cond));
194        //if (evalll)
195        vec obs_cond(obs->dimensionc());
196        cond2obs->filldown(cond, obs_cond);// set e.g. ut
197        xt2obs->filldown(est._point(), obs_cond);// set e.g. ut
198        ll=obs->evallogcond(dt,obs_cond);
199    }
200    const dirac& posterior() const {
201        return est;
202    }
203
204    void set_prior(const epdf *pdf0) {
205        est.set_point(pdf0->sample());
206    }
207
208    /*! Create object from the following structure
209    \code
210    class = "BootstrapParticle";
211    parameter_pdf = configuration of bdm::epdf;      % any offspring of epdf, bdm::epdf::from_setting
212    observation_pdf = configuration of bdm::epdf;    % any offspring of epdf, bdm::epdf::from_setting
213    --- inherited fields ---
214    bdm::BM::from_setting
215    \endcode
216    */
217    void from_setting(const Setting &set) {
218        BM::from_setting ( set );
219        par = UI::build<pdf> ( set, "parameter_pdf", UI::compulsory );
220        obs = UI::build<pdf> ( set, "observation_pdf", UI::compulsory );
221    }
222
223    void validate() {
224        yrv = obs->_rv();
225        dimy = obs->dimension();
226        set_rv( par->_rv());
227        set_dim( par->dimension());
228
229        rvc = par->_rvc().subt(par->_rv().copy_t(-1));
230        rvc.add(obs->_rvc()); //
231
232        cond2obs=new datalink_part;
233        cond2par=new datalink_part;
234        xt2obs  =new datalink_part;
235        xtm2par =new datalink_part;
236        cond2obs->set_connection(obs->_rvc(), rvc);
237        cond2par->set_connection(par->_rvc(), rvc);
238        xt2obs->set_connection(obs->_rvc(), _rv());
239        xtm2par->set_connection(par->_rvc(), _rv().copy_t(-1));
240
241        dimc = rvc._dsize();
242    };
243};
244UIREGISTER(BootstrapParticle);
245
246
247/*!
248* \brief Trivial particle filter with proposal density equal to parameter evolution model.
249
250Posterior density is represented by a weighted empirical density (\c eEmp ).
251*/
252
253class PF : public BM {
254    //! \var log_level_enums logweights
255    //! all weightes will be logged
256
257    //! \var log_level_enums logmeans
258    //! means of particles will be logged
259    LOG_LEVEL(PF,logweights,logmeans,logvars);
260
261    class pf_mix: public emix_base {
262        Array<BM*> &bms;
263    public:
264        pf_mix(vec &w0, Array<BM*> &bms0):emix_base(w0),bms(bms0) {}
265        const epdf* component(const int &i)const {
266            return &(bms(i)->posterior());
267        }
268        int no_coms() const {
269            return bms.length();
270        }
271    };
272protected:
273    //!number of particles;
274    int n;
275    //!posterior density
276    pf_mix est;
277    //! weights;
278    vec w;
279    //! particles
280    Array<BM*> particles;
281    //! internal structure storing loglikelihood of predictions
282    vec lls;
283
284    //! which resampling method will be used
285    RESAMPLING_METHOD resmethod;
286    //! resampling threshold; in this case its meaning is minimum ratio of active particles
287    //! For example, for 0.5 resampling is performed when the numebr of active aprticles drops belo 50%.
288    double res_threshold;
289
290    //! \name Options
291    //!@{
292    //!@}
293
294public:
295    //! \name Constructors
296    //!@{
297    PF ( ) : est(w,particles) { };
298
299    void set_parameters ( int n0, double res_th0 = 0.5, RESAMPLING_METHOD rm = SYSTEMATIC ) {
300        n = n0;
301        res_threshold = res_th0;
302        resmethod = rm;
303    };
304    void set_model ( const BM *particle0, const epdf *prior) {
305        if (n>0) {
306            particles.set_length(n);
307            for (int i=0; i<n; i++) {
308                particles(i) = particle0->_copy();
309                particles(i)->set_prior(prior);
310            }
311        }
312        // set values for posterior
313        est.set_rv ( particle0->posterior()._rv() );
314    };
315    void set_statistics ( const vec w0, const epdf &epdf0 ) {
316        //est.set_statistics ( w0, epdf0 );
317    };
318    /*    void set_statistics ( const eEmp &epdf0 ) {
319            bdm_assert_debug ( epdf0._rv().equal ( par->_rv() ), "Incompatible input" );
320            est = epdf0;
321        };*/
322    //!@}
323
324    //! bayes compute weights of the
325    virtual void bayes_weights();
326    //! important part of particle filtering - decide if it is time to perform resampling
327    virtual bool do_resampling() {
328        double eff = 1.0 / ( w * w );
329        return eff < ( res_threshold*n );
330    }
331    void bayes ( const vec &yt, const vec &cond );
332    //!access function
333    vec& _lls() {
334        return lls;
335    }
336    //!access function
337    RESAMPLING_METHOD _resmethod() const {
338        return resmethod;
339    }
340    //! return correctly typed posterior (covariant return)
341    const pf_mix& posterior() const {
342        return est;
343    }
344
345    /*! configuration structure for basic PF
346    \code
347    parameter_pdf   = pdf_class;         // parameter evolution pdf
348    observation_pdf = pdf_class;         // observation pdf
349    prior           = epdf_class;         // prior probability density
350    --- optional ---
351    n               = 10;                 // number of particles
352    resmethod       = 'systematic', or 'multinomial', or 'stratified'
353                                          // resampling method
354    res_threshold   = 0.5;                // resample when active particles drop below 50%
355    \endcode
356    */
357    void from_setting ( const Setting &set ) {
358        BM::from_setting ( set );
359        UI::get ( log_level, set, "log_level", UI::optional );
360
361        shared_ptr<BM> bm0 = UI::build<BM>(set, "particle",UI::compulsory);
362
363        n =0;
364        UI::get(n,set,"n",UI::optional);;
365        if (n>0) {
366            particles.set_length(n);
367            for(int i=0; i<n; i++) {
368                particles(i)=bm0->_copy();
369            }
370            w = ones(n)/n;
371        }
372        shared_ptr<epdf> pri = UI::build<epdf>(set,"prior");
373        set_prior(pri.get());
374        // set resampling method
375        resmethod_from_set ( set );
376        //set drv
377
378        rvc = bm0->_rvc();
379        dimc = bm0->dimensionc();
380        BM::set_rv(bm0->_rv());
381        yrv=bm0->_yrv();
382        dimy = bm0->dimensiony();
383    }
384
385    void log_register ( bdm::logger& L, const string& prefix ) {
386        BM::log_register(L,prefix);
387        if (log_level[logweights]) {
388            L.add_vector( log_level, logweights, RV ( particles.length()), prefix);
389        }
390        if (log_level[logmeans]) {
391            for (int i=0; i<particles.length(); i++) {
392                L.add_vector( log_level, logmeans, RV ( particles(i)->dimension() ), prefix , i);
393            }
394        }
395        if (log_level[logvars]) {
396            for (int i=0; i<particles.length(); i++) {
397                L.add_vector( log_level, logvars, RV ( particles(i)->dimension() ), prefix , i);
398            }
399        }
400    };
401    void log_write ( ) const {
402        BM::log_write();
403        if (log_level[logweights]) {
404            log_level.store( logweights, w);
405        }
406        if (log_level[logmeans]) {
407            for (int i=0; i<particles.length(); i++) {
408                log_level.store( logmeans, particles(i)->posterior().mean(), i);
409            }
410        }
411        if (log_level[logvars]) {
412            for (int i=0; i<particles.length(); i++) {
413                log_level.store( logvars, particles(i)->posterior().variance(), i);
414            }
415        }
416
417    }
418
419    void set_prior(const epdf *pri) {
420        const emix_base *emi=dynamic_cast<const emix_base*>(pri);
421        if (emi) {
422            bdm_assert(particles.length()>0, "initial particle is not assigned");
423            n = emi->_w().length();
424            int old_n = particles.length();
425            if (n!=old_n) {
426                particles.set_length(n,true);
427            }
428            for(int i=old_n; i<n; i++) {
429                particles(i)=particles(0)->_copy();
430            }
431
432            for (int i =0; i<n; i++) {
433                particles(i)->set_prior(emi->_com(i));
434            }
435        } else {
436            // try to find "n"
437            bdm_assert(n>0, "Field 'n' must be filled when prior is not of type emix");
438            for (int i =0; i<n; i++) {
439                particles(i)->set_prior(pri);
440            }
441
442        }
443    }
444    //! auxiliary function reading parameter 'resmethod' from configuration file
445    void resmethod_from_set ( const Setting &set ) {
446        string resmeth;
447        if ( UI::get ( resmeth, set, "resmethod", UI::optional ) ) {
448            if ( resmeth == "systematic" ) {
449                resmethod = SYSTEMATIC;
450            } else  {
451                if ( resmeth == "multinomial" ) {
452                    resmethod = MULTINOMIAL;
453                } else {
454                    if ( resmeth == "stratified" ) {
455                        resmethod = STRATIFIED;
456                    } else {
457                        bdm_error ( "Unknown resampling method" );
458                    }
459                }
460            }
461        } else {
462            resmethod = SYSTEMATIC;
463        };
464        if ( !UI::get ( res_threshold, set, "res_threshold", UI::optional ) ) {
465            res_threshold = 0.9;
466        }
467        //validate();
468    }
469
470    void validate() {
471        BM::validate();
472        est.validate();
473        bdm_assert ( n>0, "empty particle pool" );
474        n = w.length();
475        lls = zeros ( n );
476
477        if ( particles(0)->_rv()._dsize() > 0 ) {
478            bdm_assert (  particles(0)->_rv()._dsize() == est.dimension(), "MPF:: Mismatch of RV " +particles(0)->_rv().to_string() +
479                          " of size (" +num2str(particles(0)->_rv()._dsize())+") and dimension of posterior ("+num2str(est.dimension()) + ")" );
480        }
481    }
482    //! resample posterior density (from outside - see MPF)
483    void resample ( ) {
484        ivec ind = zeros_i ( n );
485        bdm::resample(w,ind,resmethod);
486        // copy the internals according to ind
487        for (int i = 0; i < n; i++ ) {
488            if ( ind ( i ) != i ) {
489                delete particles(i);
490                particles( i ) = particles( ind ( i ) )->_copy();
491            }
492            w ( i ) = 1.0 / n;
493        }
494    }
495    //! access function
496    Array<BM*>& _particles() {
497        return particles;
498    }
499    ~PF() {
500        for (int i=0; i<particles.length(); i++) {
501            delete particles(i);
502        }
503    }
504
505};
506UIREGISTER ( PF );
507
508/*! Marginalized particle for state-space models with unknown parameters of distribuution of residues on \f$v_t\f$.
509
510\f{eqnarray*}{
511    x_t &=& g(x_{t-1}) + v_t,\\
512    y_t &\sim &fy(x_t),
513    \f}
514
515    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.
516
517    */
518class NoiseParticleX : public MarginalizedParticleBase {
519protected:
520    //! function transforming xt, ut -> x_t+1
521    shared_ptr<fnc> g; // pdf for non-linear part
522    //! function transforming xt,ut -> yt
523    shared_ptr<pdf> fy; // pdf for non-linear part
524
525    RV rvx;
526    RV rvxc;
527    RV rvyc;
528
529    //!link from condition to f
530    datalink_part cond2g;
531    //!link from condition to h
532    datalink_part cond2fy;
533    //!link from xt to f
534    datalink_part x2g;
535    //!link from xt to h
536    datalink_part x2fy;
537
538public:
539    BM* _copy() const {
540        return new NoiseParticleX(*this);
541    };
542    void bayes(const vec &dt, const vec &cond) {
543        shared_ptr<epdf> pred_v=bm->epredictor();
544
545        vec vt=pred_v->sample();
546
547        //new sample
548        vec &xtm=est_emp.point;
549        vec g_args(g->dimensionc());
550        x2g.filldown(xtm,g_args);
551        cond2g.filldown(cond,g_args);
552        vec xt = g->eval(g_args) + vt;
553        est_emp.point=xt;
554
555        // the vector [v_t] updates bm,
556        bm->bayes(vt);
557
558        // residue of observation
559        vec fy_args(fy->dimensionc());
560        x2fy.filldown(xt,fy_args);
561        cond2fy.filldown(cond,fy_args);
562
563        ll=bm->_ll() + fy->evallogcond(dt,fy_args);
564    }
565    void from_setting(const Setting &set) {
566        MarginalizedParticleBase::from_setting(set); //reads bm, yrv,rvc, bm_rv, etc...
567
568        g=UI::build<fnc>(set,"g",UI::compulsory);
569        fy=UI::build<pdf>(set,"fy",UI::compulsory);
570        UI::get(rvx,set,"rvx",UI::compulsory);
571        est_emp.set_rv(rvx);
572
573        UI::get(rvxc,set,"rvxc",UI::compulsory);
574        UI::get(rvyc,set,"rvyc",UI::compulsory);
575
576    }
577    void validate() {
578        MarginalizedParticleBase::validate();
579
580        dimy = fy->dimension();
581        bm->set_yrv(rvx);
582
583        est_emp.set_rv(rvx);
584        est_emp.set_dim(rvx._dsize());
585        est.validate();
586        //
587        //check dimensions
588        rvc = rvxc.subt(rvx.copy_t(-1));
589        rvc.add( rvyc);
590        rvc=rvc.subt(rvx);
591
592        bdm_assert(g->dimension()==rvx._dsize(),"rvx is not described");
593        bdm_assert(g->dimensionc()==rvxc._dsize(),"rvxc is not described");
594        bdm_assert(fy->dimensionc()==rvyc._dsize(),"rvyc is not described");
595
596        bdm_assert(bm->dimensiony()==g->dimension(),
597                   "Incompatible noise estimator of dimension " +
598                   num2str(bm->dimensiony()) + " does not match dimension of g , " +
599                   num2str(g->dimension()));
600
601        dimc = rvc._dsize();
602
603        //establish datalinks
604        x2g.set_connection(rvxc, rvx.copy_t(-1));
605        cond2g.set_connection(rvxc, rvc);
606
607        x2fy.set_connection(rvyc, rvx);
608        cond2fy.set_connection(rvyc, rvc);
609    }
610};
611UIREGISTER(NoiseParticleX);
612
613/*! Marginalized particle for state-space models with unknown parameters of residues distribution
614
615\f{eqnarray*}{
616    x_t &=& g(x_{t-1}) + v_t,\\
617    z_t &= &h(x_{t-1}) + w_t,
618    \f}
619
620    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.
621
622    */
623class NoiseParticle : public MarginalizedParticleBase {
624protected:
625    //! function transforming xt, ut -> x_t+1
626    shared_ptr<fnc> g; // pdf for non-linear part
627    //! function transforming xt,ut -> yt
628    shared_ptr<fnc> h; // pdf for non-linear part
629
630    RV rvx;
631    RV rvxc;
632    RV rvyc;
633
634    //!link from condition to f
635    datalink_part cond2g;
636    //!link from condition to h
637    datalink_part cond2h;
638    //!link from xt to f
639    datalink_part x2g;
640    //!link from xt to h
641    datalink_part x2h;
642
643public:
644    BM* _copy() const {
645        return new NoiseParticle(*this);
646    };
647    void bayes(const vec &dt, const vec &cond) {
648        shared_ptr<epdf> pred_vw=bm->epredictor();
649        shared_ptr<epdf> pred_v = pred_vw->marginal(rvx);
650
651        vec vt=pred_v->sample();
652
653        //new sample
654        vec &xtm=est_emp.point;
655        vec g_args(g->dimensionc());
656        x2g.filldown(xtm,g_args);
657        cond2g.filldown(cond,g_args);
658        vec xt = g->eval(g_args) + vt;
659        est_emp.point=xt;
660
661        // residue of observation
662        vec h_args(h->dimensionc());
663        x2h.filldown(xt,h_args);
664        cond2h.filldown(cond,h_args);
665        vec wt = dt-h->eval(h_args);
666        // the vector [v_t,w_t] is now complete
667        bm->bayes(concat(vt,wt));
668        ll=bm->_ll();
669    }
670    void from_setting(const Setting &set) {
671        MarginalizedParticleBase::from_setting(set); //reads bm, yrv,rvc, bm_rv, etc...
672
673        UI::get(g,set,"g",UI::compulsory);
674        UI::get(h,set,"h",UI::compulsory);
675        UI::get(rvx,set,"rvx",UI::compulsory);
676        est_emp.set_rv(rvx);
677
678        UI::get(rvxc,set,"rvxc",UI::compulsory);
679        UI::get(rvyc,set,"rvyc",UI::compulsory);
680
681    }
682    void validate() {
683        MarginalizedParticleBase::validate();
684
685        dimy = h->dimension();
686        bm->set_yrv(concat(rvx,yrv));
687
688        est_emp.set_rv(rvx);
689        est_emp.set_dim(rvx._dsize());
690        est.validate();
691        //
692        //check dimensions
693        rvc = rvxc.subt(rvx.copy_t(-1));
694        rvc.add( rvyc);
695        rvc=rvc.subt(rvx);
696
697        bdm_assert(g->dimension()==rvx._dsize(),"rvx is not described");
698        bdm_assert(g->dimensionc()==rvxc._dsize(),"rvxc is not described");
699        bdm_assert(h->dimension()==rvyc._dsize(),"rvyc is not described");
700
701        bdm_assert(bm->dimensiony()==g->dimension()+h->dimension(),
702                   "Incompatible noise estimator of dimension " +
703                   num2str(bm->dimensiony()) + " does not match dimension of g and h, " +
704                   num2str(g->dimension())+" and "+ num2str(h->dimension()) );
705
706        dimc = rvc._dsize();
707
708        //establish datalinks
709        x2g.set_connection(rvxc, rvx.copy_t(-1));
710        cond2g.set_connection(rvxc, rvc);
711
712        x2h.set_connection(rvyc, rvx);
713        cond2h.set_connection(rvyc, rvc);
714    }
715};
716UIREGISTER(NoiseParticle);
717
718
719}
720#endif // KF_H
721
Note: See TracBrowser for help on using the browser.