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 : { 57 : private: 58 : const std::string description_; 59 : const std::string type_; 60 : // 61 : std::vector<double> stepsizes_; 62 : std::vector<double> current_stepsizes; 63 : bool fixed_stepsize_; 64 : // 65 : unsigned int iter_counter; 66 : // 67 : bool use_hessian_; 68 : bool diagonal_hessian_; 69 : bool hessian_covariance_from_averages_; 70 : // 71 : bool monitor_instantaneous_gradient_; 72 : // 73 : bool use_mwalkers_mpi_; 74 : bool mwalkers_mpi_single_files_; 75 : // 76 : std::vector<bool> dynamic_targetdists_; 77 : unsigned int ustride_targetdist_; 78 : // 79 : unsigned int ustride_reweightfactor_; 80 : // 81 : std::string coeffssetid_prefix_; 82 : // 83 : unsigned int coeffs_wstride_; 84 : std::vector<std::unique_ptr<OFile>> coeffsOFiles_; 85 : std::string coeffs_output_fmt_; 86 : // 87 : unsigned int gradient_wstride_; 88 : std::vector<std::unique_ptr<OFile>> gradientOFiles_; 89 : std::string gradient_output_fmt_; 90 : // 91 : unsigned int hessian_wstride_; 92 : std::vector<std::unique_ptr<OFile>> hessianOFiles_; 93 : std::string hessian_output_fmt_; 94 : // 95 : unsigned int targetdist_averages_wstride_; 96 : std::vector<std::unique_ptr<OFile>> targetdist_averagesOFiles_; 97 : std::string targetdist_averages_output_fmt_; 98 : // 99 : unsigned int nbiases_; 100 : std::vector<VesBias*> bias_pntrs_; 101 : // 102 : unsigned int ncoeffssets_; 103 : std::vector<CoeffsVector*> coeffs_pntrs_; 104 : std::vector<std::unique_ptr<CoeffsVector>> aux_coeffs_pntrs_; 105 : std::vector<CoeffsVector*> gradient_pntrs_; 106 : std::vector<std::unique_ptr<CoeffsVector>> aver_gradient_pntrs_; 107 : std::vector<CoeffsMatrix*> hessian_pntrs_; 108 : std::vector<std::unique_ptr<CoeffsVector>> coeffs_mask_pntrs_; 109 : std::vector<CoeffsVector*> targetdist_averages_pntrs_; 110 : // 111 : bool identical_coeffs_shape_; 112 : // 113 : bool bias_output_active_; 114 : unsigned int bias_output_stride_; 115 : bool fes_output_active_; 116 : unsigned int fes_output_stride_; 117 : bool fesproj_output_active_; 118 : unsigned int fesproj_output_stride_; 119 : bool targetdist_output_active_; 120 : unsigned int targetdist_output_stride_; 121 : bool targetdist_proj_output_active_; 122 : unsigned int targetdist_proj_output_stride_; 123 : // 124 : bool isFirstStep; 125 : // 126 : private: 127 : void updateOutputComponents(); 128 : void writeOutputFiles(const unsigned int coeffs_id = 0); 129 : void readCoeffsFromFiles(const std::vector<std::string>&, const bool); 130 : void setAllCoeffsSetIterationCounters(); 131 : protected: 132 : void turnOnHessian(); 133 : void turnOffHessian(); 134 : std::vector<CoeffsMatrix*> enableHessian(VesBias*, const bool diagonal_hessian=false); 135 : // CoeffsMatrix* switchToDiagonalHessian(VesBias*); 136 : // CoeffsMatrix* switchToFullHessian(VesBias*); 137 : // 138 : CoeffsVector& Coeffs(const unsigned int coeffs_id = 0) const; 139 : CoeffsVector& AuxCoeffs(const unsigned int coeffs_id = 0) const; 140 : CoeffsVector& Gradient(const unsigned int coeffs_id = 0) const; 141 : CoeffsMatrix& Hessian(const unsigned int coeffs_id = 0) const; 142 : CoeffsVector& CoeffsMask(const unsigned int coeffs_id = 0) const; 143 : CoeffsVector& TargetDistAverages(const unsigned int coeffs_id = 0) const; 144 : double StepSize(const unsigned int coeffs_id = 0) const; 145 : virtual void coeffsUpdate(const unsigned int coeffs_id = 0) = 0; 146 : void setCurrentStepSize(const double,const unsigned int i = 0); 147 : void setCurrentStepSizes(const std::vector<double>&); 148 : // 149 : void turnOffCoeffsOutputFiles(); 150 : // 151 : template<class T> 152 : bool parseMultipleValues(const std::string&, std::vector<T>&); 153 : template<class T> 154 : bool parseMultipleValues(const std::string&, std::vector<T>&, const T&); 155 : void parseFilenames(const std::string&, std::vector<std::string>&, const std::string&); 156 : void parseFilenames(const std::string&, std::vector<std::string>&); 157 : void addCoeffsSetIDsToFilenames(std::vector<std::string>&, std::string&); 158 : void setupOFiles(std::vector<std::string>&, std::vector<std::unique_ptr<OFile>>&, const bool multi_sim_single_files=false); 159 : public: 160 : static void registerKeywords(Keywords&); 161 : static void useMultipleWalkersKeywords(Keywords&); 162 : static void useHessianKeywords(Keywords&); 163 : static void useFixedStepSizeKeywords(Keywords&); 164 : static void useDynamicStepSizeKeywords(Keywords&); 165 : static void useMaskKeywords(Keywords&); 166 : static void useRestartKeywords(Keywords&); 167 : static void useMonitorAverageGradientKeywords(Keywords&); 168 : static void useDynamicTargetDistributionKeywords(Keywords&); 169 : static void useReweightFactorKeywords(Keywords&); 170 : // 171 : explicit Optimizer(const ActionOptions&ao); 172 : ~Optimizer(); 173 : std::string getType() const {return type_;} 174 : std::string getDescription() const {return description_;} 175 : // 176 : unsigned int numberOfBiases() const {return nbiases_;} 177 16 : unsigned int numberOfCoeffsSets() const {return ncoeffssets_;} 178 : // 179 : std::vector<double> getStepSizes() const; 180 : std::vector<double> getCurrentStepSizes() const; 181 : double getStepSize(const unsigned int coeffs_id = 0) const; 182 : double getCurrentStepSize(const unsigned int coeffs_id = 0) const; 183 : void setStepSizes(const std::vector<double>&); 184 : void setStepSize(const double, const unsigned int coeffs_id = 0); 185 : // 186 : unsigned int getIterationCounter() const; 187 : double getIterationCounterDbl() const; 188 : std::string getIterationCounterStr(const int offset=0) const; 189 : void setIterationCounter(const unsigned int); 190 : void increaseIterationCounter(); 191 : // 192 22879 : void apply() override {}; 193 22879 : void calculate() override {}; 194 : void update() override; 195 0 : unsigned int getNumberOfDerivatives() override {return 0;} 196 : // 197 : bool fixedStepSize() const {return fixed_stepsize_;} 198 : bool dynamicStepSize() const {return !fixed_stepsize_;} 199 : // 200 : bool useHessian() const {return use_hessian_;} 201 : bool diagonalHessian() const {return diagonal_hessian_;} 202 : // 203 609 : bool useMultipleWalkers() const {return use_mwalkers_mpi_;} 204 : // 205 : std::vector<VesBias*> getBiasPntrs() const {return bias_pntrs_;} 206 : std::vector<CoeffsVector*> getCoeffsPntrs() const {return coeffs_pntrs_;} 207 : std::vector<CoeffsVector*> getAuxCoeffsPntrs() const {return Tools::unique2raw(aux_coeffs_pntrs_);} 208 12 : std::vector<CoeffsVector*> getGradientPntrs()const {return gradient_pntrs_;} 209 : std::vector<CoeffsMatrix*> getHessianPntrs() const {return hessian_pntrs_;} 210 : std::vector<CoeffsVector*> getCoeffsMaskPntrs() const {return Tools::unique2raw(coeffs_mask_pntrs_);} 211 : std::vector<CoeffsVector*> getTargetDistAveragesPntrs() const {return targetdist_averages_pntrs_;} 212 : // 213 22829 : bool isBiasOutputActive() const {return bias_output_active_;} 214 814 : unsigned int getBiasOutputStride() const {return bias_output_stride_;} 215 : void setBiasOutputStride(unsigned int stride) {bias_output_stride_=stride;} 216 : void writeBiasOutputFiles() const; 217 : // 218 22829 : bool isFesOutputActive() const {return fes_output_active_;} 219 814 : unsigned int getFesOutputStride() const {return fes_output_stride_;} 220 : void setFesOutputStride(unsigned int stride) {fes_output_stride_=stride;} 221 : void writeFesOutputFiles() const; 222 : // 223 22829 : bool isFesProjOutputActive() const {return fesproj_output_active_;} 224 176 : unsigned int getFesProjOutputStride() const {return fesproj_output_stride_;} 225 : void setFesProjOutputStride(unsigned int stride) {fesproj_output_stride_=stride;} 226 : void writeFesProjOutputFiles() const; 227 : // 228 22908 : bool isTargetDistOutputActive() const {return targetdist_output_active_;} 229 22367 : unsigned int getTargetDistOutputStride() const {return targetdist_output_stride_;} 230 : void setTargetDistOutputStride(unsigned int stride) {targetdist_output_stride_=stride;} 231 : void writeTargetDistOutputFiles() const; 232 : // 233 22829 : bool isTargetDistProjOutputActive() const {return targetdist_proj_output_active_;} 234 33 : unsigned int getTargetDistProjOutputStride() const {return targetdist_proj_output_stride_;} 235 : void setTargetDistProjOutputStride(unsigned int stride) {targetdist_proj_output_stride_=stride;} 236 : void writeTargetDistProjOutputFiles() const; 237 : // 238 : }; 239 : 240 : inline 241 22705 : double Optimizer::StepSize(const unsigned int coeffs_id) const {return stepsizes_[coeffs_id];} 242 : 243 : inline 244 68214 : CoeffsVector& Optimizer::Coeffs(const unsigned int coeffs_id) const {return *coeffs_pntrs_[coeffs_id];} 245 : 246 : inline 247 21 : CoeffsVector& Optimizer::AuxCoeffs(const unsigned int coeffs_id) const {return *aux_coeffs_pntrs_[coeffs_id];} 248 : 249 : inline 250 22785 : CoeffsVector& Optimizer::Gradient(const unsigned int coeffs_id) const {return *gradient_pntrs_[coeffs_id];} 251 : 252 : inline 253 22735 : CoeffsMatrix& Optimizer::Hessian(const unsigned int coeffs_id) const { 254 22735 : plumed_massert(use_hessian_,"You cannot use the Hessian without asking for before"); 255 22735 : return *hessian_pntrs_[coeffs_id]; 256 : } 257 : 258 : inline 259 : CoeffsVector& Optimizer::CoeffsMask(const unsigned int coeffs_id) const {return *coeffs_mask_pntrs_[coeffs_id];} 260 : 261 : inline 262 : std::vector<double> Optimizer::getStepSizes() const {return stepsizes_;} 263 : 264 : inline 265 : std::vector<double> Optimizer::getCurrentStepSizes() const {return current_stepsizes;} 266 : 267 : inline 268 : double Optimizer::getStepSize(const unsigned int coeffs_id) const {return stepsizes_[coeffs_id];} 269 : 270 : inline 271 11 : double Optimizer::getCurrentStepSize(const unsigned int coeffs_id) const {return current_stepsizes[coeffs_id];} 272 : 273 : inline 274 : void Optimizer::setStepSizes(const std::vector<double>& stepsizes_in) { 275 : plumed_assert(stepsizes_in.size()==ncoeffssets_); 276 : stepsizes_ = stepsizes_in; 277 : } 278 : 279 : inline 280 : void Optimizer::setStepSize(const double stepsize_in, const unsigned int coeffs_id) { 281 : stepsizes_[coeffs_id] = stepsize_in; 282 : } 283 : 284 : inline 285 : void Optimizer::setCurrentStepSize(const double current_stepsize_in, const unsigned int coeffs_id) { 286 10 : current_stepsizes[coeffs_id] = current_stepsize_in; 287 : } 288 : 289 : inline 290 78 : void Optimizer::setCurrentStepSizes(const std::vector<double>& current_stepsizes_in) { 291 78 : plumed_assert(current_stepsizes_in.size()==ncoeffssets_); 292 78 : current_stepsizes = current_stepsizes_in; 293 78 : } 294 : 295 : inline 296 48388 : unsigned int Optimizer::getIterationCounter() const {return iter_counter;} 297 : 298 : inline 299 22695 : double Optimizer::getIterationCounterDbl() const {return static_cast<double>(iter_counter);} 300 : 301 : inline 302 22750 : void Optimizer::increaseIterationCounter() {iter_counter++;} 303 : 304 : inline 305 13 : void Optimizer::setIterationCounter(const unsigned int iter_counter_in) {iter_counter = iter_counter_in;} 306 : 307 : 308 : template<class T> 309 623 : bool Optimizer::parseMultipleValues(const std::string& keyword, std::vector<T>& values) { 310 623 : plumed_assert(ncoeffssets_>0); 311 623 : plumed_assert(values.size()==0); 312 : bool identical_values=false; 313 : // 314 623 : parseVector(keyword,values); 315 623 : if(values.size()==1 && ncoeffssets_>1) { 316 9 : values.resize(ncoeffssets_,values[0]); 317 : identical_values=true; 318 : } 319 623 : if(values.size()>0 && values.size()!=ncoeffssets_) { 320 0 : std::string s1; Tools::convert(ncoeffssets_,s1); 321 0 : plumed_merror("Error in " + keyword + " keyword: either give 1 common value for all coefficient sets or " + s1 + " separate value for each set"); 322 : } 323 623 : return identical_values; 324 : } 325 : 326 : template<class T> 327 158 : bool Optimizer::parseMultipleValues(const std::string& keyword, std::vector<T>& values, const T& default_value) { 328 158 : bool identical_values = parseMultipleValues(keyword,values); 329 158 : if(values.size()==0) { 330 79 : values.resize(ncoeffssets_,default_value); 331 : identical_values=true; 332 : } 333 158 : return identical_values; 334 : } 335 : 336 : inline 337 158 : void Optimizer::parseFilenames(const std::string& keyword, std::vector<std::string>& fnames, const std::string& default_fname) { 338 158 : if(parseMultipleValues<std::string>(keyword,fnames,default_fname)) { 339 81 : addCoeffsSetIDsToFilenames(fnames,coeffssetid_prefix_); 340 : } 341 158 : } 342 : 343 : inline 344 387 : void Optimizer::parseFilenames(const std::string& keyword, std::vector<std::string>& fnames) { 345 387 : if(parseMultipleValues<std::string>(keyword,fnames)) { 346 4 : addCoeffsSetIDsToFilenames(fnames,coeffssetid_prefix_); 347 : } 348 387 : } 349 : 350 : 351 : } 352 : } 353 : 354 : #endif