| | 627 | /*! Marginalized particle for state-space models with unknown parameters of distribuution of residues on \f$v_t\f$ and \f$ w_t \f$. |
| | 628 | |
| | 629 | \f{eqnarray*}{ |
| | 630 | x_t &=& g(x_{t-1}) + v_t,\\ |
| | 631 | y_t &= &h(x_t)+w_t, |
| | 632 | \f} |
| | 633 | |
| | 634 | 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. |
| | 635 | |
| | 636 | */ |
| | 637 | class NoiseParticleXY : public BM { |
| | 638 | //! discrte particle |
| | 639 | dirac est_emp; |
| | 640 | //! internal Bayes Model |
| | 641 | shared_ptr<BM> bmx; |
| | 642 | shared_ptr<BM> bmy; |
| | 643 | |
| | 644 | //! \brief Internal class for custom posterior - product of empirical and exact part |
| | 645 | class eprod_3:public eprod_base { |
| | 646 | protected: |
| | 647 | NoiseParticleXY ∓ |
| | 648 | public: |
| | 649 | eprod_3(NoiseParticleXY &m):mp(m) {} |
| | 650 | const epdf* factor(int i) const { |
| | 651 | if (i==0) return &mp.bmx->posterior() ; |
| | 652 | if(i==1) return &mp.bmy->posterior(); |
| | 653 | return &mp.est_emp; |
| | 654 | } |
| | 655 | const int no_factors() const { |
| | 656 | return 3; |
| | 657 | } |
| | 658 | } est; |
| | 659 | |
| | 660 | protected: |
| | 661 | //! function transforming xt, ut -> x_t+1 |
| | 662 | shared_ptr<fnc> g; // pdf for non-linear part |
| | 663 | //! function transforming xt,ut -> yt |
| | 664 | shared_ptr<fnc> h; // pdf for non-linear part |
| | 665 | |
| | 666 | RV rvx; |
| | 667 | RV rvxc; |
| | 668 | RV rvyc; |
| | 669 | |
| | 670 | //!link from condition to f |
| | 671 | datalink_part cond2g; |
| | 672 | //!link from condition to h |
| | 673 | datalink_part cond2h; |
| | 674 | //!link from xt to f |
| | 675 | datalink_part x2g; |
| | 676 | //!link from xt to h |
| | 677 | datalink_part x2h; |
| | 678 | |
| | 679 | public: |
| | 680 | NoiseParticleXY():est(*this) {}; |
| | 681 | NoiseParticleXY(const NoiseParticleXY &m2):BM(m2),est(*this),h(m2.h),g(m2.g), rvx(m2.rvx),rvxc(m2.rvxc),rvyc(m2.rvyc) { |
| | 682 | bmx = m2.bmx->_copy(); |
| | 683 | bmy = m2.bmy->_copy(); |
| | 684 | est_emp = m2.est_emp; |
| | 685 | //est.validate(); |
| | 686 | validate(); |
| | 687 | }; |
| | 688 | |
| | 689 | const eprod_3& posterior() const { |
| | 690 | return est; |
| | 691 | } |
| | 692 | |
| | 693 | void set_prior(const epdf *pdf0) { |
| | 694 | const eprod *ep=dynamic_cast<const eprod*>(pdf0); |
| | 695 | if (ep) { // full prior |
| | 696 | bdm_assert(ep->no_factors()==2,"Incompatible prod"); |
| | 697 | bmx->set_prior(ep->factor(0)); |
| | 698 | bmy->set_prior(ep->factor(1)); |
| | 699 | est_emp.set_point(ep->factor(2)->sample()); |
| | 700 | } else { |
| | 701 | // assume prior is only for emp; |
| | 702 | est_emp.set_point(pdf0->sample()); |
| | 703 | } |
| | 704 | } |
| | 705 | |
| | 706 | BM* _copy() const { |
| | 707 | return new NoiseParticleXY(*this); |
| | 708 | }; |
| | 709 | |
| | 710 | void bayes(const vec &dt, const vec &cond) { |
| | 711 | //shared_ptr<epdf> pred_v=bm->epredictor(); |
| | 712 | |
| | 713 | //vec vt=pred_v->sample(); |
| | 714 | vec vt = bmx->samplepred(); |
| | 715 | |
| | 716 | //new sample |
| | 717 | vec &xtm=est_emp.point; |
| | 718 | vec g_args(g->dimensionc()); |
| | 719 | x2g.filldown(xtm,g_args); |
| | 720 | cond2g.filldown(cond,g_args); |
| | 721 | vec xt = g->eval(g_args) + vt; |
| | 722 | est_emp.point=xt; |
| | 723 | |
| | 724 | // the vector [v_t] updates bm, |
| | 725 | bmx->bayes(vt); |
| | 726 | |
| | 727 | // residue of observation |
| | 728 | vec h_args(h->dimensionc()); |
| | 729 | x2h.filldown(xt,h_args); |
| | 730 | cond2h.filldown(cond,h_args); |
| | 731 | |
| | 732 | bmy->bayes(h->eval(h_args)-dt); |
| | 733 | ll= bmy->_ll(); |
| | 734 | } |
| | 735 | void from_setting(const Setting &set) { |
| | 736 | BM::from_setting(set); //reads bm, yrv,rvc, bm_rv, etc... |
| | 737 | bmx = UI::build<BM>(set,"bmx",UI::compulsory); |
| | 738 | |
| | 739 | bmy = UI::build<BM>(set,"bmy",UI::compulsory); |
| | 740 | g=UI::build<fnc>(set,"g",UI::compulsory); |
| | 741 | h=UI::build<fnc>(set,"h",UI::compulsory); |
| | 742 | UI::get(rvx,set,"rvx",UI::compulsory); |
| | 743 | est_emp.set_rv(rvx); |
| | 744 | |
| | 745 | UI::get(rvxc,set,"rvxc",UI::compulsory); |
| | 746 | UI::get(rvyc,set,"rvyc",UI::compulsory); |
| | 747 | |
| | 748 | } |
| | 749 | void to_setting (Setting &set) const { |
| | 750 | BM::to_setting(set); //reads bm, yrv,rvc, bm_rv, etc... |
| | 751 | UI::save(g,set,"g"); |
| | 752 | UI::save(h,set,"h"); |
| | 753 | UI::save(bmx,set,"bmx"); |
| | 754 | UI::save(bmy,set,"bmy"); |
| | 755 | } |
| | 756 | void validate() { |
| | 757 | BM::validate(); |
| | 758 | |
| | 759 | dimy = h->dimension(); |
| | 760 | // bmx->set_yrv(rvx); |
| | 761 | // bmy-> |
| | 762 | |
| | 763 | est_emp.set_rv(rvx); |
| | 764 | est_emp.set_dim(rvx._dsize()); |
| | 765 | est.validate(); |
| | 766 | // |
| | 767 | //check dimensions |
| | 768 | rvc = rvxc.subt(rvx.copy_t(-1)); |
| | 769 | rvc.add( rvyc); |
| | 770 | rvc=rvc.subt(rvx); |
| | 771 | |
| | 772 | bdm_assert(g->dimension()==rvx._dsize(),"rvx is not described"); |
| | 773 | bdm_assert(g->dimensionc()==rvxc._dsize(),"rvxc is not described"); |
| | 774 | bdm_assert(h->dimensionc()==rvyc._dsize(),"rvyc is not described"); |
| | 775 | |
| | 776 | bdm_assert(bmx->dimensiony()==g->dimension(), |
| | 777 | "Incompatible noise estimator of dimension " + |
| | 778 | num2str(bmx->dimensiony()) + " does not match dimension of g , " + |
| | 779 | num2str(g->dimension()) |
| | 780 | ); |
| | 781 | |
| | 782 | dimc = rvc._dsize(); |
| | 783 | |
| | 784 | //establish datalinks |
| | 785 | x2g.set_connection(rvxc, rvx.copy_t(-1)); |
| | 786 | cond2g.set_connection(rvxc, rvc); |
| | 787 | |
| | 788 | x2h.set_connection(rvyc, rvx); |
| | 789 | cond2h.set_connection(rvyc, rvc); |
| | 790 | } |
| | 791 | |
| | 792 | }; |
| | 793 | UIREGISTER(NoiseParticleXY); |
| | 794 | |