| 60 | | /* PF ( mpdf *par0, mpdf *obs0, epdf *epdf0, int n0 ) : |
| 61 | | est ( ),_w ( est._w() ),_samples ( est._samples() ),opt_L_smp(false), opt_L_wei(false) |
| 62 | | { set_parameters ( par0,obs0,n0 ); set_statistics ( ones ( n0 ),epdf0 ); };*/ |
| 63 | | void set_parameters ( mpdf *par0, mpdf *obs0, int n0, RESAMPLING_METHOD rm = SYSTEMATIC ) { |
| | 65 | |
| | 66 | void set_parameters (int n0, double res_th0=0.5, RESAMPLING_METHOD rm = SYSTEMATIC ) { |
| | 67 | n = n0; |
| | 68 | res_threshold = res_th0; |
| | 69 | resmethod = rm; |
| | 70 | }; |
| | 71 | void set_model ( shared_ptr<mpdf> par0, shared_ptr<mpdf> obs0) { |
| 82 | | vec* __w() { |
| 83 | | return &_w; |
| | 105 | vec& __w() { return _w; } |
| | 106 | //!access function |
| | 107 | vec& _lls() { return lls; } |
| | 108 | RESAMPLING_METHOD _resmethod() const { return resmethod; } |
| | 109 | //!access function |
| | 110 | const eEmp& posterior() const {return est;} |
| | 111 | |
| | 112 | /*! configuration structure for basic PF |
| | 113 | \code |
| | 114 | parameter_pdf = mpdf_class; // parameter evolution pdf |
| | 115 | observation_pdf = mpdf_class; // observation pdf |
| | 116 | prior = epdf_class; // prior probability density |
| | 117 | --- optional --- |
| | 118 | n = 10; // number of particles |
| | 119 | resmethod = 'systematic', or 'multinomial', or 'stratified' |
| | 120 | // resampling method |
| | 121 | res_threshold = 0.5; // resample when active particles drop below 50% |
| | 122 | \endcode |
| | 123 | */ |
| | 124 | void from_setting(const Setting &set){ |
| | 125 | par = UI::build<mpdf>(set,"parameter_pdf",UI::compulsory); |
| | 126 | obs = UI::build<mpdf>(set,"observation_pdf",UI::compulsory); |
| | 127 | |
| | 128 | prior_from_set(set); |
| | 129 | resmethod_from_set(set); |
| | 130 | // set resampling method |
| | 131 | //set drv |
| | 132 | //find potential input - what remains in rvc when we subtract rv |
| | 133 | RV u = par->_rvc().remove_time().subt( par->_rv() ); |
| | 134 | //find potential input - what remains in rvc when we subtract x_t |
| | 135 | RV obs_u = obs->_rvc().remove_time().subt( par->_rv() ); |
| | 136 | |
| | 137 | u.add(obs_u); // join both u, and check if they do not overlap |
| | 138 | |
| | 139 | set_drv(concat(obs->_rv(),u) ); |
| | 140 | } |
| | 141 | //! auxiliary function reading parameter 'resmethod' from configuration file |
| | 142 | void resmethod_from_set(const Setting &set){ |
| | 143 | string resmeth; |
| | 144 | if (UI::get(resmeth,set,"resmethod",UI::optional)){ |
| | 145 | if (resmeth=="systematic") { |
| | 146 | resmethod= SYSTEMATIC; |
| | 147 | } else { |
| | 148 | if (resmeth=="multinomial"){ |
| | 149 | resmethod=MULTINOMIAL; |
| | 150 | } else { |
| | 151 | if (resmeth=="stratified"){ |
| | 152 | resmethod= STRATIFIED; |
| | 153 | } else { |
| | 154 | bdm_error("Unknown resampling method"); |
| | 155 | } |
| | 156 | } |
| | 157 | } |
| | 158 | } else { |
| | 159 | resmethod=SYSTEMATIC; |
| | 160 | }; |
| | 161 | if(!UI::get(res_threshold, set, "res_threshold", UI::optional)){ |
| | 162 | res_threshold=0.5; |
| | 163 | } |
| | 164 | } |
| | 165 | //! load prior information from set and set internal structures accordingly |
| | 166 | void prior_from_set(const Setting & set){ |
| | 167 | shared_ptr<epdf> pri = UI::build<epdf>(set,"prior",UI::compulsory); |
| | 168 | |
| | 169 | eEmp *test_emp=dynamic_cast<eEmp*>(&(*pri)); |
| | 170 | if (test_emp) { // given pdf is sampled |
| | 171 | est=*test_emp; |
| | 172 | } else { |
| | 173 | int n; |
| | 174 | if (!UI::get(n,set,"n",UI::optional)){n=10;} |
| | 175 | // sample from prior |
| | 176 | set_statistics(ones(n)/n, *pri); |
| | 177 | } |
| | 178 | //validate(); |
| | 179 | } |
| | 180 | |
| | 181 | void validate(){ |
| | 182 | n=_w.length(); |
| | 183 | lls=zeros(n); |
| | 184 | if (par->_rv()._dsize()>0) { |
| | 185 | bdm_assert(par->_rv()._dsize()==est.dimension(),"Mismatch of RV and dimension of posterior" ); |
| | 186 | } |
| | 187 | } |
| | 188 | //! resample posterior density (from outside - see MPF) |
| | 189 | void resample(ivec &ind){ |
| | 190 | est.resample(ind,resmethod); |
| 105 | | mpfepdf ( eEmp &E0 ) : |
| 106 | | epdf ( ), E ( E0 ), _w ( E._w() ), |
| 107 | | Coms ( _w.length() ) { |
| 108 | | }; |
| 109 | | //! read statistics from MPF |
| 110 | | void read_statistics ( Array<BM_T*> &A ) { |
| 111 | | dim = E.dimension() + A ( 0 )->posterior().dimension(); |
| 112 | | for ( int i = 0; i < _w.length() ; i++ ) { |
| 113 | | Coms ( i ) = &(A ( i )->posterior()); |
| | 212 | mpfepdf (shared_ptr<PF> &pf0, Array<BM*> &BMs0): epdf(), pf(pf0), BMs(BMs0) { }; |
| | 213 | //! a variant of set parameters - this time, parameters are read from BMs and pf |
| | 214 | void read_parameters(){ |
| | 215 | rv = concat(pf->posterior()._rv(), BMs(0)->posterior()._rv()); |
| | 216 | dim = pf->posterior().dimension() + BMs(0)->posterior().dimension(); |
| | 217 | bdm_assert_debug(dim == rv._dsize(), "Wrong name "); |
| | 218 | } |
| | 219 | vec mean() const { |
| | 220 | const vec &w = pf->posterior()._w(); |
| | 221 | vec pom = zeros ( BMs(0)->posterior ().dimension() ); |
| | 222 | //compute mean of BMs |
| | 223 | for ( int i = 0; i < w.length(); i++ ) { |
| | 224 | pom += BMs ( i )->posterior().mean() * w ( i ); |
| 115 | | } |
| 116 | | //! needed in resampling |
| 117 | | void set_elements ( int &i, double wi, const epdf* ep ) { |
| 118 | | _w ( i ) = wi; |
| 119 | | Coms ( i ) = ep; |
| 120 | | }; |
| 121 | | |
| 122 | | void set_parameters ( int n ) { |
| 123 | | E.set_parameters ( n, false ); |
| 124 | | Coms.set_length ( n ); |
| 125 | | } |
| 126 | | vec mean() const { |
| 127 | | // ugly |
| 128 | | vec pom = zeros ( Coms ( 0 )->dimension() ); |
| 129 | | for ( int i = 0; i < _w.length(); i++ ) { |
| 130 | | pom += Coms ( i )->mean() * _w ( i ); |
| | 226 | return concat ( pf->posterior().mean(), pom ); |
| | 227 | } |
| | 228 | vec variance() const { |
| | 229 | const vec &w = pf->posterior()._w(); |
| | 230 | |
| | 231 | vec pom = zeros ( BMs(0)->posterior ().dimension() ); |
| | 232 | vec pom2 = zeros ( BMs(0)->posterior ().dimension() ); |
| | 233 | vec mea; |
| | 234 | |
| | 235 | for ( int i = 0; i < w.length(); i++ ) { |
| | 236 | // save current mean |
| | 237 | mea = BMs ( i )->posterior().mean(); |
| | 238 | pom += mea * w ( i ); |
| | 239 | //compute variance |
| | 240 | pom2 += ( BMs ( i )->posterior().variance() + pow ( mea, 2 ) ) * w ( i ); |
| 132 | | return concat ( E.mean(), pom ); |
| 133 | | } |
| 134 | | vec variance() const { |
| 135 | | // ugly |
| 136 | | vec pom = zeros ( Coms ( 0 )->dimension() ); |
| 137 | | vec pom2 = zeros ( Coms ( 0 )->dimension() ); |
| 138 | | for ( int i = 0; i < _w.length(); i++ ) { |
| 139 | | pom += Coms ( i )->mean() * _w ( i ); |
| 140 | | pom2 += ( Coms ( i )->variance() + pow ( Coms ( i )->mean(), 2 ) ) * _w ( i ); |
| 141 | | } |
| 142 | | return concat ( E.variance(), pom2 - pow ( pom, 2 ) ); |
| 143 | | } |
| | 242 | return concat ( pf->posterior().variance(), pom2 - pow ( pom, 2 ) ); |
| | 243 | } |
| | 244 | |
| 197 | | MPF () : PF (), jest ( est ) {}; |
| 198 | | void set_parameters ( mpdf *par0, mpdf *obs0, int n0, RESAMPLING_METHOD rm = SYSTEMATIC ) { |
| 199 | | PF::set_parameters ( par0, obs0, n0, rm ); |
| 200 | | jest.set_parameters ( n0 );//duplication of rm |
| | 299 | MPF () : jest (pf,BMs) {}; |
| | 300 | void set_parameters ( shared_ptr<mpdf> par0, shared_ptr<mpdf> obs0, int n0, RESAMPLING_METHOD rm = SYSTEMATIC ) { |
| | 301 | pf->set_model ( par0, obs0); |
| | 302 | pf->set_parameters(n0, rm ); |
| | 332 | |
| | 333 | /*! configuration structure for basic PF |
| | 334 | \code |
| | 335 | BM = BM_class; // Bayesian filtr for analytical part of the model |
| | 336 | parameter_pdf = mpdf_class; // transitional pdf for non-parametric part of the model |
| | 337 | prior = epdf_class; // prior probability density |
| | 338 | --- optional --- |
| | 339 | n = 10; // number of particles |
| | 340 | resmethod = 'systematic', or 'multinomial', or 'stratified' |
| | 341 | // resampling method |
| | 342 | \endcode |
| | 343 | */ |
| | 344 | void from_setting(const Setting &set){ |
| | 345 | shared_ptr<mpdf> par = UI::build<mpdf>(set,"parameter_pdf",UI::compulsory); |
| | 346 | shared_ptr<mpdf> obs= new mpdf(); // not used!! |
| | 347 | |
| | 348 | pf = new PF; |
| | 349 | // rpior must be set before BM |
| | 350 | pf->prior_from_set(set); |
| | 351 | pf->resmethod_from_set(set); |
| | 352 | pf->set_model(par,obs); |
| | 353 | |
| | 354 | shared_ptr<BM> BM0 =UI::build<BM>(set,"BM",UI::compulsory); |
| | 355 | set_BM(*BM0); |
| | 356 | |
| | 357 | string opt; |
| | 358 | if (UI::get(opt,set,"options",UI::optional)){ |
| | 359 | set_options(opt); |
| | 360 | } |
| | 361 | //set drv |
| | 362 | //find potential input - what remains in rvc when we subtract rv |
| | 363 | RV u = par->_rvc().remove_time().subt( par->_rv() ); |
| | 364 | set_drv(concat(BM0->_drv(),u) ); |
| | 365 | validate(); |
| | 366 | } |
| | 367 | void validate(){ |
| | 368 | try{ |
| | 369 | pf->validate(); |
| | 370 | } catch (std::exception &e){ |
| | 371 | throw UIException("Error in PF part of MPF:"); |
| | 372 | } |
| | 373 | jest.read_parameters(); |
| | 374 | } |
| | 375 | |
| 237 | | |
| 238 | | template<class BM_T> |
| 239 | | void MPF<BM_T>::bayes ( const vec &dt ) { |
| 240 | | int i; |
| 241 | | vec lls ( n ); |
| 242 | | vec llsP ( n ); |
| 243 | | ivec ind; |
| 244 | | double mlls = -std::numeric_limits<double>::infinity(); |
| 245 | | |
| 246 | | #pragma omp parallel for |
| 247 | | for ( i = 0; i < n; i++ ) { |
| 248 | | //generate new samples from paramater evolution model; |
| 249 | | vec old_smp=_samples ( i ); |
| 250 | | _samples ( i ) = par->samplecond ( old_smp ); |
| 251 | | llsP ( i ) = par->evallogcond ( _samples ( i ), old_smp ); |
| 252 | | BMs ( i )->condition ( _samples ( i ) ); |
| 253 | | BMs ( i )->bayes ( dt ); |
| 254 | | lls ( i ) = BMs ( i )->_ll(); // lls above is also in proposal her must be lls(i) =, not +=!! |
| 255 | | if ( lls ( i ) > mlls ) mlls = lls ( i ); //find maximum likelihood (for numerical stability) |
| 256 | | } |
| 257 | | |
| 258 | | double sum_w = 0.0; |
| 259 | | // compute weights |
| 260 | | #pragma omp parallel for |
| 261 | | for ( i = 0; i < n; i++ ) { |
| 262 | | _w ( i ) *= exp ( lls ( i ) - mlls ); // multiply w by likelihood |
| 263 | | sum_w += _w ( i ); |
| 264 | | } |
| 265 | | |
| 266 | | if ( sum_w > 0.0 ) { |
| 267 | | _w /= sum_w; //? |
| 268 | | } else { |
| 269 | | cout << "sum(w)==0" << endl; |
| 270 | | } |
| 271 | | |
| 272 | | |
| 273 | | double eff = 1.0 / ( _w * _w ); |
| 274 | | if ( eff < ( 0.3*n ) ) { |
| 275 | | ind = est.resample ( resmethod ); |
| 276 | | // Resample Bms! |
| 277 | | |
| 278 | | #pragma omp parallel for |
| 279 | | for ( i = 0; i < n; i++ ) { |
| 280 | | if ( ind ( i ) != i ) {//replace the current Bm by a new one |
| 281 | | //fixme this would require new assignment operator |
| 282 | | // *Bms[i] = *Bms[ind ( i ) ]; |
| 283 | | |
| 284 | | // poor-man's solution: replicate constructor here |
| 285 | | // copied from MPF::MPF |
| 286 | | delete BMs ( i ); |
| 287 | | BMs ( i ) = new BM_T ( *BMs ( ind ( i ) ) ); //copy constructor |
| 288 | | const epdf& pom = BMs ( i )->posterior(); |
| 289 | | jest.set_elements ( i, 1.0 / n, &pom ); |
| 290 | | } |
| 291 | | }; |
| 292 | | cout << '.'; |
| 293 | | } |
| 294 | | } |
| | 377 | UIREGISTER(MPF); |