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); |