Changeset baccf6
- Timestamp:
- Jul 8, 2013, 2:22:03 PM (11 years ago)
- Branches:
- Action_Thermostats, Add_AtomRandomPerturbation, Add_FitFragmentPartialChargesAction, Add_RotateAroundBondAction, Add_SelectAtomByNameAction, Added_ParseSaveFragmentResults, AddingActions_SaveParseParticleParameters, Adding_Graph_to_ChangeBondActions, Adding_MD_integration_tests, Adding_ParticleName_to_Atom, Adding_StructOpt_integration_tests, AtomFragments, Automaking_mpqc_open, AutomationFragmentation_failures, Candidate_v1.5.4, Candidate_v1.6.0, Candidate_v1.6.1, ChangeBugEmailaddress, ChangingTestPorts, ChemicalSpaceEvaluator, CombiningParticlePotentialParsing, Combining_Subpackages, Debian_Package_split, Debian_package_split_molecuildergui_only, Disabling_MemDebug, Docu_Python_wait, EmpiricalPotential_contain_HomologyGraph, EmpiricalPotential_contain_HomologyGraph_documentation, Enable_parallel_make_install, Enhance_userguide, Enhanced_StructuralOptimization, Enhanced_StructuralOptimization_continued, Example_ManyWaysToTranslateAtom, Exclude_Hydrogens_annealWithBondGraph, FitPartialCharges_GlobalError, Fix_BoundInBox_CenterInBox_MoleculeActions, Fix_ChargeSampling_PBC, Fix_ChronosMutex, Fix_FitPartialCharges, Fix_FitPotential_needs_atomicnumbers, Fix_ForceAnnealing, Fix_IndependentFragmentGrids, Fix_ParseParticles, Fix_ParseParticles_split_forward_backward_Actions, Fix_PopActions, Fix_QtFragmentList_sorted_selection, Fix_Restrictedkeyset_FragmentMolecule, Fix_StatusMsg, Fix_StepWorldTime_single_argument, Fix_Verbose_Codepatterns, Fix_fitting_potentials, Fixes, ForceAnnealing_goodresults, ForceAnnealing_oldresults, ForceAnnealing_tocheck, ForceAnnealing_with_BondGraph, ForceAnnealing_with_BondGraph_continued, ForceAnnealing_with_BondGraph_continued_betteresults, ForceAnnealing_with_BondGraph_contraction-expansion, FragmentAction_writes_AtomFragments, FragmentMolecule_checks_bonddegrees, GeometryObjects, Gui_Fixes, Gui_displays_atomic_force_velocity, ImplicitCharges, IndependentFragmentGrids, IndependentFragmentGrids_IndividualZeroInstances, IndependentFragmentGrids_IntegrationTest, IndependentFragmentGrids_Sole_NN_Calculation, JobMarket_RobustOnKillsSegFaults, JobMarket_StableWorkerPool, JobMarket_unresolvable_hostname_fix, MoreRobust_FragmentAutomation, ODR_violation_mpqc_open, PartialCharges_OrthogonalSummation, PdbParser_setsAtomName, PythonUI_with_named_parameters, QtGui_reactivate_TimeChanged_changes, Recreated_GuiChecks, Rewrite_FitPartialCharges, RotateToPrincipalAxisSystem_UndoRedo, SaturateAtoms_findBestMatching, SaturateAtoms_singleDegree, StoppableMakroAction, Subpackage_CodePatterns, Subpackage_JobMarket, Subpackage_LinearAlgebra, Subpackage_levmar, Subpackage_mpqc_open, Subpackage_vmg, Switchable_LogView, ThirdParty_MPQC_rebuilt_buildsystem, TrajectoryDependenant_MaxOrder, TremoloParser_IncreasedPrecision, TremoloParser_MultipleTimesteps, TremoloParser_setsAtomName, Ubuntu_1604_changes, stable
- Children:
- 49dcf7
- Parents:
- 7c1091
- git-author:
- Frederik Heber <heber@…> (05/10/13 07:11:56)
- git-committer:
- Frederik Heber <heber@…> (07/08/13 14:22:03)
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Actions/FragmentationAction/FitPotentialAction.cpp
r7c1091 rbaccf6 60 60 #include "FunctionApproximation/TrainingData.hpp" 61 61 #include "FunctionApproximation/writeDistanceEnergyTable.hpp" 62 #include "Potentials/CompoundPotential.hpp" 63 #include "Potentials/PotentialDeserializer.hpp" 62 64 #include "Potentials/PotentialFactory.hpp" 65 #include "Potentials/PotentialRegistry.hpp" 66 #include "Potentials/PotentialSerializer.hpp" 63 67 #include "Potentials/SerializablePotential.hpp" 64 68 … … 109 113 110 114 Action::state_ptr FragmentationFitPotentialAction::performCall() { 111 // charges specify the potential type112 SerializablePotential::ParticleTypes_t chargenumbers;113 {114 const std::vector<const element *> &charges = params.charges.get();115 std::transform(charges.begin(), charges.end(), std::back_inserter(chargenumbers),116 boost::bind(&element::getAtomicNumber, _1));117 }118 115 // fragment specifies the homology fragment to use 119 116 SerializablePotential::ParticleTypes_t fragmentnumbers; … … 122 119 std::transform(fragment.begin(), fragment.end(), std::back_inserter(fragmentnumbers), 123 120 boost::bind(&element::getAtomicNumber, _1)); 121 } 122 123 // either charges and a potential is specified or a file 124 if (boost::filesystem::exists(params.potential_file.get())) { 125 std::ifstream returnstream(params.potential_file.get().string().c_str()); 126 if (returnstream.good()) { 127 PotentialDeserializer deserialize(returnstream); 128 deserialize(); 129 } else { 130 ELOG(0, "Failed to parse from " << params.potential_file.get().string() << "."); 131 return Action::failure; 132 } 133 returnstream.close(); 134 135 LOG(0, "STATUS: I'm training now a set of potentials parsed from " 136 << params.potential_file.get().string() << " on a fragment " 137 << fragmentnumbers << " on data from " << params.homology_file.get() << "."); 138 139 } else { 140 if (params.charges.get().empty()) { 141 ELOG(1, "Neither charges nor potential file given!"); 142 return Action::failure; 143 } else { 144 // charges specify the potential type 145 SerializablePotential::ParticleTypes_t chargenumbers; 146 { 147 const std::vector<const element *> &charges = params.charges.get(); 148 std::transform(charges.begin(), charges.end(), std::back_inserter(chargenumbers), 149 boost::bind(&element::getAtomicNumber, _1)); 150 } 151 152 LOG(0, "STATUS: I'm training now a " << params.potentialtype.get() 153 << " potential on charges " << chargenumbers << " on data from " 154 << params.homology_file.get() << "."); 155 156 // register desired potential and an additional constant one 157 EmpiricalPotential *potential = 158 PotentialFactory::getInstance().createInstance( 159 params.potentialtype.get(), 160 chargenumbers); 161 PotentialRegistry::getInstance().registerInstance(potential); 162 EmpiricalPotential *constant = 163 PotentialFactory::getInstance().createInstance( 164 std::string("constant"), 165 SerializablePotential::ParticleTypes_t()); 166 PotentialRegistry::getInstance().registerInstance(constant); 167 } 124 168 } 125 169 … … 149 193 } 150 194 151 LOG(0, "STATUS: I'm training now a " << params.potentialtype.get() << " potential on charges " 152 << chargenumbers << " on data from " << params.homology_file.get() << "."); 195 // then we ought to pick the right HomologyGraph ... 196 const HomologyGraph graph = getFirstGraphwithSpecifiedElements(homologies,fragmentnumbers); 197 if (graph != HomologyGraph()) { 198 LOG(1, "First representative graph containing fragment " 199 << fragmentnumbers << " is " << graph << "."); 200 } else { 201 ELOG(1, "Specific fragment " << fragmentnumbers << " not found in homologies!"); 202 return Action::failure; 203 } 204 205 // fit potential 206 FunctionModel *model = new CompoundPotential(graph); 207 ASSERT( model != NULL, 208 "FragmentationFitPotentialAction::performCall() - model is NULL."); 153 209 154 210 /******************** TRAINING ********************/ 155 211 // fit potential 156 FunctionModel *model =157 PotentialFactory::getInstance().createInstance(158 params.potentialtype.get(),159 chargenumbers);160 ASSERT( model != NULL,161 "main() - model returned from PotentialFactory is NULL.");162 212 FunctionModel::parameters_t bestparams(model->getParameterDimension(), 0.); 163 213 { 164 // then we ought to pick the right HomologyGraph ... 165 const HomologyGraph graph = getFirstGraphwithSpecifiedElements(homologies,fragmentnumbers); 166 if (graph != HomologyGraph()) { 167 LOG(1, "First representative graph containing fragment " 168 << fragmentnumbers << " is " << graph << "."); 169 170 // Afterwards we go through all of this type and gather the distance and the energy value 171 TrainingData data(model->getFragmentSpecificExtractor()); 172 data(homologies.getHomologousGraphs(graph)); 173 174 // print distances and energies if desired for debugging 175 if (!data.getTrainingInputs().empty()) { 176 // print which distance is which 177 size_t counter=1; 178 if (DoLog(3)) { 179 const FunctionModel::arguments_t &inputs = data.getTrainingInputs()[0]; 180 for (FunctionModel::arguments_t::const_iterator iter = inputs.begin(); 181 iter != inputs.end(); ++iter) { 182 const argument_t &arg = *iter; 183 LOG(3, "DEBUG: distance " << counter++ << " is between (#" 184 << arg.indices.first << "c" << arg.types.first << "," 185 << arg.indices.second << "c" << arg.types.second << ")."); 186 } 187 } 188 189 // print table 190 LOG(3, "DEBUG: I gathered the following training data:\n" << 191 _detail::writeDistanceEnergyTable(data.getDistanceEnergyTable())); 192 } 193 194 // now perform the function approximation by optimizing the model function 195 FunctionApproximation approximator(data, *model); 196 if (model->isBoxConstraint() && approximator.checkParameterDerivatives()) { 197 double l2error = std::numeric_limits<double>::infinity(); 198 // seed with current time 199 srand((unsigned)time(0)); 200 for (unsigned int runs=0; runs < params.best_of_howmany.get(); ++runs) { 201 // generate new random initial parameter values 202 model->setParametersToRandomInitialValues(data); 203 LOG(1, "INFO: Initial parameters of run " << runs << " are " 204 << model->getParameters() << "."); 205 approximator(FunctionApproximation::ParameterDerivative); 206 LOG(1, "INFO: Final parameters of run " << runs << " are " 207 << model->getParameters() << "."); 208 const double new_l2error = data.getL2Error(*model); 209 if (new_l2error < l2error) { 210 // store currently best parameters 211 l2error = new_l2error; 212 bestparams = model->getParameters(); 213 LOG(1, "STATUS: New fit from run " << runs 214 << " has better error of " << l2error << "."); 215 } 216 } 217 // reset parameters from best fit 218 model->setParameters(bestparams); 219 LOG(1, "INFO: Best parameters with L2 error of " 220 << l2error << " are " << model->getParameters() << "."); 221 } else { 222 ELOG(0, "We require parameter derivatives for a box constraint minimization."); 223 return Action::failure; 224 } 225 226 // create a map of each fragment with error. 227 typedef std::multimap< double, size_t > WorseFragmentMap_t; 228 WorseFragmentMap_t WorseFragmentMap; 229 HomologyContainer::range_t fragmentrange = homologies.getHomologousGraphs(graph); 230 // fragments make it into the container in reversed order, hence count from top down 231 size_t index= std::distance(fragmentrange.first, fragmentrange.second)-1; 232 for (HomologyContainer::const_iterator iter = fragmentrange.first; 233 iter != fragmentrange.second; 234 ++iter) { 235 const Fragment& fragment = iter->second.first; 236 const double &energy = iter->second.second; 237 238 // create arguments from the fragment 239 FunctionModel::extractor_t extractor = model->getFragmentSpecificExtractor(); 240 FunctionModel::arguments_t args = extractor(fragment, 1); 241 242 // calculate value from potential 243 const double fitvalue = (*model)(args)[0]; 244 245 // insert difference into map 246 const double error = fabs(energy - fitvalue); 247 WorseFragmentMap.insert( std::make_pair( error, index-- ) ); 248 249 { 250 // give only the distances in the debugging text 251 std::stringstream streamargs; 252 BOOST_FOREACH (argument_t arg, args) { 253 streamargs << " " << arg.distance*AtomicLengthToAngstroem; 254 } 255 LOG(2, "DEBUG: frag.#" << index+1 << "'s error is |" << energy << " - " << fitvalue 256 << "| = " << error << " for args " << streamargs.str() << "."); 214 // Afterwards we go through all of this type and gather the distance and the energy value 215 TrainingData data(model->getFragmentSpecificExtractor()); 216 data(homologies.getHomologousGraphs(graph)); 217 218 // print distances and energies if desired for debugging 219 if (!data.getTrainingInputs().empty()) { 220 // print which distance is which 221 size_t counter=1; 222 if (DoLog(3)) { 223 const FunctionModel::arguments_t &inputs = data.getTrainingInputs()[0]; 224 for (FunctionModel::arguments_t::const_iterator iter = inputs.begin(); 225 iter != inputs.end(); ++iter) { 226 const argument_t &arg = *iter; 227 LOG(3, "DEBUG: distance " << counter++ << " is between (#" 228 << arg.indices.first << "c" << arg.types.first << "," 229 << arg.indices.second << "c" << arg.types.second << ")."); 257 230 } 258 231 } 259 LOG(0, "RESULT: WorstFragmentMap " << WorseFragmentMap << "."); 260 261 SerializablePotential *potential = dynamic_cast<SerializablePotential *>(model); 262 if (potential != NULL) { 263 LOG(1, "STATUS: Resulting parameters are " << std::endl << *potential); 264 } else { 265 LOG(1, "INFO: FunctionModel is no serializable potential."); 232 233 // print table 234 LOG(3, "DEBUG: I gathered the following training data:\n" << 235 _detail::writeDistanceEnergyTable(data.getDistanceEnergyTable())); 236 } 237 238 // now perform the function approximation by optimizing the model function 239 FunctionApproximation approximator(data, *model); 240 if (model->isBoxConstraint() && approximator.checkParameterDerivatives()) { 241 double l2error = std::numeric_limits<double>::infinity(); 242 // seed with current time 243 srand((unsigned)time(0)); 244 for (unsigned int runs=0; runs < params.best_of_howmany.get(); ++runs) { 245 // generate new random initial parameter values 246 model->setParametersToRandomInitialValues(data); 247 LOG(1, "INFO: Initial parameters of run " << runs << " are " 248 << model->getParameters() << "."); 249 approximator(FunctionApproximation::ParameterDerivative); 250 LOG(1, "INFO: Final parameters of run " << runs << " are " 251 << model->getParameters() << "."); 252 const double new_l2error = data.getL2Error(*model); 253 if (new_l2error < l2error) { 254 // store currently best parameters 255 l2error = new_l2error; 256 bestparams = model->getParameters(); 257 LOG(1, "STATUS: New fit from run " << runs 258 << " has better error of " << l2error << "."); 259 } 266 260 } 267 } 261 // reset parameters from best fit 262 model->setParameters(bestparams); 263 LOG(1, "INFO: Best parameters with L2 error of " 264 << l2error << " are " << model->getParameters() << "."); 265 } else { 266 ELOG(0, "We require parameter derivatives for a box constraint minimization."); 267 return Action::failure; 268 } 269 270 // create a map of each fragment with error. 271 typedef std::multimap< double, size_t > WorseFragmentMap_t; 272 WorseFragmentMap_t WorseFragmentMap; 273 HomologyContainer::range_t fragmentrange = homologies.getHomologousGraphs(graph); 274 // fragments make it into the container in reversed order, hence count from top down 275 size_t index= std::distance(fragmentrange.first, fragmentrange.second)-1; 276 for (HomologyContainer::const_iterator iter = fragmentrange.first; 277 iter != fragmentrange.second; 278 ++iter) { 279 const Fragment& fragment = iter->second.first; 280 const double &energy = iter->second.second; 281 282 // create arguments from the fragment 283 FunctionModel::extractor_t extractor = model->getFragmentSpecificExtractor(); 284 FunctionModel::arguments_t args = extractor(fragment, 1); 285 286 // calculate value from potential 287 const double fitvalue = (*model)(args)[0]; 288 289 // insert difference into map 290 const double error = fabs(energy - fitvalue); 291 WorseFragmentMap.insert( std::make_pair( error, index-- ) ); 292 293 { 294 // give only the distances in the debugging text 295 std::stringstream streamargs; 296 BOOST_FOREACH (argument_t arg, args) { 297 streamargs << " " << arg.distance*AtomicLengthToAngstroem; 298 } 299 LOG(2, "DEBUG: frag.#" << index+1 << "'s error is |" << energy << " - " << fitvalue 300 << "| = " << error << " for args " << streamargs.str() << "."); 301 } 302 } 303 LOG(0, "RESULT: WorstFragmentMap " << WorseFragmentMap << "."); 304 305 // print fitted potentials 306 std::stringstream potentials; 307 PotentialSerializer serialize(potentials); 308 serialize(); 309 LOG(1, "STATUS: Resulting parameters are " << std::endl << potentials.str()); 268 310 } 269 311 delete model; -
src/Actions/FragmentationAction/FitPotentialAction.def
r7c1091 rbaccf6 11 11 #include <vector> 12 12 13 #include "Parameters/Validators/DummyValidator.hpp" 13 14 #include "Parameters/Validators/RangeValidator.hpp" 14 15 #include "Parameters/Validators/STLVectorValidator.hpp" … … 20 21 // ValueStorage by the token "Z" -> first column: int, Z, "Z" 21 22 // "undefine" if no parameters are required, use (NOPARAM_DEFAULT) for each (undefined) default value 22 #define paramtypes (boost::filesystem::path)(std::string)( std::vector<const element *>)(std::vector<const element *>)(unsigned int)23 #define paramtokens ("homology-file")("fit-potential")("potential- charges")("fragment-charges")("take-best-of")24 #define paramdescriptions ("homology file to parse")("potential type to fit")(" charges specifying the potential")("charges specifying the fragment")("take the best among this many approximations")25 #define paramdefaults (NOPARAM_DEFAULT)(NOPARAM_DEFAULT)(NOPARAM_DEFAULT)(NOPARAM_DEFAULT)( PARAM_DEFAULT(3))26 #define paramreferences (homology_file)(potentialtype)( charges)(fragment)(best_of_howmany)23 #define paramtypes (boost::filesystem::path)(std::string)(boost::filesystem::path)(std::vector<const element *>)(std::vector<const element *>)(unsigned int) 24 #define paramtokens ("homology-file")("fit-potential")("potential-file")("potential-charges")("fragment-charges")("take-best-of") 25 #define paramdescriptions ("homology file to parse")("potential type to fit")("potential file specifying multiple potentials to fit")("charges specifying the potential")("charges specifying the fragment")("take the best among this many approximations") 26 #define paramdefaults (NOPARAM_DEFAULT)(NOPARAM_DEFAULT)(NOPARAM_DEFAULT)(NOPARAM_DEFAULT)(NOPARAM_DEFAULT)(PARAM_DEFAULT(3)) 27 #define paramreferences (homology_file)(potentialtype)(potential_file)(charges)(fragment)(best_of_howmany) 27 28 #define paramvalids \ 28 29 (FilePresentValidator()) \ 29 30 (PotentialTypeValidator()) \ 30 (STLVectorValidator< std::vector<const element *> >(1,99, ElementValidator())) \ 31 (DummyValidator<boost::filesystem::path>()) \ 32 (STLVectorValidator< std::vector<const element *> >(0,99, ElementValidator())) \ 31 33 (STLVectorValidator< std::vector<const element *> >(1,99, ElementValidator())) \ 32 34 (RangeValidator< unsigned int>(1,99)) -
tests/Python/AllActions/options.dat
r7c1091 rbaccf6 134 134 position "9.78 2.64 2.64" 135 135 potential-charges "1 1" 136 potential-file "test.potentials" 136 137 radius "20." 137 138 random-atom-displacement "0." -
tests/regression/Fragmentation/FitPotential/testsuite-fragmentation-fit-potential.at
r7c1091 rbaccf6 21 21 AT_SETUP([Fragmentation - Fit morse potential to water]) 22 22 AT_KEYWORDS([fragmentation fit-potential morse]) 23 AT_XFAIL_IF([/bin/true])24 23 AT_SKIP_IF([../../molecuilder --help --actionname fit-potential; if test $? -eq 5; then /bin/true; else /bin/false; fi]) 25 24 … … 31 30 AT_CHECK([grep "Best parameters with L2 error" stdout | awk '{if ($8 > 1e-6) exit 1}'], 0, [ignore], [ignore]) 32 31 # check parameters to printed precision 33 AT_CHECK([grep "morse:.*particle_type1=8,.*particle_type2=1,.*spring_constant=1.2 652,.*equilibrium_distance=1.78095,.*dissociation_energy=0.401285;" stdout], 0, [ignore], [ignore])32 AT_CHECK([grep "morse:.*particle_type1=8,.*particle_type2=1,.*spring_constant=1.27.*,.*equilibrium_distance=1.78.*,.*dissociation_energy=0.19.*;" stdout], 0, [ignore], [ignore]) 34 33 35 34 AT_CLEANUP … … 37 36 AT_SETUP([Fragmentation - Fit harmonic_angle potential to water]) 38 37 AT_KEYWORDS([fragmentation fit-potential harmonic_angle]) 39 AT_XFAIL_IF([/bin/true])40 38 AT_SKIP_IF([../../molecuilder --help --actionname fit-potential; if test $? -eq 5; then /bin/true; else /bin/false; fi]) 41 39 … … 47 45 AT_CHECK([grep "||e||_2:" stdout | awk '{if ($7 > 1e-6) exit 1}'], 0, [ignore], [ignore]) 48 46 # check parameters to printed precision 49 AT_CHECK([grep "harmonic_angle:.*particle_type1=1,.*particle_type2=8,.*particle_type3=1,.*spring_constant=0.10 0497,.*equilibrium_distance=-0.274675;" stdout], 0, [ignore], [ignore])47 AT_CHECK([grep "harmonic_angle:.*particle_type1=1,.*particle_type2=8,.*particle_type3=1,.*spring_constant=0.10.*,.*equilibrium_distance=-0.27.*;" stdout], 0, [ignore], [ignore]) 50 48 51 49 AT_CLEANUP
Note:
See TracChangeset
for help on using the changeset viewer.