Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 : Copyright (c) 2016-2021 The VES code team 3 : (see the PEOPLE-VES file at the root of this folder for a list of names) 4 : 5 : See http://www.ves-code.org for more information. 6 : 7 : This file is part of VES code module. 8 : 9 : The VES code module 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 : The VES code module 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 the VES code module. If not, see <http://www.gnu.org/licenses/>. 21 : +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ 22 : #ifndef __PLUMED_ves_Optimizer_h 23 : #define __PLUMED_ves_Optimizer_h 24 : 25 : #include "VesBias.h" 26 : 27 : #include "core/ActionPilot.h" 28 : #include "core/ActionWithValue.h" 29 : 30 : #include <vector> 31 : #include <string> 32 : #include <cmath> 33 : #include <memory> 34 : 35 : 36 : #define PLUMED_VES_OPTIMIZER_INIT(ao) Action(ao),Optimizer(ao) 37 : 38 : namespace PLMD { 39 : 40 : /** 41 : \ingroup INHERIT 42 : Abstract base class for implementing new optimization methods 43 : */ 44 : 45 : class OFile; 46 : 47 : namespace ves { 48 : 49 : class CoeffsVector; 50 : class VesBias; 51 : 52 : 53 : class Optimizer : 54 : public ActionPilot, 55 : public ActionWithValue { 56 : private: 57 : const std::string description_; 58 : const std::string type_; 59 : // 60 : std::vector<double> stepsizes_; 61 : std::vector<double> current_stepsizes; 62 : bool fixed_stepsize_; 63 : // 64 : unsigned int iter_counter; 65 : // 66 : bool use_hessian_; 67 : bool diagonal_hessian_; 68 : bool hessian_covariance_from_averages_; 69 : // 70 : bool monitor_instantaneous_gradient_; 71 : // 72 : bool use_mwalkers_mpi_; 73 : bool mwalkers_mpi_single_files_; 74 : // 75 : std::vector<bool> dynamic_targetdists_; 76 : unsigned int ustride_targetdist_; 77 : // 78 : unsigned int ustride_reweightfactor_; 79 : // 80 : std::string coeffssetid_prefix_; 81 : // 82 : unsigned int coeffs_wstride_; 83 : std::vector<std::unique_ptr<OFile>> coeffsOFiles_; 84 : std::string coeffs_output_fmt_; 85 : // 86 : unsigned int gradient_wstride_; 87 : std::vector<std::unique_ptr<OFile>> gradientOFiles_; 88 : std::string gradient_output_fmt_; 89 : // 90 : unsigned int hessian_wstride_; 91 : std::vector<std::unique_ptr<OFile>> hessianOFiles_; 92 : std::string hessian_output_fmt_; 93 : // 94 : unsigned int targetdist_averages_wstride_; 95 : std::vector<std::unique_ptr<OFile>> targetdist_averagesOFiles_; 96 : std::string targetdist_averages_output_fmt_; 97 : // 98 : unsigned int nbiases_; 99 : std::vector<VesBias*> bias_pntrs_; 100 : // 101 : unsigned int ncoeffssets_; 102 : std::vector<CoeffsVector*> coeffs_pntrs_; 103 : std::vector<std::unique_ptr<CoeffsVector>> aux_coeffs_pntrs_; 104 : std::vector<CoeffsVector*> gradient_pntrs_; 105 : std::vector<std::unique_ptr<CoeffsVector>> aver_gradient_pntrs_; 106 : std::vector<CoeffsMatrix*> hessian_pntrs_; 107 : std::vector<std::unique_ptr<CoeffsVector>> coeffs_mask_pntrs_; 108 : std::vector<CoeffsVector*> targetdist_averages_pntrs_; 109 : // 110 : bool identical_coeffs_shape_; 111 : // 112 : bool bias_output_active_; 113 : unsigned int bias_output_stride_; 114 : bool fes_output_active_; 115 : unsigned int fes_output_stride_; 116 : bool fesproj_output_active_; 117 : unsigned int fesproj_output_stride_; 118 : bool targetdist_output_active_; 119 : unsigned int targetdist_output_stride_; 120 : bool targetdist_proj_output_active_; 121 : unsigned int targetdist_proj_output_stride_; 122 : // 123 : bool isFirstStep; 124 : // 125 : private: 126 : void updateOutputComponents(); 127 : void writeOutputFiles(const unsigned int coeffs_id = 0); 128 : void readCoeffsFromFiles(const std::vector<std::string>&, const bool); 129 : void setAllCoeffsSetIterationCounters(); 130 : protected: 131 : void turnOnHessian(); 132 : void turnOffHessian(); 133 : std::vector<CoeffsMatrix*> enableHessian(VesBias*, const bool diagonal_hessian=false); 134 : CoeffsVector& Coeffs(const unsigned int coeffs_id = 0) const; 135 : CoeffsVector& AuxCoeffs(const unsigned int coeffs_id = 0) const; 136 : CoeffsVector& Gradient(const unsigned int coeffs_id = 0) const; 137 : CoeffsMatrix& Hessian(const unsigned int coeffs_id = 0) const; 138 : CoeffsVector& CoeffsMask(const unsigned int coeffs_id = 0) const; 139 : CoeffsVector& TargetDistAverages(const unsigned int coeffs_id = 0) const; 140 : double StepSize(const unsigned int coeffs_id = 0) const; 141 : virtual void coeffsUpdate(const unsigned int coeffs_id = 0) = 0; 142 : void setCurrentStepSize(const double,const unsigned int i = 0); 143 : void setCurrentStepSizes(const std::vector<double>&); 144 : // 145 : void turnOffCoeffsOutputFiles(); 146 : // 147 : template<class T> 148 : bool parseMultipleValues(const std::string&, std::vector<T>&); 149 : template<class T> 150 : bool parseMultipleValues(const std::string&, std::vector<T>&, const T&); 151 : void parseFilenames(const std::string&, std::vector<std::string>&, const std::string&); 152 : void parseFilenames(const std::string&, std::vector<std::string>&); 153 : void addCoeffsSetIDsToFilenames(std::vector<std::string>&, std::string&); 154 : void setupOFiles(std::vector<std::string>&, std::vector<std::unique_ptr<OFile>>&, const bool multi_sim_single_files=false); 155 : public: 156 : static void registerKeywords(Keywords&); 157 : static void useMultipleWalkersKeywords(Keywords&); 158 : static void useHessianKeywords(Keywords&); 159 : static void useFixedStepSizeKeywords(Keywords&); 160 : static void useDynamicStepSizeKeywords(Keywords&); 161 : static void useMaskKeywords(Keywords&); 162 : static void useRestartKeywords(Keywords&); 163 : static void useMonitorAverageGradientKeywords(Keywords&); 164 : static void useDynamicTargetDistributionKeywords(Keywords&); 165 : static void useReweightFactorKeywords(Keywords&); 166 : // 167 : explicit Optimizer(const ActionOptions&ao); 168 : ~Optimizer(); 169 : std::string getType() const { 170 : return type_; 171 : } 172 : std::string getDescription() const { 173 : return description_; 174 : } 175 : // 176 : unsigned int numberOfBiases() const { 177 : return nbiases_; 178 : } 179 : unsigned int numberOfCoeffsSets() const { 180 16 : return ncoeffssets_; 181 : } 182 : // 183 : std::vector<double> getStepSizes() const; 184 : std::vector<double> getCurrentStepSizes() const; 185 : double getStepSize(const unsigned int coeffs_id = 0) const; 186 : double getCurrentStepSize(const unsigned int coeffs_id = 0) const; 187 : void setStepSizes(const std::vector<double>&); 188 : void setStepSize(const double, const unsigned int coeffs_id = 0); 189 : // 190 : unsigned int getIterationCounter() const; 191 : double getIterationCounterDbl() const; 192 : std::string getIterationCounterStr(const int offset=0) const; 193 : void setIterationCounter(const unsigned int); 194 : void increaseIterationCounter(); 195 : // 196 22879 : void apply() override {}; 197 22879 : void calculate() override {}; 198 : void update() override; 199 0 : unsigned int getNumberOfDerivatives() override { 200 0 : return 0; 201 : } 202 : // 203 : bool fixedStepSize() const { 204 : return fixed_stepsize_; 205 : } 206 : bool dynamicStepSize() const { 207 : return !fixed_stepsize_; 208 : } 209 : // 210 : bool useHessian() const { 211 : return use_hessian_; 212 : } 213 : bool diagonalHessian() const { 214 : return diagonal_hessian_; 215 : } 216 : // 217 : bool useMultipleWalkers() const { 218 609 : return use_mwalkers_mpi_; 219 : } 220 : // 221 : std::vector<VesBias*> getBiasPntrs() const { 222 : return bias_pntrs_; 223 : } 224 : std::vector<CoeffsVector*> getCoeffsPntrs() const { 225 : return coeffs_pntrs_; 226 : } 227 : std::vector<CoeffsVector*> getAuxCoeffsPntrs() const { 228 : return Tools::unique2raw(aux_coeffs_pntrs_); 229 : } 230 : std::vector<CoeffsVector*> getGradientPntrs()const { 231 12 : return gradient_pntrs_; 232 : } 233 : std::vector<CoeffsMatrix*> getHessianPntrs() const { 234 : return hessian_pntrs_; 235 : } 236 : std::vector<CoeffsVector*> getCoeffsMaskPntrs() const { 237 : return Tools::unique2raw(coeffs_mask_pntrs_); 238 : } 239 : std::vector<CoeffsVector*> getTargetDistAveragesPntrs() const { 240 : return targetdist_averages_pntrs_; 241 : } 242 : // 243 : bool isBiasOutputActive() const { 244 22829 : return bias_output_active_; 245 : } 246 : unsigned int getBiasOutputStride() const { 247 814 : return bias_output_stride_; 248 : } 249 : void setBiasOutputStride(unsigned int stride) { 250 : bias_output_stride_=stride; 251 : } 252 : void writeBiasOutputFiles() const; 253 : // 254 : bool isFesOutputActive() const { 255 22829 : return fes_output_active_; 256 : } 257 : unsigned int getFesOutputStride() const { 258 814 : return fes_output_stride_; 259 : } 260 : void setFesOutputStride(unsigned int stride) { 261 : fes_output_stride_=stride; 262 : } 263 : void writeFesOutputFiles() const; 264 : // 265 : bool isFesProjOutputActive() const { 266 22829 : return fesproj_output_active_; 267 : } 268 : unsigned int getFesProjOutputStride() const { 269 176 : return fesproj_output_stride_; 270 : } 271 : void setFesProjOutputStride(unsigned int stride) { 272 : fesproj_output_stride_=stride; 273 : } 274 : void writeFesProjOutputFiles() const; 275 : // 276 : bool isTargetDistOutputActive() const { 277 22908 : return targetdist_output_active_; 278 : } 279 : unsigned int getTargetDistOutputStride() const { 280 22367 : return targetdist_output_stride_; 281 : } 282 : void setTargetDistOutputStride(unsigned int stride) { 283 : targetdist_output_stride_=stride; 284 : } 285 : void writeTargetDistOutputFiles() const; 286 : // 287 : bool isTargetDistProjOutputActive() const { 288 22829 : return targetdist_proj_output_active_; 289 : } 290 : unsigned int getTargetDistProjOutputStride() const { 291 33 : return targetdist_proj_output_stride_; 292 : } 293 : void setTargetDistProjOutputStride(unsigned int stride) { 294 : targetdist_proj_output_stride_=stride; 295 : } 296 : void writeTargetDistProjOutputFiles() const; 297 : // 298 : }; 299 : 300 : inline 301 : double Optimizer::StepSize(const unsigned int coeffs_id) const { 302 22705 : return stepsizes_[coeffs_id]; 303 : } 304 : 305 : inline 306 : CoeffsVector& Optimizer::Coeffs(const unsigned int coeffs_id) const { 307 68214 : return *coeffs_pntrs_[coeffs_id]; 308 : } 309 : 310 : inline 311 : CoeffsVector& Optimizer::AuxCoeffs(const unsigned int coeffs_id) const { 312 21 : return *aux_coeffs_pntrs_[coeffs_id]; 313 : } 314 : 315 : inline 316 : CoeffsVector& Optimizer::Gradient(const unsigned int coeffs_id) const { 317 22785 : return *gradient_pntrs_[coeffs_id]; 318 : } 319 : 320 : inline 321 22735 : CoeffsMatrix& Optimizer::Hessian(const unsigned int coeffs_id) const { 322 22735 : plumed_massert(use_hessian_,"You cannot use the Hessian without asking for before"); 323 22735 : return *hessian_pntrs_[coeffs_id]; 324 : } 325 : 326 : inline 327 : CoeffsVector& Optimizer::CoeffsMask(const unsigned int coeffs_id) const { 328 : return *coeffs_mask_pntrs_[coeffs_id]; 329 : } 330 : 331 : inline 332 : std::vector<double> Optimizer::getStepSizes() const { 333 : return stepsizes_; 334 : } 335 : 336 : inline 337 : std::vector<double> Optimizer::getCurrentStepSizes() const { 338 : return current_stepsizes; 339 : } 340 : 341 : inline 342 : double Optimizer::getStepSize(const unsigned int coeffs_id) const { 343 : return stepsizes_[coeffs_id]; 344 : } 345 : 346 : inline 347 : double Optimizer::getCurrentStepSize(const unsigned int coeffs_id) const { 348 11 : return current_stepsizes[coeffs_id]; 349 : } 350 : 351 : inline 352 : void Optimizer::setStepSizes(const std::vector<double>& stepsizes_in) { 353 : plumed_assert(stepsizes_in.size()==ncoeffssets_); 354 : stepsizes_ = stepsizes_in; 355 : } 356 : 357 : inline 358 : void Optimizer::setStepSize(const double stepsize_in, const unsigned int coeffs_id) { 359 : stepsizes_[coeffs_id] = stepsize_in; 360 : } 361 : 362 : inline 363 : void Optimizer::setCurrentStepSize(const double current_stepsize_in, const unsigned int coeffs_id) { 364 10 : current_stepsizes[coeffs_id] = current_stepsize_in; 365 : } 366 : 367 : inline 368 78 : void Optimizer::setCurrentStepSizes(const std::vector<double>& current_stepsizes_in) { 369 78 : plumed_assert(current_stepsizes_in.size()==ncoeffssets_); 370 78 : current_stepsizes = current_stepsizes_in; 371 78 : } 372 : 373 : inline 374 : unsigned int Optimizer::getIterationCounter() const { 375 48388 : return iter_counter; 376 : } 377 : 378 : inline 379 : double Optimizer::getIterationCounterDbl() const { 380 22695 : return static_cast<double>(iter_counter); 381 : } 382 : 383 : inline 384 : void Optimizer::increaseIterationCounter() { 385 22750 : iter_counter++; 386 : } 387 : 388 : inline 389 : void Optimizer::setIterationCounter(const unsigned int iter_counter_in) { 390 13 : iter_counter = iter_counter_in; 391 : } 392 : 393 : 394 : template<class T> 395 623 : bool Optimizer::parseMultipleValues(const std::string& keyword, std::vector<T>& values) { 396 623 : plumed_assert(ncoeffssets_>0); 397 623 : plumed_assert(values.size()==0); 398 : bool identical_values=false; 399 : // 400 623 : parseVector(keyword,values); 401 623 : if(values.size()==1 && ncoeffssets_>1) { 402 9 : values.resize(ncoeffssets_,values[0]); 403 : identical_values=true; 404 : } 405 623 : if(values.size()>0 && values.size()!=ncoeffssets_) { 406 : std::string s1; 407 0 : Tools::convert(ncoeffssets_,s1); 408 0 : plumed_merror("Error in " + keyword + " keyword: either give 1 common value for all coefficient sets or " + s1 + " separate value for each set"); 409 : } 410 623 : return identical_values; 411 : } 412 : 413 : template<class T> 414 158 : bool Optimizer::parseMultipleValues(const std::string& keyword, std::vector<T>& values, const T& default_value) { 415 158 : bool identical_values = parseMultipleValues(keyword,values); 416 158 : if(values.size()==0) { 417 79 : values.resize(ncoeffssets_,default_value); 418 : identical_values=true; 419 : } 420 158 : return identical_values; 421 : } 422 : 423 : inline 424 158 : void Optimizer::parseFilenames(const std::string& keyword, std::vector<std::string>& fnames, const std::string& default_fname) { 425 158 : if(parseMultipleValues<std::string>(keyword,fnames,default_fname)) { 426 81 : addCoeffsSetIDsToFilenames(fnames,coeffssetid_prefix_); 427 : } 428 158 : } 429 : 430 : inline 431 387 : void Optimizer::parseFilenames(const std::string& keyword, std::vector<std::string>& fnames) { 432 387 : if(parseMultipleValues<std::string>(keyword,fnames)) { 433 4 : addCoeffsSetIDsToFilenames(fnames,coeffssetid_prefix_); 434 : } 435 387 : } 436 : 437 : 438 : } 439 : } 440 : 441 : #endif