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 implenting 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 : // CoeffsMatrix* switchToDiagonalHessian(VesBias*); 135 : // CoeffsMatrix* switchToFullHessian(VesBias*); 136 : // 137 : CoeffsVector& Coeffs(const unsigned int coeffs_id = 0) const; 138 : CoeffsVector& AuxCoeffs(const unsigned int coeffs_id = 0) const; 139 : CoeffsVector& Gradient(const unsigned int coeffs_id = 0) const; 140 : CoeffsMatrix& Hessian(const unsigned int coeffs_id = 0) const; 141 : CoeffsVector& CoeffsMask(const unsigned int coeffs_id = 0) const; 142 : CoeffsVector& TargetDistAverages(const unsigned int coeffs_id = 0) const; 143 : double StepSize(const unsigned int coeffs_id = 0) const; 144 : virtual void coeffsUpdate(const unsigned int coeffs_id = 0) = 0; 145 : void setCurrentStepSize(const double,const unsigned int i = 0); 146 : void setCurrentStepSizes(const std::vector<double>&); 147 : // 148 : void turnOffCoeffsOutputFiles(); 149 : // 150 : template<class T> 151 : bool parseMultipleValues(const std::string&, std::vector<T>&); 152 : template<class T> 153 : bool parseMultipleValues(const std::string&, std::vector<T>&, const T&); 154 : void parseFilenames(const std::string&, std::vector<std::string>&, const std::string&); 155 : void parseFilenames(const std::string&, std::vector<std::string>&); 156 : void addCoeffsSetIDsToFilenames(std::vector<std::string>&, std::string&); 157 : void setupOFiles(std::vector<std::string>&, std::vector<std::unique_ptr<OFile>>&, const bool multi_sim_single_files=false); 158 : public: 159 : static void registerKeywords(Keywords&); 160 : static void useMultipleWalkersKeywords(Keywords&); 161 : static void useHessianKeywords(Keywords&); 162 : static void useFixedStepSizeKeywords(Keywords&); 163 : static void useDynamicStepSizeKeywords(Keywords&); 164 : static void useMaskKeywords(Keywords&); 165 : static void useRestartKeywords(Keywords&); 166 : static void useMonitorAverageGradientKeywords(Keywords&); 167 : static void useDynamicTargetDistributionKeywords(Keywords&); 168 : static void useReweightFactorKeywords(Keywords&); 169 : // 170 : explicit Optimizer(const ActionOptions&ao); 171 : ~Optimizer(); 172 : std::string getType() const { 173 : return type_; 174 : } 175 : std::string getDescription() const { 176 : return description_; 177 : } 178 : // 179 : unsigned int numberOfBiases() const { 180 : return nbiases_; 181 : } 182 : unsigned int numberOfCoeffsSets() const { 183 16 : return ncoeffssets_; 184 : } 185 : // 186 : std::vector<double> getStepSizes() const; 187 : std::vector<double> getCurrentStepSizes() const; 188 : double getStepSize(const unsigned int coeffs_id = 0) const; 189 : double getCurrentStepSize(const unsigned int coeffs_id = 0) const; 190 : void setStepSizes(const std::vector<double>&); 191 : void setStepSize(const double, const unsigned int coeffs_id = 0); 192 : // 193 : unsigned int getIterationCounter() const; 194 : double getIterationCounterDbl() const; 195 : std::string getIterationCounterStr(const int offset=0) const; 196 : void setIterationCounter(const unsigned int); 197 : void increaseIterationCounter(); 198 : // 199 22879 : void apply() override {}; 200 22879 : void calculate() override {}; 201 : void update() override; 202 0 : unsigned int getNumberOfDerivatives() override { 203 0 : return 0; 204 : } 205 : // 206 : bool fixedStepSize() const { 207 : return fixed_stepsize_; 208 : } 209 : bool dynamicStepSize() const { 210 : return !fixed_stepsize_; 211 : } 212 : // 213 : bool useHessian() const { 214 : return use_hessian_; 215 : } 216 : bool diagonalHessian() const { 217 : return diagonal_hessian_; 218 : } 219 : // 220 : bool useMultipleWalkers() const { 221 609 : return use_mwalkers_mpi_; 222 : } 223 : // 224 : std::vector<VesBias*> getBiasPntrs() const { 225 : return bias_pntrs_; 226 : } 227 : std::vector<CoeffsVector*> getCoeffsPntrs() const { 228 : return coeffs_pntrs_; 229 : } 230 : std::vector<CoeffsVector*> getAuxCoeffsPntrs() const { 231 : return Tools::unique2raw(aux_coeffs_pntrs_); 232 : } 233 : std::vector<CoeffsVector*> getGradientPntrs()const { 234 12 : return gradient_pntrs_; 235 : } 236 : std::vector<CoeffsMatrix*> getHessianPntrs() const { 237 : return hessian_pntrs_; 238 : } 239 : std::vector<CoeffsVector*> getCoeffsMaskPntrs() const { 240 : return Tools::unique2raw(coeffs_mask_pntrs_); 241 : } 242 : std::vector<CoeffsVector*> getTargetDistAveragesPntrs() const { 243 : return targetdist_averages_pntrs_; 244 : } 245 : // 246 : bool isBiasOutputActive() const { 247 22829 : return bias_output_active_; 248 : } 249 : unsigned int getBiasOutputStride() const { 250 814 : return bias_output_stride_; 251 : } 252 : void setBiasOutputStride(unsigned int stride) { 253 : bias_output_stride_=stride; 254 : } 255 : void writeBiasOutputFiles() const; 256 : // 257 : bool isFesOutputActive() const { 258 22829 : return fes_output_active_; 259 : } 260 : unsigned int getFesOutputStride() const { 261 814 : return fes_output_stride_; 262 : } 263 : void setFesOutputStride(unsigned int stride) { 264 : fes_output_stride_=stride; 265 : } 266 : void writeFesOutputFiles() const; 267 : // 268 : bool isFesProjOutputActive() const { 269 22829 : return fesproj_output_active_; 270 : } 271 : unsigned int getFesProjOutputStride() const { 272 176 : return fesproj_output_stride_; 273 : } 274 : void setFesProjOutputStride(unsigned int stride) { 275 : fesproj_output_stride_=stride; 276 : } 277 : void writeFesProjOutputFiles() const; 278 : // 279 : bool isTargetDistOutputActive() const { 280 22908 : return targetdist_output_active_; 281 : } 282 : unsigned int getTargetDistOutputStride() const { 283 22367 : return targetdist_output_stride_; 284 : } 285 : void setTargetDistOutputStride(unsigned int stride) { 286 : targetdist_output_stride_=stride; 287 : } 288 : void writeTargetDistOutputFiles() const; 289 : // 290 : bool isTargetDistProjOutputActive() const { 291 22829 : return targetdist_proj_output_active_; 292 : } 293 : unsigned int getTargetDistProjOutputStride() const { 294 33 : return targetdist_proj_output_stride_; 295 : } 296 : void setTargetDistProjOutputStride(unsigned int stride) { 297 : targetdist_proj_output_stride_=stride; 298 : } 299 : void writeTargetDistProjOutputFiles() const; 300 : // 301 : }; 302 : 303 : inline 304 : double Optimizer::StepSize(const unsigned int coeffs_id) const { 305 22705 : return stepsizes_[coeffs_id]; 306 : } 307 : 308 : inline 309 : CoeffsVector& Optimizer::Coeffs(const unsigned int coeffs_id) const { 310 68214 : return *coeffs_pntrs_[coeffs_id]; 311 : } 312 : 313 : inline 314 : CoeffsVector& Optimizer::AuxCoeffs(const unsigned int coeffs_id) const { 315 21 : return *aux_coeffs_pntrs_[coeffs_id]; 316 : } 317 : 318 : inline 319 : CoeffsVector& Optimizer::Gradient(const unsigned int coeffs_id) const { 320 22785 : return *gradient_pntrs_[coeffs_id]; 321 : } 322 : 323 : inline 324 22735 : CoeffsMatrix& Optimizer::Hessian(const unsigned int coeffs_id) const { 325 22735 : plumed_massert(use_hessian_,"You cannot use the Hessian without asking for before"); 326 22735 : return *hessian_pntrs_[coeffs_id]; 327 : } 328 : 329 : inline 330 : CoeffsVector& Optimizer::CoeffsMask(const unsigned int coeffs_id) const { 331 : return *coeffs_mask_pntrs_[coeffs_id]; 332 : } 333 : 334 : inline 335 : std::vector<double> Optimizer::getStepSizes() const { 336 : return stepsizes_; 337 : } 338 : 339 : inline 340 : std::vector<double> Optimizer::getCurrentStepSizes() const { 341 : return current_stepsizes; 342 : } 343 : 344 : inline 345 : double Optimizer::getStepSize(const unsigned int coeffs_id) const { 346 : return stepsizes_[coeffs_id]; 347 : } 348 : 349 : inline 350 : double Optimizer::getCurrentStepSize(const unsigned int coeffs_id) const { 351 11 : return current_stepsizes[coeffs_id]; 352 : } 353 : 354 : inline 355 : void Optimizer::setStepSizes(const std::vector<double>& stepsizes_in) { 356 : plumed_assert(stepsizes_in.size()==ncoeffssets_); 357 : stepsizes_ = stepsizes_in; 358 : } 359 : 360 : inline 361 : void Optimizer::setStepSize(const double stepsize_in, const unsigned int coeffs_id) { 362 : stepsizes_[coeffs_id] = stepsize_in; 363 : } 364 : 365 : inline 366 : void Optimizer::setCurrentStepSize(const double current_stepsize_in, const unsigned int coeffs_id) { 367 10 : current_stepsizes[coeffs_id] = current_stepsize_in; 368 : } 369 : 370 : inline 371 78 : void Optimizer::setCurrentStepSizes(const std::vector<double>& current_stepsizes_in) { 372 78 : plumed_assert(current_stepsizes_in.size()==ncoeffssets_); 373 78 : current_stepsizes = current_stepsizes_in; 374 78 : } 375 : 376 : inline 377 : unsigned int Optimizer::getIterationCounter() const { 378 48388 : return iter_counter; 379 : } 380 : 381 : inline 382 : double Optimizer::getIterationCounterDbl() const { 383 22695 : return static_cast<double>(iter_counter); 384 : } 385 : 386 : inline 387 : void Optimizer::increaseIterationCounter() { 388 22750 : iter_counter++; 389 : } 390 : 391 : inline 392 : void Optimizer::setIterationCounter(const unsigned int iter_counter_in) { 393 13 : iter_counter = iter_counter_in; 394 : } 395 : 396 : 397 : template<class T> 398 623 : bool Optimizer::parseMultipleValues(const std::string& keyword, std::vector<T>& values) { 399 623 : plumed_assert(ncoeffssets_>0); 400 623 : plumed_assert(values.size()==0); 401 : bool identical_values=false; 402 : // 403 623 : parseVector(keyword,values); 404 623 : if(values.size()==1 && ncoeffssets_>1) { 405 9 : values.resize(ncoeffssets_,values[0]); 406 : identical_values=true; 407 : } 408 623 : if(values.size()>0 && values.size()!=ncoeffssets_) { 409 : std::string s1; 410 0 : Tools::convert(ncoeffssets_,s1); 411 0 : plumed_merror("Error in " + keyword + " keyword: either give 1 common value for all coefficient sets or " + s1 + " separate value for each set"); 412 : } 413 623 : return identical_values; 414 : } 415 : 416 : template<class T> 417 158 : bool Optimizer::parseMultipleValues(const std::string& keyword, std::vector<T>& values, const T& default_value) { 418 158 : bool identical_values = parseMultipleValues(keyword,values); 419 158 : if(values.size()==0) { 420 79 : values.resize(ncoeffssets_,default_value); 421 : identical_values=true; 422 : } 423 158 : return identical_values; 424 : } 425 : 426 : inline 427 158 : void Optimizer::parseFilenames(const std::string& keyword, std::vector<std::string>& fnames, const std::string& default_fname) { 428 158 : if(parseMultipleValues<std::string>(keyword,fnames,default_fname)) { 429 81 : addCoeffsSetIDsToFilenames(fnames,coeffssetid_prefix_); 430 : } 431 158 : } 432 : 433 : inline 434 387 : void Optimizer::parseFilenames(const std::string& keyword, std::vector<std::string>& fnames) { 435 387 : if(parseMultipleValues<std::string>(keyword,fnames)) { 436 4 : addCoeffsSetIDsToFilenames(fnames,coeffssetid_prefix_); 437 : } 438 387 : } 439 : 440 : 441 : } 442 : } 443 : 444 : #endif