SedSat3 1.1.6
Sediment Source Apportionment Tool - Advanced statistical methods for environmental pollution research
Loading...
Searching...
No Matches
MCMC.hpp
Go to the documentation of this file.
1// MCMC.cpp : Defines the entry point for the console application.
2//
3
4#include <vector>
5#include "NormalDist.h"
6#include <string>
7#ifndef mac_version
8#include <omp.h>
9#endif
10#include "MCMC.h"
11#include "ProgressWindow.h"
12#include "Utilities.h"
13
14
15
16//using namespace std;
17
18template<class T>
20{
21}
22
23template<class T>
25{
26 Params.clear();
27 logp1.clear();
28 logp.clear();
29}
30
31
32template<class T>
34{
35 return &parameters->at(i);
36}
37
38
39template <class T>
41{
42 return (&observations->at(i));
43}
44
45template<class T>
46TimeSeriesSet<double> CMCMC<T>::model(vector<double> par)
47{
48 double sum = 0;
49 vector<TimeSeriesSet<double>> res;
50
51
52 T G1 = *Model;
53 G1.SetSilent(true);
54 G1.SetRecordResults(false);
55 G1.SetNumThreads(1);
56 for (int i=0; i<MCMC_Settings.number_of_parameters; i++)
57 G1.SetParameterValue(i, par[i]);
58
59 G1.ApplyParameters();
60 G1.Solve();
61 sum +=G1.GetObjectiveFunctionValue();
62
63 return G1.Outputs.ObservedOutputs;
64
65}
66
67template<class T>
68bool CMCMC<T>::SetProperty(const string &varname, const string &value)
69{
70
71 if (aquiutils::tolower(varname) == "number_of_samples") {MCMC_Settings.total_number_of_samples = aquiutils::atoi(value); return true;}
72 if (aquiutils::tolower(varname) == "number_of_chains") {MCMC_Settings.number_of_chains = aquiutils::atoi(value); return true;}
73 if (aquiutils::tolower(varname) == "number_of_burnout_samples") {MCMC_Settings.burnout_samples = aquiutils::atoi(value); return true;}
74 if (aquiutils::tolower(varname) == "initial_purturbation_factor") {MCMC_Settings.purturbation_factor = aquiutils::atof(value); return true;}
75 if (aquiutils::tolower(varname) == "record_interval") {MCMC_Settings.save_interval = aquiutils::atoi(value); return true;}
76 if (aquiutils::tolower(varname) == "initial_purturbation")
77 {
78 if (aquiutils::tolower(value)=="yes")
79 MCMC_Settings.noinipurt = false;
80 else
81 MCMC_Settings.noinipurt = true;
82 return true;
83 }
84 if (aquiutils::tolower(varname) == "perform_global_sensitivity")
85 {
86 if (aquiutils::tolower(value)=="yes")
87 MCMC_Settings.global_sensitivity = true;
88 else
89 MCMC_Settings.global_sensitivity = false;
90 return true;
91 }
92 if (aquiutils::tolower(varname) == "continue_based_on_file_name")
93 {
94 if (value!="")
95 { MCMC_Settings.continue_filename = value;
96 MCMC_Settings.continue_mcmc = true;
97 }
98 else
99 MCMC_Settings.continue_mcmc = false;
100 return true;
101 }
102 if (aquiutils::tolower(varname) == "samples_filename")
103 {
104 if (value!="")
105 {
106 if (value.find_first_of('/')!=string::npos || value.find_first_of('\\')!=string::npos)
107 FileInformation.outputfilename = value;
108 else
109 FileInformation.outputfilename = FileInformation.outputpath + value;
110 }
111
112
113 return true;
114 }
115 if (aquiutils::tolower(varname) == "number_of_post_estimate_realizations")
116 {
117 MCMC_Settings.number_of_post_estimate_realizations = aquiutils::atoi(value);
118 return true;
119 }
120 if (aquiutils::tolower(varname) == "increment_for_sensitivity_analysis")
121 {
122 MCMC_Settings.dp_sens = aquiutils::atof(value);
123 return true;
124 }
125 if (aquiutils::tolower(varname) == "add_noise_to_realizations")
126 {
127 if (aquiutils::tolower(value)=="yes")
128 MCMC_Settings.noise_realization_writeout = true;
129 else
130 MCMC_Settings.noise_realization_writeout = false;
131 return true;
132
133 }
134 if (aquiutils::tolower(varname) == "number_of_threads")
135 {
136 MCMC_Settings.numberOfThreads = aquiutils::atoi(value);
137 return true;
138 }
139 if (aquiutils::tolower(varname) == "acceptance_rate")
140 {
141 MCMC_Settings.acceptance_rate = aquiutils::atof(value);
142 return true;
143 }
144 if (aquiutils::tolower(varname) == "purturbation_change_scale")
145 {
146 MCMC_Settings.purt_change_scale = aquiutils::atof(value);
147 return true;
148 }
149 if (aquiutils::tolower(varname) == "dissolve_chains")
150 {
151 if (aquiutils::tolower(value)=="true")
152 MCMC_Settings.dissolve_chains = true;
153 else
154 MCMC_Settings.dissolve_chains = false;
155 return true;
156 }
157
158 last_error = "Property '" + varname + "' was not found!";
159 return false;
160}
161
162
163template<class T>
164double CMCMC<T>::posterior(vector<double> par, int chain_counter)
165{
166 double sum = 0;
167
168 for (int i = 0; i < MCMC_Settings.number_of_parameters; i++)
169 CopiedModels[chain_counter].SetParameterValue(i, par[i]);
170
171 for (int i = 0; i < MCMC_Settings.number_of_parameters; i++)
172 sum+=parameter(i)->CalcLogPriorProbability(par[i]);
173
174
175 sum+= -CopiedModels[chain_counter].GetObjectiveFunctionValue();
176 temp_predicted[chain_counter] = CopiedModels[chain_counter].GetPredictedValues();
177
178 return sum;
179}
180
181template<class T>
182void CMCMC<T>::model(T *Model1, vector<double> par)
183{
184
185 for (int i=0; i<MCMC_Settings.number_of_parameters; i++)
186 {
187 Model1->SetSilent(true);
188 Model1->SetRecordResults(false);
189 Model1->SetNumThreads(1);
190 for (unsigned int i = 0; i < MCMC_Settings.number_of_parameters; i++)
191 Model1->SetParameterValue(i, par[i]);
192 Model1->ApplyParameters();
193 }
194
195 Model1->Solve();
196
197}
198
199template<class T>
200void CMCMC<T>::initialize(CMBTimeSeriesSet *results, bool random)
201{
202 parameters = &Model->Parameters();
203 Params.resize(MCMC_Settings.total_number_of_samples);
204 logp.resize(MCMC_Settings.total_number_of_samples);
205 logp1.resize(MCMC_Settings.total_number_of_samples);
206 pertcoeff.resize(parameters->size());
207 MCMC_Settings.number_of_parameters = Model->Parameters().size();
208
209 for (unsigned int i=0; i<MCMC_Settings.total_number_of_samples; i++)
210 Params[i].resize(MCMC_Settings.number_of_parameters);
211
212 results->resize(MCMC_Settings.number_of_parameters);
213 results->SetAllSeriesSize(MCMC_Settings.total_number_of_samples);
214 predicted.resize(Model->ObservationsCount());
215 predicted.SetAllSeriesSize(MCMC_Settings.total_number_of_samples);
216 temp_predicted.resize(MCMC_Settings.number_of_chains);
217 CopiedModels.resize(MCMC_Settings.number_of_chains);
218 for (unsigned int i=0; i<MCMC_Settings.number_of_chains; i++)
219 {
220 CopiedModels[i] = *Model;
221 }
222 double pp=0;
223 for (int j = 0; j<MCMC_Settings.number_of_parameters; j++)
224 {
225 if (parameter(j)->GetPriorDistribution()=="normal" || parameter(j)->GetPriorDistribution()=="uniform")
226 {
227 pertcoeff[j] = MCMC_Settings.purturbation_factor*(-parameter(j)->GetRange(_range::low) + parameter(j)->GetRange(_range::high));
228 }
229 if (parameter(j)->GetPriorDistribution()=="log-normal")
230 {
231 pertcoeff[j] = MCMC_Settings.purturbation_factor*(-log(parameter(j)->GetRange(_range::low)) + log(parameter(j)->GetRange(_range::high)));
232 }
233 }
234
235 if (random)
236 { for (int j=0; j<MCMC_Settings.number_of_chains; j++)
237 {
238 double posterior_value = -2e6;
239 while (posterior_value<-1e6)
240 { for (int i=0; i<MCMC_Settings.number_of_parameters; i++)
241 { if (parameter(i)->GetPriorDistribution()=="log-normal")
242 Params[j][i] = exp(log(parameter(i)->GetRange(_range::low))+(log(parameter(i)->GetRange(_range::high))-log(parameter(i)->GetRange(_range::low)))*unitrandom());
243 else
244 Params[j][i] = parameter(i)->GetRange(_range::low)+(parameter(i)->GetRange(_range::high)-parameter(i)->GetRange(_range::low))*unitrandom();
245 if (parameter(i)->GetPriorDistribution()=="log-normal")
246 pp += log(Params[j][i]);
247 }
248
249 logp[j] = posterior(Params[j],j);
250 posterior_value = logp[j];
251 logp1[j] = logp[j]+pp;
252 }
253 results->SetRow(j,j,Params[j]);
254 cout<<"success!";
255 predicted.SetRow(j,j,CopiedModels[j].GetPredictedValues().vec);
256 temp_predicted[j] = CopiedModels[j].GetPredictedValues();
257 }
258 }
259
260 else
261 {
262 for (int j=0; j<MCMC_Settings.number_of_chains; j++)
263 { for (int i=0; i<MCMC_Settings.number_of_parameters; i++)
264 { Params[j][i] = parameter(i)->GetValue();
265 if (parameter(i)->GetPriorDistribution()=="log-normal")
266 pp += log(Params[j][i]);
267 }
268 logp[j] = posterior(Params[j],j);
269 logp1[j] = logp[j]+pp;
270 }
271 }
272
273}
274
275
276
277template<class T>
278void CMCMC<T>::initialize(vector<double> par)
279{
280
281 if (MCMC_Settings.sensbasedpurt == true)
282 {
283 CVector X = sensitivity(1e-4, par);
284
285 for (int j = 0; j<MCMC_Settings.number_of_parameters; j++)
286 {
287 if (parameter(j).Get_Distribution()=="normal" || parameter(j).Get_Distribution()=="uniform")
288 {
289 pertcoeff[j] = MCMC_Settings.purturbation_factor / fabs(X[getparamno(j, 0)]);
290 }
291 if (parameter(j).Get_Distribution()=="log-normal")
292 {
293 pertcoeff[j] = MCMC_Settings.purturbation_factor / fabs(sqrt(par[j])*X[getparamno(j, 0)]);
294 }
295
296 }
297 }
298 else
299 for (int j = 0; j<MCMC_Settings.number_of_parameters; j++)
300 {
301 if (parameter(j).Get_Distribution()=="normal" || parameter(j).Get_Distribution()=="uniform")
302 {
303 pertcoeff[j] = MCMC_Settings.purturbation_factor*(-parameter(j)->GetRange().low + -parameter(j)->GetRange().high);
304 }
305 if (parameter(j).Get_Distribution()=="log-normal")
306 {
307 pertcoeff[j] = MCMC_Settings.purturbation_factor*(-log(parameter(j)->GetRange().low) + log(parameter(j)->GetRange().high));
308 }
309 }
310 double alpha;
311 if (MCMC_Settings.noinipurt == true) alpha = 0; else alpha = 1;
312
313
314 for (int j = 0; j<MCMC_Settings.number_of_chains; j++)
315 {
316 Params[j].resize(MCMC_Settings.number_of_parameters);
317 double pp = 0;
318 for (int i = 0; i<MCMC_Settings.number_of_parameters; i++)
319 {
320 if (parameter(i).Get_Distribution()=="normal" || parameter(i).Get_Distribution()=="uniform")
321 Params[j][i] = par[i] + alpha*getnormalrand(0, pertcoeff[i]);
322 else
323 { Params[j][i] = par[i] * exp(alpha*getnormalrand(0, pertcoeff[i]));
324 pp+=log(par[i]);
325 }
326 if (parameter(i).Get_Distribution()=="uniform")
327 while ((Params[j][i]<parameter(i).GetRange().low) || (Params[j][i]>parameter(i).GetRange(_range::high)))
328 Params[j][i] = par[i] + alpha*getnormalrand(0, pertcoeff[i]);
329
330 }
331 logp[j] = posterior(Params[j]);
332 logp1[j] = logp[j] + pp;
333 }
334}
335
336template<class T>
337bool CMCMC<T>::step(int k, int chain_counter)
338{
339
340 vector<double> X = purturb(k-MCMC_Settings.number_of_chains);
341 double pp =0;
342 for (int i=0; i<MCMC_Settings.number_of_parameters; i++)
343 {
344 if (parameter(i)->GetPriorDistribution()=="log-normal")
345 pp += log(X[i]);
346 }
347 double logp_0 = posterior(X,chain_counter) + pp;
348
350 double logp_1 = logp_0;
351 bool res;
352
353
354 if (unitrandom() <exp(logp_0-logp[k-MCMC_Settings.number_of_chains]) && !isnan(logp_0))
355 {
356 res=true;
357 Params[k] = X;
358 logp[k] = logp_0;
359 logp1[k] = logp_1;
360 predicted.SetRow(k,k,temp_predicted[chain_counter].vec);
361
362 //accepted_count += 1;
363 }
364 else
365 {
366 res = false;
367 Params[k] = Params[k-MCMC_Settings.number_of_chains];
368 logp[k] = logp[k-MCMC_Settings.number_of_chains];
369 logp1[k] = logp_1;
370 predicted.SetRow(k,k,predicted.getrow(k-MCMC_Settings.number_of_chains));
371 }
372 //total_count += 1;
373 return res;
374}
375
376template<class T>
377vector<double> CMCMC<T>::purturb(int k)
378{
379 vector<double> X;
380 X.resize(MCMC_Settings.number_of_parameters);
381 for (int i=0; i<MCMC_Settings.number_of_parameters; i++)
382 {
383 if (parameter(i)->GetPriorDistribution() == "log-normal")
384 X[i] = Params[k][i]*exp(pertcoeff[i]*getstdnormalrand());
385 else
386 X[i] = Params[k][i]+pertcoeff[i]*getstdnormalrand();
387
388 }
389 return X;
390}
391
392template<class T>
393bool CMCMC<T>::step(int k, int nsamps, string filename, CMBTimeSeriesSet *results, ProgressWindow *rtw)
394{
395 FILE *file;
396 if (!MCMC_Settings.continue_mcmc)
397 { file = fopen(filename.c_str(),"w");
398 fclose(file);
399 }
400 qDebug()<<5;
401 if (!MCMC_Settings.continue_mcmc)
402 {
403 file = fopen(filename.c_str(),"a");
404 fprintf(file,"%s, ", "no.");
405 for (unsigned int i=0; i<MCMC_Settings.number_of_parameters; i++)
406 { fprintf(file, "%s, ", parameter(i)->Name().c_str());
407 results->setname(i,parameter(i)->Name());
408 }
409 fprintf(file,"%s, %s, %s,", "logp", "logp_1", "stuck_counter");
410 for (unsigned int j=0; j<pertcoeff.size(); j++) fprintf(file,"%s,", string("purt_coeff_" + QString("%1").arg(j).toStdString()).c_str());
411 fprintf(file, "\n");
412 fclose(file);
413 }
414
415 CVector stuckcounter(MCMC_Settings.number_of_chains);
416 CVector accepted(MCMC_Settings.number_of_chains);
417
418 MCMC_Settings.ini_purt_fact = pertcoeff[0];
419 int k_0 = k;
420 qDebug()<<6;
421 for (unsigned int kk=k; kk<k+nsamps+MCMC_Settings.number_of_chains; kk+=MCMC_Settings.number_of_chains)
422 {
423 QCoreApplication::processEvents(QEventLoop::AllEvents,10*1000);
424
425#ifndef NO_OPENMP
426 omp_set_num_threads(MCMC_Settings.numberOfThreads);
427#endif
428
429
430#ifdef WIN64
431#pragma omp parallel
432 {
433 srand(int(time(NULL)) ^ omp_get_thread_num() + kk);
434 }
435#endif
436qDebug()<<7;
437#pragma omp parallel for
438 for (int jj = kk; jj < min(kk + MCMC_Settings.number_of_chains, MCMC_Settings.total_number_of_samples); jj++)
439 {
440 qDebug() << "Starting step: " + QString::number(jj);
441 bool stepstuck = !step(jj,jj-kk);
442 qDebug() << "Step: " + QString::number(jj) + "Done!";
443 if (stepstuck)
444 { stuckcounter[jj - kk]++;
445 accepted[jj-kk]=0;
446 }
447 else
448 { stuckcounter[jj - kk] = 0;
449 accepted[jj-kk]=1;
450 }
451
452 }
454 accepted_count += accepted.sum();
455 total_count += accepted.num;
456 QCoreApplication::processEvents(QEventLoop::AllEvents,100*1000);
457
458 if ((kk-k_0) % (50 * MCMC_Settings.number_of_chains) == 0 || kk == k + nsamps + MCMC_Settings.number_of_chains - 1)
459 {
460
461 if (MCMC_Settings.dissolve_chains)
462 { int_value_pair minchain = Min(logp,min(kk + MCMC_Settings.number_of_chains, MCMC_Settings.total_number_of_samples),MCMC_Settings.number_of_chains);
463 int_value_pair maxchain = Max(logp,min(kk + MCMC_Settings.number_of_chains, MCMC_Settings.total_number_of_samples),MCMC_Settings.number_of_chains);
464 double ratio = maxchain.value-minchain.value;
465 qDebug()<<"Ratio:"<<ratio;
466 if (ratio>5)
468 Params[minchain.counter] = Params[maxchain.counter];
469 logp[minchain.counter] = logp[maxchain.counter];
470 logp1[minchain.counter] = logp1[maxchain.counter];
471 }
472 }
473 file = fopen(filename.c_str(), "a");
474 for (int jj = max(int(min(kk + MCMC_Settings.number_of_chains, MCMC_Settings.total_number_of_samples) - 50 * MCMC_Settings.number_of_chains), k_0); jj < min(kk + MCMC_Settings.number_of_chains, MCMC_Settings.total_number_of_samples); jj++)
475 {
476 if (jj%MCMC_Settings.save_interval == 0)
477 {
478 //QCoreApplication::processEvents(QEventLoop::AllEvents,100*1000);
479
480 fprintf(file, "%i, ", jj);
481 for (int i = 0; i < MCMC_Settings.number_of_parameters; i++)
482 fprintf(file, "%le, ", Params[jj][i]);
483 if (!results->SetRow(jj, jj,Params[jj]))
484 {
485 cout<<"not enough room!";
487
488 fprintf(file, "%le, %le, %f,", logp[jj], logp1[jj], stuckcounter[jj%MCMC_Settings.number_of_chains]);
489 for (int j = 0; j < pertcoeff.size(); j++) fprintf(file, "%le,", pertcoeff[j]);
490 fprintf(file, "\n");
491
492 }
493
494 //cout << jj << "," << pertcoeff[0] << "," << stuckcounter.max() << "," << stuckcounter.min() << endl;
496 //if (jj<n_burnout)
497 }
498 fclose(file);
499 }
500
501 if ((kk-k_0) % (50*MCMC_Settings.number_of_chains) == 0)
502 {
503
504 if (double(accepted_count) / double(total_count)>MCMC_Settings.acceptance_rate)
505 for (int i = 0; i < MCMC_Settings.number_of_parameters; i++) pertcoeff[i] /= MCMC_Settings.purt_change_scale;
506 else
507 for (int i = 0; i < MCMC_Settings.number_of_parameters; i++) pertcoeff[i] *= MCMC_Settings.purt_change_scale;
508 accepted_count = 0;
509 total_count = 0;
510
511 }
512
513
514 if (rtw)
515 {
516 double average_log_p = CVector::Extract(logp,kk-100,kk).mean();
517 double progress = double(kk) / double(nsamps)*0.98;
518 rtw->SetProgress(progress);
519 rtw->AppendPoint(kk,double(accepted_count) / double(total_count),0);
520 rtw->AppendPoint(kk,double(pertcoeff[0] / MCMC_Settings.ini_purt_fact),1);
521 rtw->AppendPoint(kk,double(average_log_p),2);
522 QCoreApplication::processEvents();
523 }
524 }
525 qDebug()<<"MCMC done!";
526 return 0;
527}
528
529template<class T>
531{
532 rtw = _rtw;
533}
534
535template<class T>
537{
538 Model = _system;
539 MCMC_Settings.number_of_parameters = 0;
540 MCMC_Settings.numberOfThreads = 20;
541 FileInformation.outputpath = Model->OutputPath();
542
543 for (unsigned int i=0; i<Model->Parameters().size(); i++)
544 {
545 MCMC_Settings.number_of_parameters++;
546 params.push_back(i);
547 }
548 parameters = &Model->Parameters();
549 observations = Model->Observations();
550 pertcoeff.resize(parameters->size());
551}
552
553template<class T>
554CVector CMCMC<T>::sensitivity(double d, vector<double> par)
555{
556
557 double base = posterior(par);
558 CVector X(MCMC_Settings.number_of_parameters);
559 for (int i=0; i<MCMC_Settings.number_of_parameters; i++)
560 {
561 vector<double> par1 = par;
562 par1[i]=par[i]*(1+d);
563 double base_1 = posterior(par1);
564
565 X[i] = (sqrt(fabs(base))-sqrt(fabs(base_1)))/(d*par[i]);
566 }
567 return X;
568}
569
570
571template<class T>
572CVector CMCMC<T>::sensitivity_ln(double d, vector<double> par)
574
575 CVector X = sensitivity(d, par);
576 for (int i=0; i<MCMC_Settings.number_of_parameters; i++)
577 {
578 X[i] = par[i]*X[i];
579 }
580 return X;
581}
582
583template<class T>
584int CMCMC<T>::readfromfile(string filename)
585{
586 ifstream file(filename);
587 vector<string> s;
588 s = aquiutils::getline(file);
589 int jj=0;
590 while (file.eof() == false)
591 {
592 s = aquiutils::getline(file);
593 if (s.size() == 2*MCMC_Settings.number_of_parameters+4)
594 { Params[jj].resize(MCMC_Settings.number_of_parameters);
595 for (int i=0; i<MCMC_Settings.number_of_parameters; i++)
596 {
597 Params[jj][i] = atof(s[i+1].c_str());
598 pertcoeff[i] = atof(s[MCMC_Settings.number_of_parameters+i+4].c_str());
599 }
600 logp[jj] = atof(s[MCMC_Settings.number_of_parameters+1].c_str());
601 logp1[jj] = atof(s[MCMC_Settings.number_of_parameters+2].c_str());
602 jj++;
603 }
604 }
605 file.close();
606 return jj;
607}
608
609template<class T>
610TimeSeriesSet<double> CMCMC<T>::prior_distribution(int n_bins)
611{
612 TimeSeriesSet<double> prior_dist(MCMC_Settings.number_of_parameters);
613 TimeSeries<double> B(n_bins);
614
615 double min_range , max_range;
616
617 for (int i=0; i<MCMC_Settings.number_of_parameters; i++)
618 {
619 if (parameter(i).GetDistribution() != "log-normal")
620 {
621 min_range = parameter(i)->mean() - 4*parameter(i)->std();
622 max_range = parameter(i)->mean() + 4*parameter(i)->std();;
623 }
624 if (parameter(i).GetDistribution() == "log-normal")
625 {
626 min_range = parameter(i)->mean() * exp(-4*parameter(i)->std());
627 max_range = parameter(i)->mean() * exp(4*parameter(i)->std());
628 }
629
630
631 double dp = abs(max_range - min_range) / n_bins;
632
633 B.setTime(0, min_range + dp/2);
634 for (int j=0; j<n_bins-1; j++)
635 B.setTime(j+1, B.getTime(j) + dp);
636
637 if (parameter(i).GetDistribution() != "log-normal")
638 for (int j=0; j<n_bins; j++)
639 B.setValue(j , exp(-pow(B.getTime(j)-parameter(i)->mean(),2)/(2.0*pow(parameter(i)->std(),2)))/(parameter(i)->std()*pow(6.28,0.5)));
640
641 if (parameter(i).GetDistribution() == "log-normal")
642 for (int j=0; j<n_bins; j++)
643 B.setValue(j, exp(-pow(log(B.getTime(j))-log(parameter(i)->mean()),2)/(2.0*pow(parameter(i)->std(),2)))/(B.getTime(j)*parameter(i)->std()*pow(6.28,0.5)));
644
645 prior_dist.at(i) = B;
646 }
647
648 return prior_dist;
649}
650
651template<class T>
652void CMCMC<T>::ProduceRealizations(TimeSeriesSet<double> &MCMCout)
653{
654
655 vector<TimeSeriesSet<double>> realized_timeseries(observations->size());
656 vector<TimeSeriesSet<double>> predicted_percentiles(observations->size());
657
658 for (unsigned int jj = 0; jj <=MCMC_Settings.number_of_post_estimate_realizations/MCMC_Settings.numberOfThreads; jj++)
659 {
660 vector<T> Sys1(MCMC_Settings.numberOfThreads);
661#ifndef NO_OPENMP
662 omp_set_num_threads(MCMC_Settings.numberOfThreads);
663#endif
664#pragma omp parallel for
665 for (int j = 0; j < min(MCMC_Settings.numberOfThreads, MCMC_Settings.number_of_post_estimate_realizations - jj*MCMC_Settings.numberOfThreads); j++)
666 {
667 Sys1[j] = *Model;
668 vector<double> sampled_parameters = MCMCout.getrandom(MCMC_Settings.burnout_samples);
669 model(&Sys1[j],sampled_parameters);
670 }
671
672 for (unsigned int j = 0; j < min(MCMC_Settings.numberOfThreads, MCMC_Settings.number_of_post_estimate_realizations - jj*MCMC_Settings.numberOfThreads); j++)
673 for (unsigned int i=0; i<observations->size(); i++)
674 realized_timeseries[i].append(*(Sys1[j].observation(i)->GetModeledTimeSeries()));
675
676 if (rtw)
677 {
678 double progress = double(jj*MCMC_Settings.numberOfThreads) / double(MCMC_Settings.number_of_post_estimate_realizations);
679 rtw->SetProgress(progress);
680 }
681 }
682 vector<double> percents; percents.push_back(0.025); percents.push_back(0.5); percents.push_back(0.975);
683 for (unsigned int i=0; i<observations->size(); i++)
684 {
685 realized_timeseries[i].write(FileInformation.outputpath + "Realizations_" + observation(i)->GetName() + ".txt");
686 predicted_percentiles[i] = realized_timeseries[i].getpercentiles(percents);
687 observation(i)->SetPercentile95(predicted_percentiles[i]);
688 predicted_percentiles[i].write(FileInformation.outputpath + "Predicted_95p_Bracket" + observation(i)->GetName() + ".txt");
689 observation(i)->SetRealizations(realized_timeseries[i]);
690
691 }
692 rtw->SetProgress(1);
693}
695template<class T>
696void CMCMC<T>::get_outputpercentiles(TimeSeriesSet<double> &MCMCout)
697{
698
699 ProduceRealizations(MCMCout);
700 int n_BTCout_obs = Model->ObservationsCount();
701
702 BTCout_obs_prcntle.resize(1); for (int j = 0; j < 1; j++) BTCout_obs_prcntle[j].resize(n_BTCout_obs);
703 BTCout_obs_prcntle_noise.resize(1); for (int j = 0; j < 1; j++) BTCout_obs_prcntle_noise[j].resize(n_BTCout_obs);
704
705 if (calc_output_percentiles.size()>0)
706 for (int i = 0; i < n_BTCout_obs; i++)
707 {
708 for (int j = 0; j < 1; j++)
709 {
710 BTCout_obs_prcntle[j][i] = BTCout_obs[j][i].getpercentiles(calc_output_percentiles);
711
712 BTCout_obs_prcntle[j][i].write(FileInformation.outputpath + "BTC_obs_prcntl_" + Model->Observation(i)->GetName() + ".txt");
713
714 if (MCMC_Settings.noise_realization_writeout)
715 BTCout_obs_prcntle_noise[j][i] = BTCout_obs_noise[j][i].getpercentiles(calc_output_percentiles);
716
717 BTCout_obs_prcntle_noise[j][i].write(FileInformation.outputpath + "BTC_obs_prcntl_noise_" + Model->Observation(i)->GetName() + ".txt");
718
719 }
720 }
721
722}
723
724template<class T>
726{
727 initialize(false);
728 int mcmcstart = MCMC_Settings.number_of_chains;
729 if (MCMC_Settings.continue_mcmc)
730 {
731 //if (rtw) rtw->AppendText("Reading samples from ... " + MCMC_Settings.continue_filename);
732 mcmcstart = readfromfile(MCMC_Settings.continue_filename);
733 }
734 //if (rtw) rtw->AppendText(string("Generating samples ... "));
735 step(mcmcstart, int((MCMC_Settings.total_number_of_samples - mcmcstart) / MCMC_Settings.number_of_chains)*MCMC_Settings.number_of_chains, FileInformation.outputfilename , rtw);
736 //if (rtw) rtw->AppendText(string("Creating posterior distribution ..."));
737 TimeSeriesSet<double> all_posterior_distributions;
738 TimeSeriesSet<double> parameter_samples;
739 for (unsigned int i=0; i<parameters->size(); i++)
740 {
741 TimeSeriesSet<double> chain_values(MCMC_Settings.number_of_chains);
742 TimeSeries<double> all_samples;
743 for (unsigned int i=0; i<MCMC_Settings.number_of_chains; i++)
744 {
745 chain_values.setname(i,"Chain_" + aquiutils::numbertostring(i));
746 }
747 for (unsigned int j=MCMC_Settings.burnout_samples; j<MCMC_Settings.total_number_of_samples; j++)
748 chain_values[j%MCMC_Settings.number_of_chains].append(j,Params[j][i]);
749
750 for (unsigned int i=0; i<MCMC_Settings.number_of_chains; i++)
751 {
752 all_samples.append(chain_values[i]);
753 }
754
755 //chain_values.name = parameter(i)->GetName();
756 parameter(i)->SetMCMCSamples(chain_values);
757
758 TimeSeries<double> posterior_distribution = all_samples.distribution(all_samples.size()/100,0);
759 all_posterior_distributions.append(posterior_distribution,parameter(i)->GetName());
760 posterior_distribution.setName("Posterior density");
761 parameter(i)->SetPosteriorDistribution(posterior_distribution);
762 parameter_samples.append(all_samples);
763
764 }
765 all_posterior_distributions.write(FileInformation.outputpath + "Posterior_distributions.txt");
766 //if (rtw) rtw->AppendText(string("Generating Realizations ..."));
767 ProduceRealizations(parameter_samples);
768}
769
770template<class T>
771int_value_pair CMCMC<T>::Min(const vector<double> &vec, int current_counter, int n_chains)
772{
773 int_value_pair out;
774 out.value = 1e12;
775 for (unsigned int i=max(current_counter-n_chains,0); i<current_counter; i++)
776 {
777 if (vec[i]<out.value)
778 {
779 out.value = vec[i];
780 out.counter = i;
781 }
782 }
783 return out;
784}
785
786template<class T>
787int_value_pair CMCMC<T>::Max(const vector<double> &vec, int current_counter, int n_chains)
789 int_value_pair out;
790 out.value = -1e12;
791 for (unsigned int i=max(current_counter-n_chains,0); i<current_counter; i++)
792 {
793 if (vec[i]>out.value)
794 {
795 out.value = vec[i];
796 out.counter = i;
797 }
798 }
799 return out;
800}
801
Collection of time series with labels and observed values.
void model(T *Model1, vector< double > par)
Evaluate model with given parameters.
Definition MCMC.hpp:182
bool SetProperty(const string &varname, const string &value)
Set MCMC properties from string key-value pairs.
Definition MCMC.hpp:68
TimeSeriesSet< double > prior_distribution(int n_bins)
Generate histogram of prior distributions.
Definition MCMC.hpp:610
void ProduceRealizations(TimeSeriesSet< double > &MCMCout)
Generate posterior predictive realizations.
Definition MCMC.hpp:652
Observation * observation(int i)
Get pointer to specific observation.
Definition MCMC.hpp:40
vector< double > purturb(int k)
Generate proposed parameter values by perturbing current state.
Definition MCMC.hpp:377
CMCMC(void)
Default constructor.
Definition MCMC.hpp:19
bool step(int k, int chain_counter)
Perform single MCMC step for one chain.
Definition MCMC.hpp:337
Parameter * parameter(int i)
Get pointer to specific parameter.
Definition MCMC.hpp:33
int_value_pair Max(const vector< double > &vec, int current_counter, int n_chains)
Find maximum value and its chain index.
Definition MCMC.hpp:787
double posterior(vector< double > par, int chain_counter)
Calculate log-posterior probability for given parameters.
Definition MCMC.hpp:164
void Perform()
Main entry point to run complete MCMC analysis.
Definition MCMC.hpp:725
void initialize(CMBTimeSeriesSet *results, bool random=false)
Initialize MCMC chains with starting parameter values.
Definition MCMC.hpp:200
int_value_pair Min(const vector< double > &vec, int current_counter, int n_chains)
Find minimum value and its chain index.
Definition MCMC.hpp:771
CVector sensitivity(double d, vector< double > par)
Calculate sensitivity of model output to parameters.
Definition MCMC.hpp:554
void get_outputpercentiles(TimeSeriesSet< double > &MCMCout)
Calculate percentiles of model outputs from MCMC samples.
Definition MCMC.hpp:696
CVector sensitivity_ln(double d, vector< double > par)
Calculate log-space sensitivity (for lognormal parameters)
Definition MCMC.hpp:572
int readfromfile(string filename)
Read MCMC state from file to continue previous run.
Definition MCMC.hpp:584
void SetRunTimeWindow(ProgressWindow *_rtw)
Set progress window for GUI updates.
Definition MCMC.hpp:530
~CMCMC(void)
Destructor.
Definition MCMC.hpp:24
Represents a model parameter with prior distribution and constraints.
Definition parameter.h:73
void AppendPoint(const double &x, const double &y, int chart=0)
void SetProgress(const double &prog)
@ low
Lower bound of the parameter range.
@ high
Upper bound of the parameter range.
Utility structure pairing an integer counter with a double value.
Definition MCMC.h:236
double value
Associated value (likelihood, parameter, etc.)
Definition MCMC.h:238
int counter
Chain or sample index.
Definition MCMC.h:237