Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 : Copyright (c) 2016-2019 The plumed team
3 : (see the PEOPLE file at the root of the distribution for a list of names)
4 :
5 : See http://www.plumed.org for more information.
6 :
7 : This file is part of plumed, version 2.
8 :
9 : plumed is free software: you can redistribute it and/or modify
10 : it under the terms of the GNU Lesser General Public License as published by
11 : the Free Software Foundation, either version 3 of the License, or
12 : (at your option) any later version.
13 :
14 : plumed is distributed in the hope that it will be useful,
15 : but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : GNU Lesser General Public License for more details.
18 :
19 : You should have received a copy of the GNU Lesser General Public License
20 : along with plumed. If not, see <http://www.gnu.org/licenses/>.
21 : +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
22 :
23 : #include "bias/Bias.h"
24 : #include "bias/ActionRegister.h"
25 : #include "core/PlumedMain.h"
26 : #include "core/Atoms.h"
27 : #include "core/Value.h"
28 : #include "tools/File.h"
29 : #include "tools/OpenMP.h"
30 : #include "tools/Random.h"
31 : #include <cmath>
32 : #include <ctime>
33 : #include <numeric>
34 : using namespace std;
35 :
36 : #ifndef M_PI
37 : #define M_PI 3.14159265358979323846
38 : #endif
39 :
40 : namespace PLMD {
41 : namespace isdb {
42 :
43 : //+PLUMEDOC ISDB_BIAS METAINFERENCE
44 : /*
45 : Calculates the Metainference energy for a set of experimental data.
46 :
47 : Metainference \cite Bonomi:2016ip is a Bayesian framework
48 : to model heterogeneous systems by integrating prior information with noisy, ensemble-averaged data.
49 : Metainference models a system and quantifies the level of noise in the data by considering a set of replicas of the system.
50 :
51 : Calculated experimental data are given in input as ARG while reference experimental values
52 : can be given either from fixed components of other actions using PARARG or as numbers using
53 : PARAMETERS. The default behavior is that of averaging the data over the available replicas,
54 : if this is not wanted the keyword NOENSEMBLE prevent this averaging.
55 :
56 : Metadynamic Metainference \cite Bonomi:2016ge or more in general biased Metainference requires the knowledge of
57 : biasing potential in order to calculate the weighted average. In this case the value of the bias
58 : can be provided as the last argument in ARG and adding the keyword REWEIGHT. To avoid the noise
59 : resulting from the instantaneus value of the bias the weight of each replica can be averaged
60 : over a give time using the keyword AVERAGING.
61 :
62 : The data can be averaged by using multiple replicas and weighted for a bias if present.
63 : The functional form of Metainference can be chosen among four variants selected
64 : with NOISE=GAUSS,MGAUSS,OUTLIERS,MOUTLIERS,GENERIC which correspond to modelling the noise for
65 : the arguments as a single gaussian common to all the data points, a gaussian per data
66 : point, a single long-tailed gaussian common to all the data points, a log-tailed
67 : gaussian per data point or using two distinct noises as for the most general formulation of Metainference.
68 : In this latter case the noise of the replica-averaging is gaussian (one per data point) and the noise for
69 : the comparison with the experiemntal data can chosen using the keywork LIKELIHOOD
70 : between gaussian or log-normal (one per data point), furthermore the evolution of the estimated average
71 : over an infinite number of replicas is driven by DFTILDE.
72 :
73 : As for Metainference theory there are two sigma values: SIGMA_MEAN represent the
74 : error of calculating an average quantity using a finite set of replica and should
75 : be set as small as possible following the guidelines for replica-averaged simulations
76 : in the framework of the Maximum Entropy Principle. Alternatively, this can be obtained
77 : automatically using the internal sigma mean optimisation as introduced in \cite Lohr:2017gc
78 : (OPTSIGMAMEAN=SEM), in this second case sigma_mean is estimated from the maximum standard error
79 : of the mean either over the simulation or over a defined time using the keyword AVERAGING.
80 : SIGMA_BIAS is an uncertainty parameter, sampled by a MC algorithm in the bounded interval
81 : defined by SIGMA_MIN and SIGMA_MAX. The initial value is set at SIGMA0. The MC move is a
82 : random displacement of maximum value equal to DSIGMA. If the number of data point is
83 : too large and the acceptance rate drops it is possible to make the MC move over mutually
84 : exclusive, random subset of size MC_CHUNKSIZE and run more than one move setting MC_STRIDE
85 : in such a way that MC_CHUNKSIZE*MC_STEPS will cover all the data points.
86 :
87 : Calculated and experimental data can be compared modulo a scaling factor and/or an offset
88 : using SCALEDATA and/or ADDOFFSET, the sampling is obtained by a MC algorithm either using
89 : a flat or a gaussian prior setting it with SCALE_PRIOR or OFFSET_PRIOR.
90 :
91 : \par Examples
92 :
93 : In the following example we calculate a set of \ref RDC, take the replica-average of
94 : them and comparing them with a set of experimental values. RDCs are compared with
95 : the experimental data but for a multiplication factor SCALE that is also sampled by
96 : MC on-the-fly
97 :
98 : \plumedfile
99 : RDC ...
100 : LABEL=rdc
101 : SCALE=0.0001
102 : GYROM=-72.5388
103 : ATOMS1=22,23
104 : ATOMS2=25,27
105 : ATOMS3=29,31
106 : ATOMS4=33,34
107 : ... RDC
108 :
109 : METAINFERENCE ...
110 : ARG=rdc.*
111 : NOISETYPE=MGAUSS
112 : PARAMETERS=1.9190,2.9190,3.9190,4.9190
113 : SCALEDATA SCALE0=1 SCALE_MIN=0.1 SCALE_MAX=3 DSCALE=0.01
114 : SIGMA0=0.01 SIGMA_MIN=0.00001 SIGMA_MAX=3 DSIGMA=0.01
115 : SIGMA_MEAN=0.001
116 : LABEL=spe
117 : ... METAINFERENCE
118 :
119 : PRINT ARG=spe.bias FILE=BIAS STRIDE=1
120 : \endplumedfile
121 :
122 : in the following example instead of using one uncertainty parameter per data point we use
123 : a single uncertainty value in a long-tailed gaussian to take into account for outliers, furthermore
124 : the data are weighted for the bias applied to other variables of the system.
125 :
126 : \plumedfile
127 : cv1: TORSION ATOMS=1,2,3,4
128 : cv2: TORSION ATOMS=2,3,4,5
129 : mm: METAD ARG=cv1,cv2 HEIGHT=0.5 SIGMA=0.3,0.3 PACE=200 BIASFACTOR=8 WALKERS_MPI
130 :
131 : METAINFERENCE ...
132 : ARG=rdc.*,mm.bias
133 : REWEIGHT
134 : NOISETYPE=OUTLIERS
135 : PARAMETERS=1.9190,2.9190,3.9190,4.9190
136 : SCALEDATA SCALE0=1 SCALE_MIN=0.1 SCALE_MAX=3 DSCALE=0.01
137 : SIGMA0=0.01 SIGMA_MIN=0.00001 SIGMA_MAX=3 DSIGMA=0.01
138 : SIGMA_MEAN=0.001
139 : LABEL=spe
140 : ... METAINFERENCE
141 : \endplumedfile
142 :
143 : (See also \ref RDC, \ref PBMETAD).
144 :
145 : */
146 : //+ENDPLUMEDOC
147 :
148 : class Metainference : public bias::Bias
149 : {
150 : // experimental values
151 : vector<double> parameters;
152 : // noise type
153 : unsigned noise_type_;
154 : enum { GAUSS, MGAUSS, OUTLIERS, MOUTLIERS, GENERIC };
155 : unsigned gen_likelihood_;
156 : enum { LIKE_GAUSS, LIKE_LOGN };
157 : // scale is data scaling factor
158 : // noise type
159 : unsigned scale_prior_;
160 : enum { SC_GAUSS, SC_FLAT };
161 : bool doscale_;
162 : double scale_;
163 : double scale_mu_;
164 : double scale_min_;
165 : double scale_max_;
166 : double Dscale_;
167 : // scale is data scaling factor
168 : // noise type
169 : unsigned offset_prior_;
170 : bool dooffset_;
171 : double offset_;
172 : double offset_mu_;
173 : double offset_min_;
174 : double offset_max_;
175 : double Doffset_;
176 : // sigma is data uncertainty
177 : vector<double> sigma_;
178 : vector<double> sigma_min_;
179 : vector<double> sigma_max_;
180 : vector<double> Dsigma_;
181 : // sigma_mean is uncertainty in the mean estimate
182 : vector<double> sigma_mean2_;
183 : // this is the estimator of the mean value per replica for generic metainference
184 : vector<double> ftilde_;
185 : double Dftilde_;
186 :
187 : // temperature in kbt
188 : double kbt_;
189 :
190 : // Monte Carlo stuff
191 : vector<Random> random;
192 : unsigned MCsteps_;
193 : unsigned MCstride_;
194 : long unsigned MCaccept_;
195 : long unsigned MCacceptScale_;
196 : long unsigned MCacceptFT_;
197 : long unsigned MCtrial_;
198 : unsigned MCchunksize_;
199 :
200 : // output
201 : Value* valueScale;
202 : Value* valueOffset;
203 : Value* valueAccept;
204 : Value* valueAcceptScale;
205 : Value* valueAcceptFT;
206 : vector<Value*> valueSigma;
207 : vector<Value*> valueSigmaMean;
208 : vector<Value*> valueFtilde;
209 :
210 : // restart
211 : unsigned write_stride_;
212 : OFile sfile_;
213 :
214 : // others
215 : bool firstTime;
216 : vector<bool> firstTimeW;
217 : bool master;
218 : bool do_reweight_;
219 : unsigned do_optsigmamean_;
220 : unsigned nrep_;
221 : unsigned replica_;
222 : unsigned narg;
223 :
224 : // selector
225 : string selector_;
226 :
227 : // optimize sigma mean
228 : vector< vector < vector <double> > > sigma_mean2_last_;
229 : unsigned optsigmamean_stride_;
230 :
231 : // average weights
232 : unsigned average_weights_stride_;
233 : vector< vector <double> > average_weights_;
234 :
235 : double getEnergyMIGEN(const vector<double> &mean, const vector<double> &ftilde, const vector<double> &sigma,
236 : const double scale, const double offset);
237 : double getEnergySP(const vector<double> &mean, const vector<double> &sigma,
238 : const double scale, const double offset);
239 : double getEnergySPE(const vector<double> &mean, const vector<double> &sigma,
240 : const double scale, const double offset);
241 : double getEnergyGJ(const vector<double> &mean, const vector<double> &sigma,
242 : const double scale, const double offset);
243 : double getEnergyGJE(const vector<double> &mean, const vector<double> &sigma,
244 : const double scale, const double offset);
245 : void doMonteCarlo(const vector<double> &mean);
246 : double getEnergyForceMIGEN(const vector<double> &mean, const vector<double> &dmean_x, const vector<double> &dmean_b);
247 : double getEnergyForceSP(const vector<double> &mean, const vector<double> &dmean_x, const vector<double> &dmean_b);
248 : double getEnergyForceSPE(const vector<double> &mean, const vector<double> &dmean_x, const vector<double> &dmean_b);
249 : double getEnergyForceGJ(const vector<double> &mean, const vector<double> &dmean_x, const vector<double> &dmean_b);
250 : double getEnergyForceGJE(const vector<double> &mean, const vector<double> &dmean_x, const vector<double> &dmean_b);
251 : void get_weights(const unsigned iselect, double &fact, double &var_fact);
252 : void replica_averaging(const double fact, std::vector<double> &mean, std::vector<double> &dmean_b);
253 : void get_sigma_mean(const unsigned iselect, const double fact, const double var_fact, const vector<double> &mean);
254 : void writeStatus();
255 :
256 : public:
257 : explicit Metainference(const ActionOptions&);
258 : ~Metainference();
259 : void calculate();
260 : void update();
261 : static void registerKeywords(Keywords& keys);
262 : };
263 :
264 :
265 6471 : PLUMED_REGISTER_ACTION(Metainference,"METAINFERENCE")
266 :
267 20 : void Metainference::registerKeywords(Keywords& keys) {
268 20 : Bias::registerKeywords(keys);
269 40 : keys.use("ARG");
270 80 : keys.add("optional","PARARG","reference values for the experimental data, these can be provided as arguments without derivatives");
271 80 : keys.add("optional","PARAMETERS","reference values for the experimental data");
272 60 : keys.addFlag("NOENSEMBLE",false,"don't perform any replica-averaging");
273 60 : keys.addFlag("REWEIGHT",false,"simple REWEIGHT using the latest ARG as energy");
274 80 : keys.add("optional","AVERAGING", "Stride for calculation of averaged weights and sigma_mean");
275 100 : keys.add("compulsory","NOISETYPE","MGAUSS","functional form of the noise (GAUSS,MGAUSS,OUTLIERS,MOUTLIERS,GENERIC)");
276 100 : keys.add("compulsory","LIKELIHOOD","GAUSS","the likelihood for the GENERIC metainference model, GAUSS or LOGN");
277 100 : keys.add("compulsory","DFTILDE","0.1","fraction of sigma_mean used to evolve ftilde");
278 60 : keys.addFlag("SCALEDATA",false,"Set to TRUE if you want to sample a scaling factor common to all values and replicas");
279 100 : keys.add("compulsory","SCALE0","1.0","initial value of the scaling factor");
280 100 : keys.add("compulsory","SCALE_PRIOR","FLAT","either FLAT or GAUSSIAN");
281 80 : keys.add("optional","SCALE_MIN","minimum value of the scaling factor");
282 80 : keys.add("optional","SCALE_MAX","maximum value of the scaling factor");
283 80 : keys.add("optional","DSCALE","maximum MC move of the scaling factor");
284 60 : keys.addFlag("ADDOFFSET",false,"Set to TRUE if you want to sample an offset common to all values and replicas");
285 100 : keys.add("compulsory","OFFSET0","0.0","initial value of the offset");
286 100 : keys.add("compulsory","OFFSET_PRIOR","FLAT","either FLAT or GAUSSIAN");
287 80 : keys.add("optional","OFFSET_MIN","minimum value of the offset");
288 80 : keys.add("optional","OFFSET_MAX","maximum value of the offset");
289 80 : keys.add("optional","DOFFSET","maximum MC move of the offset");
290 100 : keys.add("compulsory","SIGMA0","1.0","initial value of the uncertainty parameter");
291 100 : keys.add("compulsory","SIGMA_MIN","0.0","minimum value of the uncertainty parameter");
292 100 : keys.add("compulsory","SIGMA_MAX","10.","maximum value of the uncertainty parameter");
293 80 : keys.add("optional","DSIGMA","maximum MC move of the uncertainty parameter");
294 100 : keys.add("compulsory","OPTSIGMAMEAN","NONE","Set to NONE/SEM to manually set sigma mean, or to estimate it on the fly");
295 80 : keys.add("optional","SIGMA_MEAN0","starting value for the uncertainty in the mean estimate");
296 80 : keys.add("optional","TEMP","the system temperature - this is only needed if code doesnt' pass the temperature to plumed");
297 80 : keys.add("optional","MC_STEPS","number of MC steps");
298 80 : keys.add("optional","MC_STRIDE","MC stride");
299 80 : keys.add("optional","MC_CHUNKSIZE","MC chunksize");
300 80 : keys.add("optional","STATUS_FILE","write a file with all the data usefull for restart/continuation of Metainference");
301 100 : keys.add("compulsory","WRITE_STRIDE","1000","write the status to a file every N steps, this can be used for restart/continuation");
302 80 : keys.add("optional","SELECTOR","name of selector");
303 80 : keys.add("optional","NSELECT","range of values for selector [0, N-1]");
304 40 : keys.use("RESTART");
305 20 : useCustomisableComponents(keys);
306 80 : keys.addOutputComponent("sigma", "default", "uncertainty parameter");
307 80 : keys.addOutputComponent("sigmaMean", "default", "uncertainty in the mean estimate");
308 80 : keys.addOutputComponent("acceptSigma", "default", "MC acceptance");
309 80 : keys.addOutputComponent("acceptScale", "SCALEDATA", "MC acceptance");
310 80 : keys.addOutputComponent("weight", "REWEIGHT", "weights of the weighted average");
311 80 : keys.addOutputComponent("biasDer", "REWEIGHT", "derivatives wrt the bias");
312 80 : keys.addOutputComponent("scale", "SCALEDATA", "scale parameter");
313 80 : keys.addOutputComponent("offset", "ADDOFFSET", "offset parameter");
314 80 : keys.addOutputComponent("ftilde", "GENERIC", "ensemble average estimator");
315 20 : }
316 :
317 19 : Metainference::Metainference(const ActionOptions&ao):
318 : PLUMED_BIAS_INIT(ao),
319 : doscale_(false),
320 : scale_(1.),
321 : scale_mu_(0),
322 : scale_min_(1),
323 : scale_max_(-1),
324 : Dscale_(-1),
325 : dooffset_(false),
326 : offset_(0.),
327 : offset_mu_(0),
328 : offset_min_(1),
329 : offset_max_(-1),
330 : Doffset_(-1),
331 : Dftilde_(0.1),
332 : random(3),
333 : MCsteps_(1),
334 : MCstride_(1),
335 : MCaccept_(0),
336 : MCacceptScale_(0),
337 : MCacceptFT_(0),
338 : MCtrial_(0),
339 : MCchunksize_(0),
340 : write_stride_(0),
341 : firstTime(true),
342 : do_reweight_(false),
343 : do_optsigmamean_(0),
344 : optsigmamean_stride_(0),
345 247 : average_weights_stride_(1)
346 : {
347 19 : bool noensemble = false;
348 38 : parseFlag("NOENSEMBLE", noensemble);
349 :
350 : // set up replica stuff
351 19 : master = (comm.Get_rank()==0);
352 19 : if(master) {
353 11 : nrep_ = multi_sim_comm.Get_size();
354 11 : replica_ = multi_sim_comm.Get_rank();
355 11 : if(noensemble) nrep_ = 1;
356 : } else {
357 8 : nrep_ = 0;
358 8 : replica_ = 0;
359 : }
360 19 : comm.Sum(&nrep_,1);
361 19 : comm.Sum(&replica_,1);
362 :
363 19 : unsigned nsel = 1;
364 38 : parse("SELECTOR", selector_);
365 38 : parse("NSELECT", nsel);
366 : // do checks
367 19 : if(selector_.length()>0 && nsel<=1) error("With SELECTOR active, NSELECT must be greater than 1");
368 19 : if(selector_.length()==0 && nsel>1) error("With NSELECT greater than 1, you must specify SELECTOR");
369 :
370 : // initialise firstTimeW
371 19 : firstTimeW.resize(nsel, true);
372 :
373 : // reweight implies a different number of arguments (the latest one must always be the bias)
374 38 : parseFlag("REWEIGHT", do_reweight_);
375 19 : if(do_reweight_&&nrep_<2) error("REWEIGHT can only be used in parallel with 2 or more replicas");
376 38 : if(!getRestart()) average_weights_.resize(nsel, vector<double> (nrep_, 1./static_cast<double>(nrep_)));
377 0 : else average_weights_.resize(nsel, vector<double> (nrep_, 0.));
378 19 : narg = getNumberOfArguments();
379 19 : if(do_reweight_) narg--;
380 :
381 19 : unsigned averaging=0;
382 38 : parse("AVERAGING", averaging);
383 19 : if(averaging>0) {
384 0 : average_weights_stride_ = averaging;
385 0 : optsigmamean_stride_ = averaging;
386 : }
387 :
388 38 : parseVector("PARAMETERS",parameters);
389 19 : if(parameters.size()!=static_cast<unsigned>(narg)&&!parameters.empty())
390 0 : error("Size of PARAMETERS array should be either 0 or the same as of the number of arguments in ARG1");
391 :
392 : vector<Value*> arg2;
393 38 : parseArgumentList("PARARG",arg2);
394 19 : if(!arg2.empty()) {
395 4 : if(parameters.size()>0) error("It is not possible to use PARARG and PARAMETERS together");
396 4 : if(arg2.size()!=narg) error("Size of PARARG array should be the same as number for arguments in ARG");
397 7076 : for(unsigned i=0; i<arg2.size(); i++) {
398 7068 : parameters.push_back(arg2[i]->get());
399 4712 : if(arg2[i]->hasDerivatives()==true) error("PARARG can only accept arguments without derivatives");
400 : }
401 : }
402 :
403 19 : if(parameters.size()!=narg)
404 0 : error("PARARG or PARAMETERS arrays should include the same number of elements as the arguments in ARG");
405 :
406 : string stringa_noise;
407 38 : parse("NOISETYPE",stringa_noise);
408 19 : if(stringa_noise=="GAUSS") noise_type_ = GAUSS;
409 18 : else if(stringa_noise=="MGAUSS") noise_type_ = MGAUSS;
410 10 : else if(stringa_noise=="OUTLIERS") noise_type_ = OUTLIERS;
411 5 : else if(stringa_noise=="MOUTLIERS") noise_type_ = MOUTLIERS;
412 1 : else if(stringa_noise=="GENERIC") noise_type_ = GENERIC;
413 0 : else error("Unknown noise type!");
414 :
415 19 : if(noise_type_== GENERIC) {
416 : string stringa_like;
417 2 : parse("LIKELIHOOD",stringa_like);
418 1 : if(stringa_like=="GAUSS") gen_likelihood_ = LIKE_GAUSS;
419 0 : else if(stringa_like=="LOGN") gen_likelihood_ = LIKE_LOGN;
420 0 : else error("Unknown likelihood type!");
421 :
422 2 : parse("DFTILDE",Dftilde_);
423 : }
424 :
425 38 : parse("WRITE_STRIDE",write_stride_);
426 : string status_file_name_;
427 38 : parse("STATUS_FILE",status_file_name_);
428 57 : if(status_file_name_=="") status_file_name_ = "MISTATUS"+getLabel();
429 0 : else status_file_name_ = status_file_name_+getLabel();
430 :
431 : string stringa_optsigma;
432 38 : parse("OPTSIGMAMEAN", stringa_optsigma);
433 19 : if(stringa_optsigma=="NONE") do_optsigmamean_=0;
434 0 : else if(stringa_optsigma=="SEM") do_optsigmamean_=1;
435 :
436 : // resize vector for sigma_mean history
437 19 : sigma_mean2_last_.resize(nsel);
438 57 : for(unsigned i=0; i<nsel; i++) sigma_mean2_last_[i].resize(narg);
439 :
440 : vector<double> read_sigma_mean_;
441 38 : parseVector("SIGMA_MEAN0",read_sigma_mean_);
442 38 : if(!do_optsigmamean_ && read_sigma_mean_.size()==0 && !getRestart())
443 0 : error("If you don't use OPTSIGMAMEAN and you are not RESTARTING then you MUST SET SIGMA_MEAN0");
444 :
445 19 : if(noise_type_==MGAUSS||noise_type_==MOUTLIERS||noise_type_==GENERIC) {
446 13 : if(read_sigma_mean_.size()==narg) {
447 0 : sigma_mean2_.resize(narg);
448 0 : for(unsigned i=0; i<narg; i++) sigma_mean2_[i]=read_sigma_mean_[i]*read_sigma_mean_[i];
449 13 : } else if(read_sigma_mean_.size()==1) {
450 13 : sigma_mean2_.resize(narg,read_sigma_mean_[0]*read_sigma_mean_[0]);
451 0 : } else if(read_sigma_mean_.size()==0) {
452 0 : sigma_mean2_.resize(narg,0.000001);
453 : } else {
454 0 : error("SIGMA_MEAN0 can accept either one single value or as many values as the arguments (with NOISETYPE=MGAUSS|MOUTLIERS)");
455 : }
456 : // set the initial value for the history
457 2416 : for(unsigned i=0; i<nsel; i++) for(unsigned j=0; j<narg; j++) sigma_mean2_last_[i][j].push_back(sigma_mean2_[j]);
458 : } else {
459 6 : if(read_sigma_mean_.size()==1) {
460 6 : sigma_mean2_.resize(1, read_sigma_mean_[0]*read_sigma_mean_[0]);
461 0 : } else if(read_sigma_mean_.size()==0) {
462 0 : sigma_mean2_.resize(1, 0.000001);
463 : } else {
464 0 : error("If you want to use more than one SIGMA_MEAN0 you should use NOISETYPE=MGAUSS|MOUTLIERS");
465 : }
466 : // set the initial value for the history
467 37 : for(unsigned i=0; i<nsel; i++) for(unsigned j=0; j<narg; j++) sigma_mean2_last_[i][j].push_back(sigma_mean2_[0]);
468 : }
469 :
470 38 : parseFlag("SCALEDATA", doscale_);
471 19 : if(doscale_) {
472 : string stringa_noise;
473 24 : parse("SCALE_PRIOR",stringa_noise);
474 12 : if(stringa_noise=="GAUSSIAN") scale_prior_ = SC_GAUSS;
475 12 : else if(stringa_noise=="FLAT") scale_prior_ = SC_FLAT;
476 0 : else error("Unknown SCALE_PRIOR type!");
477 24 : parse("SCALE0",scale_);
478 24 : parse("DSCALE",Dscale_);
479 12 : if(Dscale_<0.) error("DSCALE must be set when using SCALEDATA");
480 12 : if(scale_prior_==SC_GAUSS) {
481 0 : scale_mu_=scale_;
482 : } else {
483 24 : parse("SCALE_MIN",scale_min_);
484 24 : parse("SCALE_MAX",scale_max_);
485 12 : if(scale_max_<scale_min_) error("SCALE_MAX and SCALE_MIN must be set when using SCALE_PRIOR=FLAT");
486 : }
487 : }
488 :
489 38 : parseFlag("ADDOFFSET", dooffset_);
490 19 : if(dooffset_) {
491 : string stringa_noise;
492 4 : parse("OFFSET_PRIOR",stringa_noise);
493 2 : if(stringa_noise=="GAUSSIAN") offset_prior_ = SC_GAUSS;
494 2 : else if(stringa_noise=="FLAT") offset_prior_ = SC_FLAT;
495 0 : else error("Unknown OFFSET_PRIOR type!");
496 4 : parse("OFFSET0",offset_);
497 4 : parse("DOFFSET",Doffset_);
498 2 : if(offset_prior_==SC_GAUSS) {
499 0 : offset_mu_=offset_;
500 0 : if(Doffset_<0.) error("DOFFSET must be set when using OFFSET_PRIOR=GAUSS");
501 : } else {
502 4 : parse("OFFSET_MIN",offset_min_);
503 4 : parse("OFFSET_MAX",offset_max_);
504 2 : if(Doffset_<0) Doffset_ = 0.05*(offset_max_ - offset_min_);
505 2 : if(offset_max_<offset_min_) error("OFFSET_MAX and OFFSET_MIN must be set when using OFFSET_PRIOR=FLAT");
506 : }
507 : }
508 :
509 : vector<double> readsigma;
510 38 : parseVector("SIGMA0",readsigma);
511 25 : if((noise_type_!=MGAUSS&&noise_type_!=MOUTLIERS&&noise_type_!=GENERIC)&&readsigma.size()>1)
512 0 : error("If you want to use more than one SIGMA you should use NOISETYPE=MGAUSS|MOUTLIERS");
513 19 : if(noise_type_==MGAUSS||noise_type_==MOUTLIERS||noise_type_==GENERIC) {
514 13 : if(readsigma.size()==narg) {
515 0 : sigma_.resize(narg);
516 0 : sigma_=readsigma;
517 13 : } else if(readsigma.size()==1) {
518 13 : sigma_.resize(narg,readsigma[0]);
519 : } else {
520 0 : error("SIGMA0 can accept either one single value or as many values as the number of arguments (with NOISETYPE=MGAUSS|MOUTLIERS)");
521 : }
522 6 : } else sigma_.resize(1, readsigma[0]);
523 :
524 : double read_smin_;
525 38 : parse("SIGMA_MIN",read_smin_);
526 19 : sigma_min_.resize(sigma_.size(),read_smin_);
527 : double read_smax_;
528 38 : parse("SIGMA_MAX",read_smax_);
529 19 : sigma_max_.resize(sigma_.size(),read_smax_);
530 19 : double read_dsigma_=-1.;
531 38 : parse("DSIGMA",read_dsigma_);
532 19 : if(read_dsigma_<0) read_dsigma_ = 0.05*(read_smax_ - read_smin_);
533 19 : Dsigma_.resize(sigma_.size(),read_dsigma_);
534 :
535 : // monte carlo stuff
536 38 : parse("MC_STEPS",MCsteps_);
537 38 : parse("MC_STRIDE",MCstride_);
538 38 : parse("MC_CHUNKSIZE", MCchunksize_);
539 : // adjust for multiple-time steps
540 19 : MCstride_ *= getStride();
541 : // get temperature
542 19 : double temp=0.0;
543 38 : parse("TEMP",temp);
544 38 : if(temp>0.0) kbt_=plumed.getAtoms().getKBoltzmann()*temp;
545 0 : else kbt_=plumed.getAtoms().getKbT();
546 19 : if(kbt_==0.0) error("Unless the MD engine passes the temperature to plumed, you must specify it using TEMP");
547 :
548 19 : checkRead();
549 :
550 38 : IFile restart_sfile;
551 19 : restart_sfile.link(*this);
552 19 : if(getRestart()&&restart_sfile.FileExist(status_file_name_)) {
553 0 : firstTime = false;
554 0 : for(unsigned i=0; i<nsel; i++) firstTimeW[i] = false;
555 0 : restart_sfile.open(status_file_name_);
556 0 : log.printf(" Restarting from %s\n", status_file_name_.c_str());
557 : double dummy;
558 0 : if(restart_sfile.scanField("time",dummy)) {
559 : // nsel
560 0 : for(unsigned i=0; i<sigma_mean2_last_.size(); i++) {
561 : std::string msg_i;
562 0 : Tools::convert(i,msg_i);
563 : // narg
564 0 : if(noise_type_==MGAUSS||noise_type_==MOUTLIERS||noise_type_==GENERIC) {
565 0 : for(unsigned j=0; j<narg; ++j) {
566 : std::string msg_j;
567 0 : Tools::convert(j,msg_j);
568 0 : std::string msg = msg_i+"_"+msg_j;
569 : double read_sm;
570 0 : restart_sfile.scanField("sigma_mean_"+msg,read_sm);
571 0 : sigma_mean2_last_[i][j][0] = read_sm*read_sm;
572 : }
573 : }
574 0 : if(noise_type_==GAUSS||noise_type_==OUTLIERS) {
575 : double read_sm;
576 0 : restart_sfile.scanField("sigma_mean_0_"+msg_i,read_sm);
577 0 : for(unsigned j=0; j<narg; j++) sigma_mean2_last_[i][j][0] = read_sm*read_sm;
578 : }
579 : }
580 :
581 0 : for(unsigned i=0; i<sigma_.size(); ++i) {
582 : std::string msg;
583 0 : Tools::convert(i,msg);
584 0 : restart_sfile.scanField("sigma_"+msg,sigma_[i]);
585 : }
586 0 : if(noise_type_==GENERIC) {
587 0 : for(unsigned i=0; i<ftilde_.size(); ++i) {
588 : std::string msg;
589 0 : Tools::convert(i,msg);
590 0 : restart_sfile.scanField("ftilde_"+msg,ftilde_[i]);
591 : }
592 : }
593 0 : restart_sfile.scanField("scale0_",scale_);
594 0 : restart_sfile.scanField("offset0_",offset_);
595 :
596 0 : for(unsigned i=0; i<nsel; i++) {
597 : std::string msg;
598 0 : Tools::convert(i,msg);
599 : double tmp_w;
600 0 : restart_sfile.scanField("weight_"+msg,tmp_w);
601 0 : if(master) {
602 0 : average_weights_[i][replica_] = tmp_w;
603 0 : if(nrep_>1) multi_sim_comm.Sum(&average_weights_[i][0], nrep_);
604 : }
605 0 : comm.Sum(&average_weights_[i][0], nrep_);
606 : }
607 :
608 : }
609 0 : restart_sfile.scanField();
610 0 : restart_sfile.close();
611 : }
612 :
613 19 : switch(noise_type_) {
614 1 : case GENERIC:
615 1 : log.printf(" with general metainference ");
616 1 : if(gen_likelihood_==LIKE_GAUSS) log.printf(" and a gaussian likelihood\n");
617 0 : else if(gen_likelihood_==LIKE_LOGN) log.printf(" and a log-normal likelihood\n");
618 1 : log.printf(" ensemble average parameter sampled with a step %lf of sigma_mean\n", Dftilde_);
619 : break;
620 1 : case GAUSS:
621 1 : log.printf(" with gaussian noise and a single noise parameter for all the data\n");
622 : break;
623 8 : case MGAUSS:
624 8 : log.printf(" with gaussian noise and a noise parameter for each data point\n");
625 : break;
626 5 : case OUTLIERS:
627 5 : log.printf(" with long tailed gaussian noise and a single noise parameter for all the data\n");
628 : break;
629 4 : case MOUTLIERS:
630 4 : log.printf(" with long tailed gaussian noise and a noise parameter for each data point\n");
631 : break;
632 : }
633 :
634 19 : if(doscale_) {
635 12 : log.printf(" sampling a common scaling factor with:\n");
636 12 : log.printf(" initial scale parameter %f\n",scale_);
637 12 : if(scale_prior_==SC_GAUSS) {
638 0 : log.printf(" gaussian prior with mean %f and width %f\n",scale_mu_,Dscale_);
639 : }
640 12 : if(scale_prior_==SC_FLAT) {
641 12 : log.printf(" flat prior between %f - %f\n",scale_min_,scale_max_);
642 12 : log.printf(" maximum MC move of scale parameter %f\n",Dscale_);
643 : }
644 : }
645 :
646 19 : if(dooffset_) {
647 2 : log.printf(" sampling a common offset with:\n");
648 2 : log.printf(" initial offset parameter %f\n",offset_);
649 2 : if(offset_prior_==SC_GAUSS) {
650 0 : log.printf(" gaussian prior with mean %f and width %f\n",offset_mu_,Doffset_);
651 : }
652 2 : if(offset_prior_==SC_FLAT) {
653 2 : log.printf(" flat prior between %f - %f\n",offset_min_,offset_max_);
654 2 : log.printf(" maximum MC move of offset parameter %f\n",Doffset_);
655 : }
656 : }
657 :
658 19 : log.printf(" number of experimental data points %u\n",narg);
659 19 : log.printf(" number of replicas %u\n",nrep_);
660 19 : log.printf(" initial data uncertainties");
661 7226 : for(unsigned i=0; i<sigma_.size(); ++i) log.printf(" %f", sigma_[i]);
662 19 : log.printf("\n");
663 19 : log.printf(" minimum data uncertainty %f\n",read_smin_);
664 19 : log.printf(" maximum data uncertainty %f\n",read_smax_);
665 19 : log.printf(" maximum MC move of data uncertainty %f\n",read_dsigma_);
666 19 : log.printf(" temperature of the system %f\n",kbt_);
667 19 : log.printf(" MC steps %u\n",MCsteps_);
668 19 : log.printf(" MC stride %u\n",MCstride_);
669 19 : log.printf(" initial standard errors of the mean");
670 7226 : for(unsigned i=0; i<sigma_mean2_.size(); ++i) log.printf(" %f", sqrt(sigma_mean2_[i]));
671 19 : log.printf("\n");
672 :
673 19 : if(do_reweight_) {
674 32 : addComponent("biasDer");
675 32 : componentIsNotPeriodic("biasDer");
676 32 : addComponent("weight");
677 32 : componentIsNotPeriodic("weight");
678 : }
679 :
680 19 : if(doscale_) {
681 24 : addComponent("scale");
682 24 : componentIsNotPeriodic("scale");
683 24 : valueScale=getPntrToComponent("scale");
684 : }
685 :
686 19 : if(dooffset_) {
687 4 : addComponent("offset");
688 4 : componentIsNotPeriodic("offset");
689 4 : valueOffset=getPntrToComponent("offset");
690 : }
691 :
692 19 : if(dooffset_||doscale_) {
693 28 : addComponent("acceptScale");
694 28 : componentIsNotPeriodic("acceptScale");
695 28 : valueAcceptScale=getPntrToComponent("acceptScale");
696 : }
697 :
698 19 : if(noise_type_==GENERIC) {
699 2 : addComponent("acceptFT");
700 2 : componentIsNotPeriodic("acceptFT");
701 2 : valueAcceptFT=getPntrToComponent("acceptFT");
702 : }
703 :
704 38 : addComponent("acceptSigma");
705 38 : componentIsNotPeriodic("acceptSigma");
706 38 : valueAccept=getPntrToComponent("acceptSigma");
707 :
708 19 : if(noise_type_==MGAUSS||noise_type_==MOUTLIERS||noise_type_==GENERIC) {
709 7196 : for(unsigned i=0; i<sigma_mean2_.size(); ++i) {
710 2390 : std::string num; Tools::convert(i,num);
711 7170 : addComponent("sigmaMean_"+num); componentIsNotPeriodic("sigmaMean_"+num);
712 7170 : valueSigmaMean.push_back(getPntrToComponent("sigmaMean_"+num));
713 7170 : getPntrToComponent("sigmaMean_"+num)->set(sqrt(sigma_mean2_[i]));
714 7170 : addComponent("sigma_"+num); componentIsNotPeriodic("sigma_"+num);
715 7170 : valueSigma.push_back(getPntrToComponent("sigma_"+num));
716 7170 : getPntrToComponent("sigma_"+num)->set(sigma_[i]);
717 2390 : if(noise_type_==GENERIC) {
718 6 : addComponent("ftilde_"+num); componentIsNotPeriodic("ftilde_"+num);
719 6 : valueFtilde.push_back(getPntrToComponent("ftilde_"+num));
720 : }
721 : }
722 : } else {
723 18 : addComponent("sigmaMean"); componentIsNotPeriodic("sigmaMean");
724 18 : valueSigmaMean.push_back(getPntrToComponent("sigmaMean"));
725 18 : getPntrToComponent("sigmaMean")->set(sqrt(sigma_mean2_[0]));
726 18 : addComponent("sigma"); componentIsNotPeriodic("sigma");
727 18 : valueSigma.push_back(getPntrToComponent("sigma"));
728 18 : getPntrToComponent("sigma")->set(sigma_[0]);
729 : }
730 :
731 : // initialize random seed
732 : unsigned iseed;
733 19 : if(master) iseed = time(NULL)+replica_;
734 8 : else iseed = 0;
735 19 : comm.Sum(&iseed, 1);
736 19 : random[0].setSeed(-iseed);
737 : // Random chunk
738 19 : if(master) iseed = time(NULL)+replica_;
739 8 : else iseed = 0;
740 19 : comm.Sum(&iseed, 1);
741 19 : random[2].setSeed(-iseed);
742 19 : if(doscale_||dooffset_) {
743 : // in this case we want the same seed everywhere
744 14 : iseed = time(NULL);
745 14 : if(master&&nrep_>1) multi_sim_comm.Bcast(iseed,0);
746 14 : comm.Bcast(iseed,0);
747 14 : random[1].setSeed(-iseed);
748 : }
749 :
750 : // outfile stuff
751 19 : if(write_stride_>0) {
752 19 : sfile_.link(*this);
753 19 : sfile_.open(status_file_name_);
754 : }
755 :
756 57 : log<<" Bibliography "<<plumed.cite("Bonomi, Camilloni, Cavalli, Vendruscolo, Sci. Adv. 2, e150117 (2016)");
757 51 : if(do_reweight_) log<<plumed.cite("Bonomi, Camilloni, Vendruscolo, Sci. Rep. 6, 31232 (2016)");
758 19 : if(do_optsigmamean_>0) log<<plumed.cite("Loehr, Jussupow, Camilloni, J. Chem. Phys. 146, 165102 (2017)");
759 57 : log<<plumed.cite("Bonomi, Camilloni, Bioinformatics, 33, 3999 (2017)");
760 19 : log<<"\n";
761 19 : }
762 :
763 114 : Metainference::~Metainference()
764 : {
765 19 : if(sfile_.isOpen()) sfile_.close();
766 38 : }
767 :
768 156 : double Metainference::getEnergySP(const vector<double> &mean, const vector<double> &sigma,
769 : const double scale, const double offset)
770 : {
771 156 : const double scale2 = scale*scale;
772 156 : const double sm2 = sigma_mean2_[0];
773 156 : const double ss2 = sigma[0]*sigma[0] + scale2*sm2;
774 156 : const double sss = sigma[0]*sigma[0] + sm2;
775 :
776 : double ene = 0.0;
777 468 : #pragma omp parallel num_threads(OpenMP::getNumThreads()) shared(ene)
778 : {
779 312 : #pragma omp for reduction( + : ene)
780 312 : for(unsigned i=0; i<narg; ++i) {
781 1980 : const double dev = scale*mean[i]-parameters[i]+offset;
782 660 : const double a2 = 0.5*dev*dev + ss2;
783 660 : ene += std::log(2.0*a2/(1.0-exp(-a2/sm2)));
784 : }
785 : }
786 : // add one single Jeffrey's prior and one normalisation per data point
787 156 : ene += 0.5*std::log(sss) + static_cast<double>(narg)*0.5*std::log(0.5*M_PI*M_PI/ss2);
788 156 : if(doscale_) ene += 0.5*std::log(sss);
789 156 : if(dooffset_) ene += 0.5*std::log(sss);
790 156 : return kbt_ * ene;
791 : }
792 :
793 144 : double Metainference::getEnergySPE(const vector<double> &mean, const vector<double> &sigma,
794 : const double scale, const double offset)
795 : {
796 144 : const double scale2 = scale*scale;
797 : double ene = 0.0;
798 432 : #pragma omp parallel num_threads(OpenMP::getNumThreads()) shared(ene)
799 : {
800 288 : #pragma omp for reduction( + : ene)
801 288 : for(unsigned i=0; i<narg; ++i) {
802 1152 : const double sm2 = sigma_mean2_[i];
803 1152 : const double ss2 = sigma[i]*sigma[i] + scale2*sm2;
804 576 : const double sss = sigma[i]*sigma[i] + sm2;
805 1728 : const double dev = scale*mean[i]-parameters[i]+offset;
806 576 : const double a2 = 0.5*dev*dev + ss2;
807 576 : ene += 0.5*std::log(sss) + 0.5*std::log(0.5*M_PI*M_PI/ss2) + std::log(2.0*a2/(1.0-exp(-a2/sm2)));
808 1152 : if(doscale_) ene += 0.5*std::log(sss);
809 576 : if(dooffset_) ene += 0.5*std::log(sss);
810 : }
811 : }
812 144 : return kbt_ * ene;
813 : }
814 :
815 48 : double Metainference::getEnergyMIGEN(const vector<double> &mean, const vector<double> &ftilde, const vector<double> &sigma,
816 : const double scale, const double offset)
817 : {
818 : double ene = 0.0;
819 144 : #pragma omp parallel num_threads(OpenMP::getNumThreads()) shared(ene)
820 : {
821 96 : #pragma omp for reduction( + : ene)
822 96 : for(unsigned i=0; i<narg; ++i) {
823 192 : const double inv_sb2 = 1./(sigma[i]*sigma[i]);
824 96 : const double inv_sm2 = 1./sigma_mean2_[i];
825 : double devb = 0;
826 384 : if(gen_likelihood_==LIKE_GAUSS) devb = scale*ftilde[i]-parameters[i]+offset;
827 0 : else if(gen_likelihood_==LIKE_LOGN) devb = std::log(scale*ftilde[i]/parameters[i]);
828 288 : double devm = mean[i] - ftilde[i];
829 : // deviation + normalisation + jeffrey
830 : double normb = 0.;
831 192 : if(gen_likelihood_==LIKE_GAUSS) normb = -0.5*std::log(0.5/M_PI*inv_sb2);
832 0 : else if(gen_likelihood_==LIKE_LOGN) normb = -0.5*std::log(0.5/M_PI*inv_sb2/(parameters[i]*parameters[i]));
833 96 : const double normm = -0.5*std::log(0.5/M_PI*inv_sm2);
834 96 : const double jeffreys = -0.5*std::log(2.*inv_sb2);
835 96 : ene += 0.5*devb*devb*inv_sb2 + 0.5*devm*devm*inv_sm2 + normb + normm + jeffreys;
836 96 : if(doscale_) ene += jeffreys;
837 96 : if(dooffset_) ene += jeffreys;
838 : }
839 : }
840 48 : return kbt_ * ene;
841 : }
842 :
843 36 : double Metainference::getEnergyGJ(const vector<double> &mean, const vector<double> &sigma,
844 : const double scale, const double offset)
845 : {
846 36 : const double scale2 = scale*scale;
847 72 : const double inv_s2 = 1./(sigma[0]*sigma[0] + scale2*sigma_mean2_[0]);
848 36 : const double inv_sss = 1./(sigma[0]*sigma[0] + sigma_mean2_[0]);
849 :
850 : double ene = 0.0;
851 108 : #pragma omp parallel num_threads(OpenMP::getNumThreads()) shared(ene)
852 : {
853 72 : #pragma omp for reduction( + : ene)
854 72 : for(unsigned i=0; i<narg; ++i) {
855 216 : double dev = scale*mean[i]-parameters[i]+offset;
856 72 : ene += 0.5*dev*dev*inv_s2;
857 : }
858 : }
859 36 : const double normalisation = -0.5*std::log(0.5/M_PI*inv_s2);
860 36 : const double jeffreys = -0.5*std::log(2.*inv_sss);
861 : // add Jeffrey's prior in case one sigma for all data points + one normalisation per datapoint
862 36 : ene += jeffreys + static_cast<double>(narg)*normalisation;
863 36 : if(doscale_) ene += jeffreys;
864 36 : if(dooffset_) ene += jeffreys;
865 :
866 36 : return kbt_ * ene;
867 : }
868 :
869 152 : double Metainference::getEnergyGJE(const vector<double> &mean, const vector<double> &sigma,
870 : const double scale, const double offset)
871 : {
872 152 : const double scale2 = scale*scale;
873 :
874 : double ene = 0.0;
875 456 : #pragma omp parallel num_threads(OpenMP::getNumThreads()) shared(ene)
876 : {
877 304 : #pragma omp for reduction( + : ene)
878 304 : for(unsigned i=0; i<narg; ++i) {
879 15864 : const double inv_s2 = 1./(sigma[i]*sigma[i] + scale2*sigma_mean2_[i]);
880 5288 : const double inv_sss = 1./(sigma[i]*sigma[i] + sigma_mean2_[i]);
881 15864 : double dev = scale*mean[i]-parameters[i]+offset;
882 : // deviation + normalisation + jeffrey
883 5288 : const double normalisation = -0.5*std::log(0.5/M_PI*inv_s2);
884 5288 : const double jeffreys = -0.5*std::log(2.*inv_sss);
885 5288 : ene += 0.5*dev*dev*inv_s2 + normalisation + jeffreys;
886 5864 : if(doscale_) ene += jeffreys;
887 5288 : if(dooffset_) ene += jeffreys;
888 : }
889 : }
890 152 : return kbt_ * ene;
891 : }
892 :
893 178 : void Metainference::doMonteCarlo(const vector<double> &mean_)
894 : {
895 : // calculate old energy with the updated coordinates
896 : double old_energy=0.;
897 :
898 178 : switch(noise_type_) {
899 12 : case GAUSS:
900 12 : old_energy = getEnergyGJ(mean_,sigma_,scale_,offset_);
901 : break;
902 52 : case MGAUSS:
903 52 : old_energy = getEnergyGJE(mean_,sigma_,scale_,offset_);
904 : break;
905 54 : case OUTLIERS:
906 54 : old_energy = getEnergySP(mean_,sigma_,scale_,offset_);
907 : break;
908 48 : case MOUTLIERS:
909 48 : old_energy = getEnergySPE(mean_,sigma_,scale_,offset_);
910 : break;
911 12 : case GENERIC:
912 12 : old_energy = getEnergyMIGEN(mean_,ftilde_,sigma_,scale_,offset_);
913 : break;
914 : }
915 :
916 : // Create vector of random sigma indices
917 : vector<unsigned> indices;
918 178 : if (MCchunksize_ > 0) {
919 0 : for (unsigned j=0; j<sigma_.size(); j++) {
920 0 : indices.push_back(j);
921 : }
922 0 : random[2].Shuffle(indices);
923 : }
924 : bool breaknow = false;
925 :
926 : // cycle on MC steps
927 534 : for(unsigned i=0; i<MCsteps_; ++i) {
928 :
929 178 : MCtrial_++;
930 :
931 : // propose move for ftilde
932 178 : vector<double> new_ftilde(sigma_.size());
933 178 : new_ftilde = ftilde_;
934 :
935 178 : if(noise_type_==GENERIC) {
936 : // change all sigmas
937 96 : for(unsigned j=0; j<sigma_.size(); j++) {
938 24 : const double r3 = random[0].Gaussian();
939 48 : const double ds3 = Dftilde_*sqrt(sigma_mean2_[j])*r3;
940 48 : new_ftilde[j] = ftilde_[j] + ds3;
941 : }
942 : // calculate new energy
943 12 : double new_energy = getEnergyMIGEN(mean_,new_ftilde,sigma_,scale_,offset_);
944 :
945 : // accept or reject
946 12 : const double delta = ( new_energy - old_energy ) / kbt_;
947 : // if delta is negative always accept move
948 12 : if( delta <= 0.0 ) {
949 : old_energy = new_energy;
950 0 : ftilde_ = new_ftilde;
951 0 : MCacceptFT_++;
952 : // otherwise extract random number
953 : } else {
954 12 : const double s = random[0].RandU01();
955 12 : if( s < exp(-delta) ) {
956 : old_energy = new_energy;
957 0 : ftilde_ = new_ftilde;
958 0 : MCacceptFT_++;
959 : }
960 : }
961 : }
962 :
963 : // propose move for scale and/or offset
964 178 : double new_scale = scale_;
965 178 : double new_offset = offset_;
966 178 : if(doscale_||dooffset_) {
967 168 : if(doscale_) {
968 144 : if(scale_prior_==SC_FLAT) {
969 144 : const double r1 = random[1].Gaussian();
970 144 : const double ds1 = Dscale_*r1;
971 144 : new_scale += ds1;
972 : // check boundaries
973 144 : if(new_scale > scale_max_) {new_scale = 2.0 * scale_max_ - new_scale;}
974 144 : if(new_scale < scale_min_) {new_scale = 2.0 * scale_min_ - new_scale;}
975 : } else {
976 0 : const double r1 = random[1].Gaussian();
977 0 : const double ds1 = 0.5*(scale_mu_-new_scale)+Dscale_*exp(1)/M_PI*r1;
978 0 : new_scale += ds1;
979 : }
980 : }
981 :
982 168 : if(dooffset_) {
983 24 : if(offset_prior_==SC_FLAT) {
984 24 : const double r1 = random[1].Gaussian();
985 24 : const double ds1 = Doffset_*r1;
986 24 : new_offset += ds1;
987 : // check boundaries
988 24 : if(new_offset > offset_max_) {new_offset = 2.0 * offset_max_ - new_offset;}
989 24 : if(new_offset < offset_min_) {new_offset = 2.0 * offset_min_ - new_offset;}
990 : } else {
991 0 : const double r1 = random[1].Gaussian();
992 0 : const double ds1 = 0.5*(offset_mu_-new_offset)+Doffset_*exp(1)/M_PI*r1;
993 0 : new_offset += ds1;
994 : }
995 : }
996 :
997 : // calculate new energy
998 : double new_energy = 0.;
999 :
1000 168 : switch(noise_type_) {
1001 12 : case GAUSS:
1002 12 : new_energy = getEnergyGJ(mean_,sigma_,new_scale,new_offset);
1003 : break;
1004 48 : case MGAUSS:
1005 48 : new_energy = getEnergyGJE(mean_,sigma_,new_scale,new_offset);
1006 : break;
1007 48 : case OUTLIERS:
1008 48 : new_energy = getEnergySP(mean_,sigma_,new_scale,new_offset);
1009 : break;
1010 48 : case MOUTLIERS:
1011 48 : new_energy = getEnergySPE(mean_,sigma_,new_scale,new_offset);
1012 : break;
1013 12 : case GENERIC:
1014 12 : new_energy = getEnergyMIGEN(mean_,ftilde_,sigma_,new_scale,new_offset);
1015 : break;
1016 : }
1017 : // for the scale we need to consider the total energy
1018 168 : vector<double> totenergies(2);
1019 168 : if(master) {
1020 96 : totenergies[0] = old_energy;
1021 96 : totenergies[1] = new_energy;
1022 96 : if(nrep_>1) multi_sim_comm.Sum(totenergies);
1023 : } else {
1024 72 : totenergies[0] = 0;
1025 72 : totenergies[1] = 0;
1026 : }
1027 168 : comm.Sum(totenergies);
1028 :
1029 : // accept or reject
1030 168 : const double delta = ( totenergies[1] - totenergies[0] ) / kbt_;
1031 : // if delta is negative always accept move
1032 168 : if( delta <= 0.0 ) {
1033 : old_energy = new_energy;
1034 156 : scale_ = new_scale;
1035 156 : offset_ = new_offset;
1036 156 : MCacceptScale_++;
1037 : // otherwise extract random number
1038 : } else {
1039 12 : double s = random[1].RandU01();
1040 12 : if( s < exp(-delta) ) {
1041 : old_energy = new_energy;
1042 0 : scale_ = new_scale;
1043 0 : offset_ = new_offset;
1044 0 : MCacceptScale_++;
1045 : }
1046 : }
1047 : }
1048 :
1049 : // propose move for sigma
1050 178 : vector<double> new_sigma(sigma_.size());
1051 178 : new_sigma = sigma_;
1052 :
1053 : // change MCchunksize_ sigmas
1054 178 : if (MCchunksize_ > 0) {
1055 0 : if ((MCchunksize_ * i) >= sigma_.size()) {
1056 : // This means we are not moving any sigma, so we should break immediately
1057 : breaknow = true;
1058 : }
1059 :
1060 : // change random sigmas
1061 0 : for(unsigned j=0; j<MCchunksize_; j++) {
1062 0 : const unsigned shuffle_index = j + MCchunksize_ * i;
1063 0 : if (shuffle_index >= sigma_.size()) {
1064 : // Going any further will segfault but we should still evaluate the sigmas we changed
1065 : break;
1066 : }
1067 0 : const unsigned index = indices[shuffle_index];
1068 0 : const double r2 = random[0].Gaussian();
1069 0 : const double ds2 = Dsigma_[index]*r2;
1070 0 : new_sigma[index] = sigma_[index] + ds2;
1071 : // check boundaries
1072 0 : if(new_sigma[index] > sigma_max_[index]) {new_sigma[index] = 2.0 * sigma_max_[index] - new_sigma[index];}
1073 0 : if(new_sigma[index] < sigma_min_[index]) {new_sigma[index] = 2.0 * sigma_min_[index] - new_sigma[index];}
1074 : }
1075 : } else {
1076 : // change all sigmas
1077 8846 : for(unsigned j=0; j<sigma_.size(); j++) {
1078 2830 : const double r2 = random[0].Gaussian();
1079 2830 : const double ds2 = Dsigma_[j]*r2;
1080 5660 : new_sigma[j] = sigma_[j] + ds2;
1081 : // check boundaries
1082 5660 : if(new_sigma[j] > sigma_max_[j]) {new_sigma[j] = 2.0 * sigma_max_[j] - new_sigma[j];}
1083 5660 : if(new_sigma[j] < sigma_min_[j]) {new_sigma[j] = 2.0 * sigma_min_[j] - new_sigma[j];}
1084 : }
1085 : }
1086 :
1087 178 : if (breaknow) {
1088 : // We didnt move any sigmas, so no sense in evaluating anything
1089 : break;
1090 : }
1091 :
1092 : // calculate new energy
1093 : double new_energy = 0.;
1094 178 : switch(noise_type_) {
1095 12 : case GAUSS:
1096 12 : new_energy = getEnergyGJ(mean_,new_sigma,scale_,offset_);
1097 : break;
1098 52 : case MGAUSS:
1099 52 : new_energy = getEnergyGJE(mean_,new_sigma,scale_,offset_);
1100 : break;
1101 54 : case OUTLIERS:
1102 54 : new_energy = getEnergySP(mean_,new_sigma,scale_,offset_);
1103 : break;
1104 48 : case MOUTLIERS:
1105 48 : new_energy = getEnergySPE(mean_,new_sigma,scale_,offset_);
1106 : break;
1107 12 : case GENERIC:
1108 12 : new_energy = getEnergyMIGEN(mean_,ftilde_,new_sigma,scale_,offset_);
1109 : break;
1110 : }
1111 :
1112 : // accept or reject
1113 178 : const double delta = ( new_energy - old_energy ) / kbt_;
1114 : // if delta is negative always accept move
1115 178 : if( delta <= 0.0 ) {
1116 : old_energy = new_energy;
1117 166 : sigma_ = new_sigma;
1118 166 : MCaccept_++;
1119 : // otherwise extract random number
1120 : } else {
1121 12 : const double s = random[0].RandU01();
1122 12 : if( s < exp(-delta) ) {
1123 : old_energy = new_energy;
1124 0 : sigma_ = new_sigma;
1125 0 : MCaccept_++;
1126 : }
1127 : }
1128 :
1129 : }
1130 : /* save the result of the sampling */
1131 178 : double accept = static_cast<double>(MCaccept_) / static_cast<double>(MCtrial_);
1132 178 : valueAccept->set(accept);
1133 178 : if(doscale_) valueScale->set(scale_);
1134 178 : if(dooffset_) valueOffset->set(offset_);
1135 178 : if(doscale_||dooffset_) {
1136 168 : accept = static_cast<double>(MCacceptScale_) / static_cast<double>(MCtrial_);
1137 168 : valueAcceptScale->set(accept);
1138 : }
1139 14506 : for(unsigned i=0; i<sigma_.size(); i++) valueSigma[i]->set(sigma_[i]);
1140 178 : if(noise_type_==GENERIC) {
1141 12 : accept = static_cast<double>(MCacceptFT_) / static_cast<double>(MCtrial_);
1142 12 : valueAcceptFT->set(accept);
1143 144 : for(unsigned i=0; i<sigma_.size(); i++) valueFtilde[i]->set(ftilde_[i]);
1144 : }
1145 178 : }
1146 :
1147 : /*
1148 : In the following energy-force functions we don't add the normalisation and the jeffreys priors
1149 : because they are not needed for the forces, the correct MetaInference energy is the one calculated
1150 : in the Monte-Carlo
1151 : */
1152 :
1153 54 : double Metainference::getEnergyForceSP(const vector<double> &mean, const vector<double> &dmean_x,
1154 : const vector<double> &dmean_b)
1155 : {
1156 54 : const double scale2 = scale_*scale_;
1157 54 : const double sm2 = sigma_mean2_[0];
1158 54 : const double ss2 = sigma_[0]*sigma_[0] + scale2*sm2;
1159 54 : vector<double> f(narg+1,0);
1160 :
1161 54 : if(master) {
1162 : double omp_ene=0.;
1163 90 : #pragma omp parallel num_threads(OpenMP::getNumThreads()) shared(omp_ene)
1164 : {
1165 60 : #pragma omp for reduction( + : omp_ene)
1166 60 : for(unsigned i=0; i<narg; ++i) {
1167 414 : const double dev = scale_*mean[i]-parameters[i]+offset_;
1168 138 : const double a2 = 0.5*dev*dev + ss2;
1169 138 : const double t = exp(-a2/sm2);
1170 138 : const double dt = 1./t;
1171 138 : const double it = 1./(1.-t);
1172 138 : const double dit = 1./(1.-dt);
1173 138 : omp_ene += std::log(2.*a2*it);
1174 276 : f[i] = -scale_*dev*(dit/sm2 + 1./a2);
1175 : }
1176 : }
1177 60 : f[narg] = omp_ene;
1178 : // collect contribution to forces and energy from other replicas
1179 54 : if(nrep_>1) multi_sim_comm.Sum(&f[0],narg+1);
1180 : }
1181 : // intra-replica summation
1182 108 : comm.Sum(&f[0],narg+1);
1183 :
1184 108 : const double ene = f[narg];
1185 : double w_tmp = 0.;
1186 522 : for(unsigned i=0; i<narg; ++i) {
1187 702 : setOutputForce(i, kbt_*f[i]*dmean_x[i]);
1188 702 : w_tmp += kbt_*f[i]*dmean_b[i];
1189 : }
1190 :
1191 54 : if(do_reweight_) {
1192 48 : setOutputForce(narg, w_tmp);
1193 96 : getPntrToComponent("biasDer")->set(-w_tmp);
1194 : }
1195 :
1196 108 : return kbt_*ene;
1197 : }
1198 :
1199 48 : double Metainference::getEnergyForceSPE(const vector<double> &mean, const vector<double> &dmean_x,
1200 : const vector<double> &dmean_b)
1201 : {
1202 48 : const double scale2 = scale_*scale_;
1203 48 : vector<double> f(narg+1,0);
1204 :
1205 48 : if(master) {
1206 : double omp_ene = 0;
1207 72 : #pragma omp parallel num_threads(OpenMP::getNumThreads()) shared(omp_ene)
1208 : {
1209 48 : #pragma omp for reduction( + : omp_ene)
1210 48 : for(unsigned i=0; i<narg; ++i) {
1211 192 : const double sm2 = sigma_mean2_[i];
1212 96 : const double ss2 = sigma_[i]*sigma_[i] + scale2*sm2;
1213 288 : const double dev = scale_*mean[i]-parameters[i]+offset_;
1214 96 : const double a2 = 0.5*dev*dev + ss2;
1215 96 : const double t = exp(-a2/sm2);
1216 96 : const double dt = 1./t;
1217 96 : const double it = 1./(1.-t);
1218 96 : const double dit = 1./(1.-dt);
1219 96 : omp_ene += std::log(2.*a2*it);
1220 192 : f[i] = -scale_*dev*(dit/sm2 + 1./a2);
1221 : }
1222 : }
1223 48 : f[narg] = omp_ene;
1224 : // collect contribution to forces and energy from other replicas
1225 48 : if(nrep_>1) multi_sim_comm.Sum(&f[0],narg+1);
1226 : }
1227 96 : comm.Sum(&f[0],narg+1);
1228 :
1229 96 : const double ene = f[narg];
1230 : double w_tmp = 0.;
1231 432 : for(unsigned i=0; i<narg; ++i) {
1232 576 : setOutputForce(i, kbt_ * dmean_x[i] * f[i]);
1233 576 : w_tmp += kbt_ * dmean_b[i] *f[i];
1234 : }
1235 :
1236 48 : if(do_reweight_) {
1237 48 : setOutputForce(narg, w_tmp);
1238 96 : getPntrToComponent("biasDer")->set(-w_tmp);
1239 : }
1240 :
1241 96 : return kbt_*ene;
1242 : }
1243 :
1244 12 : double Metainference::getEnergyForceGJ(const vector<double> &mean, const vector<double> &dmean_x,
1245 : const vector<double> &dmean_b)
1246 : {
1247 12 : const double scale2 = scale_*scale_;
1248 12 : double inv_s2=0.;
1249 :
1250 12 : if(master) {
1251 24 : inv_s2 = 1./(sigma_[0]*sigma_[0] + scale2*sigma_mean2_[0]);
1252 12 : if(nrep_>1) multi_sim_comm.Sum(inv_s2);
1253 : }
1254 12 : comm.Sum(inv_s2);
1255 :
1256 : double ene = 0.;
1257 : double w_tmp = 0.;
1258 36 : #pragma omp parallel num_threads(OpenMP::getNumThreads()) shared(ene,w_tmp)
1259 : {
1260 24 : #pragma omp for reduction( + : ene,w_tmp)
1261 24 : for(unsigned i=0; i<narg; ++i) {
1262 72 : const double dev = scale_*mean[i]-parameters[i]+offset_;
1263 24 : const double mult = dev*scale_*inv_s2;
1264 24 : ene += 0.5*dev*dev*inv_s2;
1265 48 : setOutputForce(i, -kbt_*dmean_x[i]*mult);
1266 48 : w_tmp += kbt_*dmean_b[i]*mult;
1267 : }
1268 : }
1269 :
1270 12 : if(do_reweight_) {
1271 0 : setOutputForce(narg, -w_tmp);
1272 0 : getPntrToComponent("biasDer")->set(w_tmp);
1273 : }
1274 :
1275 12 : return kbt_*ene;
1276 : }
1277 :
1278 52 : double Metainference::getEnergyForceGJE(const vector<double> &mean, const vector<double> &dmean_x,
1279 : const vector<double> &dmean_b)
1280 : {
1281 52 : const double scale2 = scale_*scale_;
1282 104 : vector<double> inv_s2(sigma_.size(),0.);
1283 :
1284 52 : if(master) {
1285 6422 : for(unsigned i=0; i<sigma_.size(); ++i) inv_s2[i] = 1./(sigma_[i]*sigma_[i] + scale2*sigma_mean2_[i]);
1286 52 : if(nrep_>1) multi_sim_comm.Sum(&inv_s2[0],sigma_.size());
1287 : }
1288 156 : comm.Sum(&inv_s2[0],sigma_.size());
1289 :
1290 : double ene = 0.;
1291 : double w_tmp = 0.;
1292 156 : #pragma omp parallel num_threads(OpenMP::getNumThreads()) shared(ene,w_tmp)
1293 : {
1294 104 : #pragma omp for reduction( + : ene,w_tmp)
1295 104 : for(unsigned i=0; i<narg; ++i) {
1296 7644 : const double dev = scale_*mean[i]-parameters[i]+offset_;
1297 5096 : const double mult = dev*scale_*inv_s2[i];
1298 2548 : ene += 0.5*dev*dev*inv_s2[i];
1299 5096 : setOutputForce(i, -kbt_*dmean_x[i]*mult);
1300 5096 : w_tmp += kbt_*dmean_b[i]*mult;
1301 : }
1302 : }
1303 :
1304 52 : if(do_reweight_) {
1305 52 : setOutputForce(narg, -w_tmp);
1306 104 : getPntrToComponent("biasDer")->set(w_tmp);
1307 : }
1308 :
1309 104 : return kbt_*ene;
1310 : }
1311 :
1312 12 : double Metainference::getEnergyForceMIGEN(const vector<double> &mean, const vector<double> &dmean_x, const vector<double> &dmean_b)
1313 : {
1314 24 : vector<double> inv_s2(sigma_.size(),0.);
1315 24 : vector<double> dev(sigma_.size(),0.);
1316 24 : vector<double> dev2(sigma_.size(),0.);
1317 :
1318 96 : for(unsigned i=0; i<sigma_.size(); ++i) {
1319 48 : inv_s2[i] = 1./sigma_mean2_[i];
1320 24 : if(master) {
1321 72 : dev[i] = (mean[i]-ftilde_[i]);
1322 48 : dev2[i] = dev[i]*dev[i];
1323 : }
1324 : }
1325 12 : if(master&&nrep_>1) {
1326 0 : multi_sim_comm.Sum(&dev[0],dev.size());
1327 0 : multi_sim_comm.Sum(&dev2[0],dev2.size());
1328 : }
1329 24 : comm.Sum(&dev[0],dev.size());
1330 24 : comm.Sum(&dev2[0],dev2.size());
1331 :
1332 : double dene_b = 0.;
1333 : double ene = 0.;
1334 36 : #pragma omp parallel num_threads(OpenMP::getNumThreads()) shared(ene,dene_b)
1335 : {
1336 24 : #pragma omp for reduction( + : ene,dene_b)
1337 24 : for(unsigned i=0; i<narg; ++i) {
1338 96 : const double dene_x = kbt_*inv_s2[i]*dmean_x[i]*dev[i];
1339 48 : dene_b += kbt_*inv_s2[i]*dmean_b[i]*dev[i];
1340 48 : ene += 0.5*dev2[i]*inv_s2[i];
1341 24 : setOutputForce(i, -dene_x);
1342 : }
1343 : }
1344 :
1345 12 : if(do_reweight_) {
1346 0 : setOutputForce(narg, -dene_b);
1347 0 : getPntrToComponent("biasDer")->set(dene_b);
1348 : }
1349 :
1350 24 : return kbt_*ene;
1351 : }
1352 :
1353 178 : void Metainference::get_weights(const unsigned iselect, double &fact, double &var_fact)
1354 : {
1355 178 : const double dnrep = static_cast<double>(nrep_);
1356 178 : const double ave_fact = 1.0/dnrep;
1357 :
1358 : double norm = 0.0;
1359 :
1360 : // calculate the weights either from BIAS
1361 178 : if(do_reweight_) {
1362 148 : vector<double> bias(nrep_,0);
1363 148 : if(master) {
1364 148 : bias[replica_] = getArgument(narg);
1365 148 : if(nrep_>1) multi_sim_comm.Sum(&bias[0], nrep_);
1366 : }
1367 296 : comm.Sum(&bias[0], nrep_);
1368 :
1369 148 : const double maxbias = *(std::max_element(bias.begin(), bias.end()));
1370 740 : for(unsigned i=0; i<nrep_; ++i) {
1371 592 : bias[i] = exp((bias[i]-maxbias)/kbt_);
1372 296 : norm += bias[i];
1373 : }
1374 :
1375 : // accumulate weights
1376 148 : const double decay = 1./static_cast<double> (average_weights_stride_);
1377 296 : if(!firstTimeW[iselect]) {
1378 660 : for(unsigned i=0; i<nrep_; ++i) {
1379 792 : const double delta=bias[i]/norm-average_weights_[iselect][i];
1380 264 : average_weights_[iselect][i]+=decay*delta;
1381 : }
1382 : } else {
1383 : firstTimeW[iselect] = false;
1384 80 : for(unsigned i=0; i<nrep_; ++i) {
1385 96 : average_weights_[iselect][i] = bias[i]/norm;
1386 : }
1387 : }
1388 :
1389 : // set average back into bias and set norm to one
1390 740 : for(unsigned i=0; i<nrep_; ++i) bias[i] = average_weights_[iselect][i];
1391 : // set local weight, norm and weight variance
1392 296 : fact = bias[replica_];
1393 : norm = 1.0;
1394 740 : for(unsigned i=0; i<nrep_; ++i) var_fact += (bias[i]/norm-ave_fact)*(bias[i]/norm-ave_fact);
1395 296 : getPntrToComponent("weight")->set(fact);
1396 : } else {
1397 : // or arithmetic ones
1398 : norm = dnrep;
1399 30 : fact = 1.0/norm;
1400 : }
1401 178 : }
1402 :
1403 178 : void Metainference::get_sigma_mean(const unsigned iselect, const double fact, const double var_fact, const vector<double> &mean)
1404 : {
1405 178 : const double dnrep = static_cast<double>(nrep_);
1406 178 : const double ave_fact = 1.0/dnrep;
1407 :
1408 356 : vector<double> sigma_mean2_tmp(sigma_mean2_.size(), 0.);
1409 :
1410 178 : if(do_optsigmamean_>0) {
1411 : // remove first entry of the history vector
1412 0 : if(sigma_mean2_last_[iselect][0].size()==optsigmamean_stride_&&optsigmamean_stride_>0)
1413 0 : for(unsigned i=0; i<narg; ++i) sigma_mean2_last_[iselect][i].erase(sigma_mean2_last_[iselect][i].begin());
1414 : /* this is the current estimate of sigma mean for each argument
1415 : there is one of this per argument in any case because it is
1416 : the maximum among these to be used in case of GAUSS/OUTLIER */
1417 0 : vector<double> sigma_mean2_now(narg,0);
1418 0 : if(do_reweight_) {
1419 0 : if(master) {
1420 0 : for(unsigned i=0; i<narg; ++i) {
1421 0 : double tmp1 = (fact*getArgument(i)-ave_fact*mean[i])*(fact*getArgument(i)-ave_fact*mean[i]);
1422 0 : double tmp2 = -2.*mean[i]*(fact-ave_fact)*(fact*getArgument(i)-ave_fact*mean[i]);
1423 0 : sigma_mean2_now[i] = tmp1 + tmp2;
1424 : }
1425 0 : if(nrep_>1) multi_sim_comm.Sum(&sigma_mean2_now[0], narg);
1426 : }
1427 0 : comm.Sum(&sigma_mean2_now[0], narg);
1428 0 : for(unsigned i=0; i<narg; ++i) sigma_mean2_now[i] = dnrep/(dnrep-1.)*(sigma_mean2_now[i] + mean[i]*mean[i]*var_fact);
1429 : } else {
1430 0 : if(master) {
1431 0 : for(unsigned i=0; i<narg; ++i) {
1432 0 : double tmp = getArgument(i)-mean[i];
1433 0 : sigma_mean2_now[i] = fact*tmp*tmp;
1434 : }
1435 0 : if(nrep_>1) multi_sim_comm.Sum(&sigma_mean2_now[0], narg);
1436 : }
1437 0 : comm.Sum(&sigma_mean2_now[0], narg);
1438 0 : for(unsigned i=0; i<narg; ++i) sigma_mean2_now[i] /= dnrep;
1439 : }
1440 :
1441 : // add sigma_mean2 to history
1442 0 : if(optsigmamean_stride_>0) {
1443 0 : for(unsigned i=0; i<narg; ++i) sigma_mean2_last_[iselect][i].push_back(sigma_mean2_now[i]);
1444 : } else {
1445 0 : for(unsigned i=0; i<narg; ++i) if(sigma_mean2_now[i] > sigma_mean2_last_[iselect][i][0]) sigma_mean2_last_[iselect][i][0] = sigma_mean2_now[i];
1446 : }
1447 :
1448 0 : if(noise_type_==MGAUSS||noise_type_==MOUTLIERS||noise_type_==GENERIC) {
1449 0 : for(unsigned i=0; i<narg; ++i) {
1450 : /* set to the maximum in history vector */
1451 0 : sigma_mean2_tmp[i] = *max_element(sigma_mean2_last_[iselect][i].begin(), sigma_mean2_last_[iselect][i].end());
1452 : /* the standard error of the mean */
1453 0 : valueSigmaMean[i]->set(sqrt(sigma_mean2_tmp[i]));
1454 0 : if(noise_type_==GENERIC) {
1455 0 : sigma_min_[i] = sqrt(sigma_mean2_tmp[i]);
1456 0 : if(sigma_[i] < sigma_min_[i]) sigma_[i] = sigma_min_[i];
1457 : }
1458 : }
1459 0 : } else if(noise_type_==GAUSS||noise_type_==OUTLIERS) {
1460 : // find maximum for each data point
1461 : vector <double> max_values;
1462 0 : for(unsigned i=0; i<narg; ++i) max_values.push_back(*max_element(sigma_mean2_last_[iselect][i].begin(), sigma_mean2_last_[iselect][i].end()));
1463 : // find maximum across data points
1464 0 : const double max_now = *max_element(max_values.begin(), max_values.end());
1465 : // set new value
1466 0 : sigma_mean2_tmp[0] = max_now;
1467 0 : valueSigmaMean[0]->set(sqrt(sigma_mean2_tmp[0]));
1468 : }
1469 : // endif sigma optimization
1470 : } else {
1471 178 : if(noise_type_==MGAUSS||noise_type_==MOUTLIERS||noise_type_==GENERIC) {
1472 5640 : for(unsigned i=0; i<narg; ++i) {
1473 5528 : sigma_mean2_tmp[i] = sigma_mean2_last_[iselect][i][0];
1474 5528 : valueSigmaMean[i]->set(sqrt(sigma_mean2_tmp[i]));
1475 : }
1476 66 : } else if(noise_type_==GAUSS||noise_type_==OUTLIERS) {
1477 132 : sigma_mean2_tmp[0] = sigma_mean2_last_[iselect][0][0];
1478 132 : valueSigmaMean[0]->set(sqrt(sigma_mean2_tmp[0]));
1479 : }
1480 : }
1481 :
1482 178 : sigma_mean2_ = sigma_mean2_tmp;
1483 178 : }
1484 :
1485 178 : void Metainference::replica_averaging(const double fact, vector<double> &mean, vector<double> &dmean_b)
1486 : {
1487 178 : if(master) {
1488 3216 : for(unsigned i=0; i<narg; ++i) mean[i] = fact*getArgument(i);
1489 178 : if(nrep_>1) multi_sim_comm.Sum(&mean[0], narg);
1490 : }
1491 356 : comm.Sum(&mean[0], narg);
1492 : // set the derivative of the mean with respect to the bias
1493 9244 : for(unsigned i=0; i<narg; ++i) dmean_b[i] = fact/kbt_*(getArgument(i)-mean[i])/static_cast<double>(average_weights_stride_);
1494 :
1495 : // this is only for generic metainference
1496 178 : if(firstTime) {ftilde_ = mean; firstTime = false;}
1497 178 : }
1498 :
1499 178 : void Metainference::calculate()
1500 : {
1501 : unsigned iselect = 0;
1502 : // set the value of selector for REM-like stuff
1503 178 : if(selector_.length()>0) iselect = static_cast<unsigned>(plumed.passMap[selector_]);
1504 :
1505 178 : double fact = 0.0;
1506 178 : double var_fact = 0.0;
1507 :
1508 178 : get_weights(iselect, fact, var_fact);
1509 :
1510 : // calculate the mean
1511 178 : vector<double> mean(narg,0);
1512 : // this is the derivative of the mean with respect to the argument
1513 178 : vector<double> dmean_x(narg,fact);
1514 : // this is the derivative of the mean with respect to the bias
1515 178 : vector<double> dmean_b(narg,0);
1516 : // calculate it
1517 178 : replica_averaging(fact, mean, dmean_b);
1518 :
1519 178 : get_sigma_mean(iselect, fact, var_fact, mean);
1520 :
1521 :
1522 : /* MONTE CARLO */
1523 178 : const long int step = getStep();
1524 178 : if(step%MCstride_==0&&!getExchangeStep()) doMonteCarlo(mean);
1525 :
1526 : // calculate bias and forces
1527 : double ene = 0;
1528 178 : switch(noise_type_) {
1529 12 : case GAUSS:
1530 12 : ene = getEnergyForceGJ(mean, dmean_x, dmean_b);
1531 : break;
1532 52 : case MGAUSS:
1533 52 : ene = getEnergyForceGJE(mean, dmean_x, dmean_b);
1534 : break;
1535 54 : case OUTLIERS:
1536 54 : ene = getEnergyForceSP(mean, dmean_x, dmean_b);
1537 : break;
1538 48 : case MOUTLIERS:
1539 48 : ene = getEnergyForceSPE(mean, dmean_x, dmean_b);
1540 : break;
1541 12 : case GENERIC:
1542 12 : ene = getEnergyForceMIGEN(mean, dmean_x, dmean_b);
1543 : break;
1544 : }
1545 :
1546 : // set value of the bias
1547 : setBias(ene);
1548 178 : }
1549 :
1550 19 : void Metainference::writeStatus()
1551 : {
1552 19 : sfile_.rewind();
1553 38 : sfile_.printField("time",getTimeStep()*getStep());
1554 : //nsel
1555 95 : for(unsigned i=0; i<sigma_mean2_last_.size(); i++) {
1556 : std::string msg_i,msg_j;
1557 19 : Tools::convert(i,msg_i);
1558 : vector <double> max_values;
1559 : //narg
1560 4849 : for(unsigned j=0; j<narg; ++j) {
1561 2415 : Tools::convert(j,msg_j);
1562 4830 : std::string msg = msg_i+"_"+msg_j;
1563 2415 : if(noise_type_==MGAUSS||noise_type_==MOUTLIERS||noise_type_==GENERIC) {
1564 7170 : sfile_.printField("sigma_mean_"+msg,sqrt(*max_element(sigma_mean2_last_[i][j].begin(), sigma_mean2_last_[i][j].end())));
1565 : } else {
1566 : // find maximum for each data point
1567 50 : max_values.push_back(*max_element(sigma_mean2_last_[i][j].begin(), sigma_mean2_last_[i][j].end()));
1568 : }
1569 : }
1570 19 : if(noise_type_==GAUSS||noise_type_==OUTLIERS) {
1571 : // find maximum across data points
1572 6 : const double max_now = sqrt(*max_element(max_values.begin(), max_values.end()));
1573 12 : sfile_.printField("sigma_mean_0_"+msg_i,max_now);
1574 : }
1575 : }
1576 7226 : for(unsigned i=0; i<sigma_.size(); ++i) {
1577 : std::string msg;
1578 2396 : Tools::convert(i,msg);
1579 4792 : sfile_.printField("sigma_"+msg,sigma_[i]);
1580 : }
1581 19 : if(noise_type_==GENERIC) {
1582 8 : for(unsigned i=0; i<ftilde_.size(); ++i) {
1583 : std::string msg;
1584 2 : Tools::convert(i,msg);
1585 4 : sfile_.printField("ftilde_"+msg,ftilde_[i]);
1586 : }
1587 : }
1588 38 : sfile_.printField("scale0_",scale_);
1589 38 : sfile_.printField("offset0_",offset_);
1590 95 : for(unsigned i=0; i<average_weights_.size(); i++) {
1591 : std::string msg_i;
1592 19 : Tools::convert(i,msg_i);
1593 57 : sfile_.printField("weight_"+msg_i,average_weights_[i][replica_]);
1594 : }
1595 19 : sfile_.printField();
1596 19 : sfile_.flush();
1597 19 : }
1598 :
1599 178 : void Metainference::update() {
1600 : // write status file
1601 178 : if(write_stride_>0&& (getStep()%write_stride_==0 || getCPT()) ) writeStatus();
1602 178 : }
1603 :
1604 : }
1605 4839 : }
1606 :
|