source: src/LevMartester.cpp@ f68c68

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 Candidate_v1.7.0 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
Last change on this file since f68c68 was f68c68, checked in by Frederik Heber <heber@…>, 13 years ago

Tersoff now also uses TrainingData class.

  • shifted calculation of errors into two new TrainingData functions: getL2Error() and getLMaxError().
  • Property mode set to 100644
File size: 24.6 KB
RevLine 
[f06d52]1/*
2 * Project: MoleCuilder
3 * Description: creates and alters molecular systems
4 * Copyright (C) 2012 University of Bonn. All rights reserved.
5 * Please see the COPYING file or "Copyright notice" in builder.cpp for details.
6 *
7 *
8 * This file is part of MoleCuilder.
9 *
10 * MoleCuilder is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation, either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * MoleCuilder is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with MoleCuilder. If not, see <http://www.gnu.org/licenses/>.
22 */
23
24/*
25 * LevMartester.cpp
26 *
27 * Created on: Sep 27, 2012
28 * Author: heber
29 */
30
31
32// include config.h
33#ifdef HAVE_CONFIG_H
34#include <config.h>
35#endif
36
[69b30a]37#include <boost/archive/text_iarchive.hpp>
38
[f06d52]39#include "CodePatterns/MemDebug.hpp"
40
[9340ee]41#include <boost/assign.hpp>
[4ec18b]42#include <boost/bind.hpp>
[f06d52]43#include <boost/filesystem.hpp>
[4ec18b]44#include <boost/function.hpp>
[f06d52]45#include <boost/program_options.hpp>
46
[17b3598]47#include <cstdlib>
48#include <ctime>
[f06d52]49#include <fstream>
50#include <iostream>
51#include <iterator>
[eb1efe]52#include <list>
[f06d52]53#include <vector>
54
55#include <levmar.h>
56
57#include "CodePatterns/Assert.hpp"
58#include "CodePatterns/Log.hpp"
59
60#include "LinearAlgebra/Vector.hpp"
61
62#include "Fragmentation/Homology/HomologyContainer.hpp"
63#include "Fragmentation/SetValues/Fragment.hpp"
[8aa597]64#include "FunctionApproximation/Extractors.hpp"
[c62f96]65#include "FunctionApproximation/FunctionApproximation.hpp"
66#include "FunctionApproximation/FunctionModel.hpp"
[f48ad3]67#include "Helpers/defs.hpp"
[155cc2]68#include "Potentials/Specifics/PairPotential_Morse.hpp"
[9340ee]69#include "Potentials/Specifics/PairPotential_Angle.hpp"
[40fff1]70#include "Potentials/Specifics/SaturationPotential.hpp"
[f06d52]71
72namespace po = boost::program_options;
73
[9340ee]74using namespace boost::assign;
75
76HomologyGraph getFirstGraphWithThreeCarbons(const HomologyContainer &homologies)
77{
78 FragmentNode SaturatedCarbon(6,4); // carbon has atomic number 6 and should have 4 bonds for C3H8
79 FragmentNode DanglingCarbon(6,3); // carbon has atomic number 6 and should have 3 pure bonds for C3H8
80 for (HomologyContainer::container_t::const_iterator iter =
81 homologies.begin(); iter != homologies.end(); ++iter) {
82 if ((iter->first.hasNode(SaturatedCarbon,2)) && (iter->first.hasNode(DanglingCarbon,1)))
83 return iter->first;
84 }
85 return HomologyGraph();
86}
87
[f06d52]88HomologyGraph getFirstGraphWithTwoCarbons(const HomologyContainer &homologies)
89{
[8ea8c8]90 FragmentNode SaturatedCarbon(6,3); // carbon has atomic number 6 and should have 4 bonds for C2H6
[f06d52]91 for (HomologyContainer::container_t::const_iterator iter =
92 homologies.begin(); iter != homologies.end(); ++iter) {
93 if (iter->first.hasNode(SaturatedCarbon,2))
94 return iter->first;
95 }
96 return HomologyGraph();
97}
98
[eb1efe]99HomologyGraph getFirstGraphWithOneCarbon(const HomologyContainer &homologies)
100{
[8ea8c8]101 FragmentNode SaturatedCarbon(6,2); // carbon has atomic number 6 and has 3 bonds (to other Hs)
[eb1efe]102 for (HomologyContainer::container_t::const_iterator iter =
103 homologies.begin(); iter != homologies.end(); ++iter) {
104 if (iter->first.hasNode(SaturatedCarbon,1))
105 return iter->first;
106 }
107 return HomologyGraph();
108}
109
110
111/** This function returns the elements of the sum over index "k" for an
112 * argument containing indices "i" and "j"
113 * @param inputs vector of all configuration (containing each a vector of all arguments)
114 * @param arg argument containing indices "i" and "j"
115 * @param cutoff cutoff criterion for sum over k
116 * @return vector of argument pairs (a vector) of ik and jk for at least all k
117 * within distance of \a cutoff to i
118 */
119std::vector<FunctionModel::arguments_t>
120getTripleFromArgument(const FunctionApproximation::inputs_t &inputs, const argument_t &arg, const double cutoff)
121{
122 typedef std::list<argument_t> arg_list_t;
123 typedef std::map<size_t, arg_list_t > k_args_map_t;
124 k_args_map_t tempresult;
125 ASSERT( inputs.size() > arg.globalid,
126 "getTripleFromArgument() - globalid "+toString(arg.globalid)
127 +" is greater than all inputs "+toString(inputs.size())+".");
128 const FunctionModel::arguments_t &listofargs = inputs[arg.globalid];
129 for (FunctionModel::arguments_t::const_iterator argiter = listofargs.begin();
130 argiter != listofargs.end();
131 ++argiter) {
132 // first index must be either i or j but second index not
133 if (((argiter->indices.first == arg.indices.first)
134 || (argiter->indices.first == arg.indices.second))
135 && ((argiter->indices.second != arg.indices.first)
136 && (argiter->indices.second != arg.indices.second))) {
137 // we need arguments ik and jk
138 std::pair< k_args_map_t::iterator, bool> inserter =
139 tempresult.insert( std::make_pair( argiter->indices.second, arg_list_t(1,*argiter)));
140 if (!inserter.second) {
141 // is present one ik or jk, if ik insert jk at back
142 if (inserter.first->second.begin()->indices.first == arg.indices.first)
143 inserter.first->second.push_back(*argiter);
144 else // if jk, insert ik at front
145 inserter.first->second.push_front(*argiter);
146 }
147 }
148// // or second index must be either i or j but first index not
149// else if (((argiter->indices.first != arg.indices.first)
150// && (argiter->indices.first != arg.indices.second))
151// && ((argiter->indices.second == arg.indices.first)
152// || (argiter->indices.second == arg.indices.second))) {
153// // we need arguments ki and kj
154// std::pair< k_args_map_t::iterator, bool> inserter =
155// tempresult.insert( std::make_pair( argiter->indices.first, arg_list_t(1,*argiter)));
156// if (!inserter.second) {
157// // is present one ki or kj, if ki insert kj at back
158// if (inserter.first->second.begin()->indices.second == arg.indices.first)
159// inserter.first->second.push_back(*argiter);
160// else // if kj, insert ki at front
161// inserter.first->second.push_front(*argiter);
162// }
163// }
164 }
165 // check that i,j are NOT contained
166 ASSERT( tempresult.count(arg.indices.first) == 0,
167 "getTripleFromArgument() - first index of argument present in k_args_map?");
168 ASSERT( tempresult.count(arg.indices.second) == 0,
169 "getTripleFromArgument() - first index of argument present in k_args_map?");
170
171 // convert
172 std::vector<FunctionModel::arguments_t> result;
173 for (k_args_map_t::const_iterator iter = tempresult.begin();
174 iter != tempresult.end();
175 ++iter) {
176 ASSERT( iter->second.size() == 2,
177 "getTripleFromArgument() - for index "+toString(iter->first)+" we did not find both ik and jk.");
178 result.push_back( FunctionModel::arguments_t(iter->second.begin(), iter->second.end()) );
179 }
180 return result;
181}
182
[9340ee]183double
184function_angle(
185 const double &r_ij,
186 const double &r_ik,
187 const double &r_jk
188 )
189{
190// Info info(__func__);
191 const double angle = pow(r_ij,2.) + pow(r_ik,2.) - pow(r_jk,2.);
192 const double divisor = 2.* r_ij * r_ik;
193
194// LOG(2, "DEBUG: cos(theta)= " << angle/divisor);
195 if (divisor == 0.)
196 return 0.;
197 else
198 return angle/divisor;
199}
[f06d52]200
[4ec18b]201/** This class encapsulates the training data for a given potential function
202 * to learn.
203 *
204 * The data is added piece-wise by calling the operator() with a specific
205 * Fragment.
206 */
207class TrainingData
208{
209public:
210 //!> typedef for a range within the HomologyContainer at which fragments to look at
211 typedef std::pair<
212 HomologyContainer::const_iterator,
213 HomologyContainer::const_iterator> range_t;
214 //!> Training tuple input vector pair
215 typedef FunctionApproximation::inputs_t InputVector_t;
216 //!> Training tuple output vector pair
217 typedef FunctionApproximation::outputs_t OutputVector_t;
218 //!> Typedef for a function containing how to extract required information from a Fragment.
219 typedef boost::function< FunctionModel::arguments_t (const Fragment &, const size_t)> extractor_t;
220
221public:
222 /** Constructor for class TrainingData.
223 *
224 */
225 explicit TrainingData(const extractor_t &_extractor) :
226 extractor(extractor)
227 {}
228 /** Destructor for class TrainingData.
229 *
230 */
231 ~TrainingData()
232 {}
233
234 /** We go through the given \a range of homologous fragments and call
235 * TrainingData::extractor on them in order to gather the distance and
236 * the energy value, stored internally.
237 *
238 * \param range given range within a HomologyContainer of homologous fragments
239 */
240 void operator()(const range_t &range) {
[f68c68]241 double EnergySum = 0.; //std::numeric_limits<double>::max();
242 size_t counter = 0.;
243 for (HomologyContainer::const_iterator iter = range.first; iter != range.second; ++iter) {
244 const double &energy = iter->second.second;
245// if (energy <= EnergySum)
246// EnergySum = energy;
247 EnergySum += energy;
248 ++counter;
249 }
250 EnergySum *= 1./(double)counter;
[4ec18b]251 for (HomologyContainer::const_iterator iter = range.first; iter != range.second; ++iter) {
252 // get distance out of Fragment
253 const Fragment &fragment = iter->second.first;
254 FunctionModel::arguments_t args = extractor(
255 fragment,
256 DistanceVector.size()
257 );
258 DistanceVector.push_back( args );
259 const double &energy = iter->second.second;
[f68c68]260 EnergyVector.push_back( FunctionModel::results_t(1, energy-EnergySum) );
[4ec18b]261 }
262 }
263
264 /** Getter for const access to internal training data inputs.
265 *
266 * \return const ref to training tuple of input vector
267 */
268 const InputVector_t& getTrainingInputs() const {
269 return DistanceVector;
270 }
271
272 /** Getter for const access to internal training data outputs.
273 *
274 * \return const ref to training tuple of output vector
275 */
276 const OutputVector_t& getTrainingOutputs() const {
277 return EnergyVector;
278 }
279
[f68c68]280 /** Calculate the L2 error of a given \a model against the stored training data.
281 *
282 * \param model model whose L2 error to calculate
283 * \return sum of squared differences at training tuples
284 */
285 const double getL2Error(const FunctionModel &model) const
286 {
287 double L2sum = 0.;
288
289 FunctionApproximation::inputs_t::const_iterator initer = DistanceVector.begin();
290 FunctionApproximation::outputs_t::const_iterator outiter = EnergyVector.begin();
291 for (; initer != DistanceVector.end(); ++initer, ++outiter) {
292 const FunctionModel::results_t result = model((*initer));
293 const double temp = fabs((*outiter)[0] - result[0]);
294 L2sum += temp*temp;
295 }
296 return L2sum;
297 }
298
299 /** Calculate the Lmax error of a given \a model against the stored training data.
300 *
301 * \param model model whose Lmax error to calculate
302 * \return maximum difference over all training tuples
303 */
304 const double getLMaxError(const FunctionModel &model) const
305 {
306 double Lmax = 0.;
307 size_t maxindex = -1;
308 FunctionApproximation::inputs_t::const_iterator initer = DistanceVector.begin();
309 FunctionApproximation::outputs_t::const_iterator outiter = EnergyVector.begin();
310 for (; initer != DistanceVector.end(); ++initer, ++outiter) {
311 const FunctionModel::results_t result = model((*initer));
312 const double temp = fabs((*outiter)[0] - result[0]);
313 if (temp > Lmax) {
314 Lmax = temp;
315 maxindex = std::distance(
316 const_cast<const FunctionApproximation::inputs_t &>(DistanceVector).begin(),
317 initer
318 );
319 }
320 }
321 return Lmax;
322 }
323
[4ec18b]324private:
325 // prohibit use of default constructor, as we always require extraction functor.
326 TrainingData();
327
328private:
329 //!> private training data vector
330 InputVector_t DistanceVector;
331 OutputVector_t EnergyVector;
332 //!> function to be used for training input data extraction from a fragment
333 const extractor_t extractor;
334};
335
336// print training data for debugging
337std::ostream &operator<<(std::ostream &out, const TrainingData &data)
338{
339 const TrainingData::InputVector_t &DistanceVector = data.getTrainingInputs();
340 const TrainingData::OutputVector_t &EnergyVector = data.getTrainingOutputs();
341 out << "(" << DistanceVector.size()
342 << "," << EnergyVector.size() << ") data pairs: ";
343 FunctionApproximation::inputs_t::const_iterator initer = DistanceVector.begin();
344 FunctionApproximation::outputs_t::const_iterator outiter = EnergyVector.begin();
345 for (; initer != DistanceVector.end(); ++initer, ++outiter) {
346 for (size_t index = 0; index < (*initer).size(); ++index)
347 out << "(" << (*initer)[index].indices.first << "," << (*initer)[index].indices.second
348 << ") " << (*initer)[index].distance;
349 out << " with energy " << *outiter;
350 }
351 return out;
352}
353
[f06d52]354int main(int argc, char **argv)
355{
356 std::cout << "Hello to the World from LevMar!" << std::endl;
357
358 // load homology file
359 po::options_description desc("Allowed options");
360 desc.add_options()
361 ("help", "produce help message")
362 ("homology-file", po::value< boost::filesystem::path >(), "homology file to parse")
363 ;
364
365 po::variables_map vm;
366 po::store(po::parse_command_line(argc, argv, desc), vm);
367 po::notify(vm);
368
369 if (vm.count("help")) {
370 std::cout << desc << "\n";
371 return 1;
372 }
373
374 boost::filesystem::path homology_file;
375 if (vm.count("homology-file")) {
376 homology_file = vm["homology-file"].as<boost::filesystem::path>();
377 LOG(1, "INFO: Parsing " << homology_file.string() << ".");
378 } else {
379 LOG(0, "homology-file level was not set.");
380 }
381 HomologyContainer homologies;
382 if (boost::filesystem::exists(homology_file)) {
383 std::ifstream returnstream(homology_file.string().c_str());
384 if (returnstream.good()) {
385 boost::archive::text_iarchive ia(returnstream);
386 ia >> homologies;
387 } else {
388 ELOG(2, "Failed to parse from " << homology_file.string() << ".");
389 }
390 returnstream.close();
391 } else {
392 ELOG(0, homology_file << " does not exist.");
393 }
394
395 // first we try to look into the HomologyContainer
396 LOG(1, "INFO: Listing all present homologies ...");
397 for (HomologyContainer::container_t::const_iterator iter =
398 homologies.begin(); iter != homologies.end(); ++iter) {
399 LOG(1, "INFO: graph " << iter->first << " has Fragment "
400 << iter->second.first << " and associated energy " << iter->second.second << ".");
401 }
402
[9340ee]403 /******************** Angle TRAINING ********************/
404 {
405 // then we ought to pick the right HomologyGraph ...
406 const HomologyGraph graph = getFirstGraphWithThreeCarbons(homologies);
407 LOG(1, "First representative graph containing three saturated carbons is " << graph << ".");
408
409 // Afterwards we go through all of this type and gather the distance and the energy value
410 typedef std::pair<
411 FunctionApproximation::inputs_t,
412 FunctionApproximation::outputs_t> InputOutputVector_t;
413 InputOutputVector_t DistanceEnergyVector;
414 std::pair<HomologyContainer::const_iterator, HomologyContainer::const_iterator> range =
415 homologies.getHomologousGraphs(graph);
416 for (HomologyContainer::const_iterator fragiter = range.first; fragiter != range.second; ++fragiter) {
417 // get distance out of Fragment
418 const double &energy = fragiter->second.second;
419 const Fragment &fragment = fragiter->second.first;
420 const Fragment::charges_t charges = fragment.getCharges();
421 const Fragment::positions_t positions = fragment.getPositions();
422 std::vector< std::pair<Vector, size_t> > DistanceVectors;
423 for (Fragment::charges_t::const_iterator chargeiter = charges.begin();
424 chargeiter != charges.end(); ++chargeiter) {
425 if (*chargeiter == 6) {
426 Fragment::positions_t::const_iterator positer = positions.begin();
427 const size_t steps = std::distance(charges.begin(), chargeiter);
428 std::advance(positer, steps);
429 DistanceVectors.push_back(
430 std::make_pair(Vector((*positer)[0], (*positer)[1], (*positer)[2]),
431 steps));
432 }
433 }
434 if (DistanceVectors.size() == (size_t)3) {
435 FunctionModel::arguments_t args(3);
436 // we require specific ordering of the carbons: ij, ik, jk
437 typedef std::vector< std::pair<size_t, size_t> > indices_t;
438 indices_t indices;
439 indices += std::make_pair(0,1), std::make_pair(0,2), std::make_pair(1,2);
440 // create the three arguments
441 for (indices_t::const_iterator iter = indices.begin(); iter != indices.end(); ++iter) {
442 const size_t &firstindex = iter->first;
443 const size_t &secondindex = iter->second;
444 argument_t &arg = args[(size_t)std::distance(const_cast<const indices_t&>(indices).begin(), iter)];
445 arg.indices.first = DistanceVectors[firstindex].second;
446 arg.indices.second = DistanceVectors[secondindex].second;
447 arg.distance = DistanceVectors[firstindex].first.distance(DistanceVectors[secondindex].first);
448 arg.globalid = DistanceEnergyVector.first.size();
449 }
450 // make largest distance last to create correct angle
451 // (this would normally depend on the order of the nodes in the subgraph)
452 std::list<argument_t> sorted_args;
453 double greatestdistance = 0.;
454 for(FunctionModel::arguments_t::const_iterator iter = args.begin(); iter != args.end(); ++iter)
455 greatestdistance = std::max(greatestdistance, iter->distance);
456 for(FunctionModel::arguments_t::const_iterator iter = args.begin(); iter != args.end(); ++iter)
457 if (iter->distance == greatestdistance)
458 sorted_args.push_back(*iter);
459 else
460 sorted_args.push_front(*iter);
461 // and add the training pair
462 DistanceEnergyVector.first.push_back( FunctionModel::arguments_t(sorted_args.begin(), sorted_args.end()) );
463 DistanceEnergyVector.second.push_back( FunctionModel::results_t(1,energy) );
464 } else {
465 ELOG(2, "main() - found not exactly three carbon atoms in fragment "
466 << fragment << ".");
467 }
468 }
469 // print training data for debugging
470 {
471 LOG(1, "INFO: I gathered the following (" << DistanceEnergyVector.first.size()
472 << "," << DistanceEnergyVector.second.size() << ") data pairs: ");
473 FunctionApproximation::inputs_t::const_iterator initer = DistanceEnergyVector.first.begin();
474 FunctionApproximation::outputs_t::const_iterator outiter = DistanceEnergyVector.second.begin();
475 for (; initer != DistanceEnergyVector.first.end(); ++initer, ++outiter) {
476 std::stringstream stream;
477 const double cos_angle = function_angle((*initer)[0].distance,(*initer)[1].distance,(*initer)[2].distance);
478 for (size_t index = 0; index < (*initer).size(); ++index)
479 stream << " (" << (*initer)[index].indices.first << "," << (*initer)[index].indices.second
480 << ") " << (*initer)[index].distance;
481 stream << " with energy " << *outiter << " and cos(angle) " << cos_angle;
482 LOG(1, "INFO:" << stream.str());
483 }
484 }
485 // NOTICE that distance are in bohrradi as they come from MPQC!
486
487 // now perform the function approximation by optimizing the model function
488 FunctionModel::parameters_t params(PairPotential_Angle::MAXPARAMS, 0.);
489 params[PairPotential_Angle::energy_offset] = -1.;
490 params[PairPotential_Angle::spring_constant] = 1.;
491 params[PairPotential_Angle::equilibrium_distance] = 0.2;
492 PairPotential_Angle angle;
493 LOG(0, "INFO: Initial parameters are " << params << ".");
494 angle.setParameters(params);
495 FunctionModel &model = angle;
496 FunctionApproximation approximator(
497 DistanceEnergyVector.first.begin()->size(),
498 DistanceEnergyVector.second.begin()->size(),
499 model);
500 approximator.setTrainingData(DistanceEnergyVector.first,DistanceEnergyVector.second);
501 if (model.isBoxConstraint() && approximator.checkParameterDerivatives())
502 approximator(FunctionApproximation::ParameterDerivative);
503 else
504 ELOG(0, "We require parameter derivatives for a box constraint minimization.");
505 params = model.getParameters();
506
507 LOG(0, "RESULT: Best parameters are " << params << ".");
508 }
509
[eb1efe]510 /******************** MORSE TRAINING ********************/
511 {
512 // then we ought to pick the right HomologyGraph ...
513 const HomologyGraph graph = getFirstGraphWithTwoCarbons(homologies);
514 LOG(1, "First representative graph containing two saturated carbons is " << graph << ".");
515
516 // Afterwards we go through all of this type and gather the distance and the energy value
[4ec18b]517 TrainingData MorseData(
518 boost::bind(&Extractors::gatherFirstDistance, _1, _2, 6, 6) // gather first carbon pair
519 );
520 MorseData(homologies.getHomologousGraphs(graph));
521 LOG(1, "INFO: I gathered the following training data: " << MorseData);
[eb1efe]522 // NOTICE that distance are in bohrradi as they come from MPQC!
523
524 // now perform the function approximation by optimizing the model function
[f48ad3]525 FunctionModel::parameters_t params(PairPotential_Morse::MAXPARAMS, 0.);
526 params[PairPotential_Morse::dissociation_energy] = 0.5;
527 params[PairPotential_Morse::energy_offset] = -1.;
528 params[PairPotential_Morse::spring_constant] = 1.;
529 params[PairPotential_Morse::equilibrium_distance] = 2.9;
530 PairPotential_Morse morse;
531 morse.setParameters(params);
[eb1efe]532 FunctionModel &model = morse;
[4ec18b]533 FunctionApproximation approximator(
534 MorseData.getTrainingInputs().begin()->size(),
535 MorseData.getTrainingOutputs().begin()->size(),
536 model);
537 approximator.setTrainingData(MorseData.getTrainingInputs(),MorseData.getTrainingOutputs());
[d03292]538 if (model.isBoxConstraint() && approximator.checkParameterDerivatives())
539 approximator(FunctionApproximation::ParameterDerivative);
540 else
541 ELOG(0, "We require parameter derivatives for a box constraint minimization.");
[f48ad3]542 params = model.getParameters();
[eb1efe]543
544 LOG(0, "RESULT: Best parameters are " << params << ".");
[f06d52]545 }
[eb1efe]546
[40fff1]547 /******************* SATURATION TRAINING *******************/
548 FunctionModel::parameters_t params(SaturationPotential::MAXPARAMS, 0.);
[c62f96]549 {
[eb1efe]550 // then we ought to pick the right HomologyGraph ...
551 const HomologyGraph graph = getFirstGraphWithOneCarbon(homologies);
552 LOG(1, "First representative graph containing one saturated carbon is " << graph << ".");
553
554 // Afterwards we go through all of this type and gather the distance and the energy value
[f68c68]555 TrainingData TersoffData(
556 TrainingData::extractor_t(&Extractors::gatherAllDistances) // gather first carbon pair
557 );
558 TersoffData( homologies.getHomologousGraphs(graph) );
559 LOG(1, "INFO: I gathered the following training data: " << TersoffData);
[eb1efe]560 // NOTICE that distance are in bohrradi as they come from MPQC!
561
562 // now perform the function approximation by optimizing the model function
563 boost::function< std::vector<FunctionModel::arguments_t>(const argument_t &, const double)> triplefunction =
[f68c68]564 boost::bind(&getTripleFromArgument, boost::cref(TersoffData.getTrainingInputs()), _1, _2);
[17b3598]565 srand((unsigned)time(0)); // seed with current time
[40fff1]566 LOG(0, "INFO: Initial parameters are " << params << ".");
567
568 SaturationPotential saturation(triplefunction);
569 saturation.setParameters(params);
570 FunctionModel &model = saturation;
[eb1efe]571 FunctionApproximation approximator(
[f68c68]572 TersoffData.getTrainingInputs().begin()->size(),
573 TersoffData.getTrainingOutputs().begin()->size(),
[4ec18b]574 model);
[f68c68]575 approximator.setTrainingData(TersoffData.getTrainingInputs(),TersoffData.getTrainingOutputs());
[d03292]576 if (model.isBoxConstraint() && approximator.checkParameterDerivatives())
577 approximator(FunctionApproximation::ParameterDerivative);
578 else
579 ELOG(0, "We require parameter derivatives for a box constraint minimization.");
[40fff1]580
[f48ad3]581 params = model.getParameters();
[eb1efe]582
583 LOG(0, "RESULT: Best parameters are " << params << ".");
[a30b7f]584
[40fff1]585// std::cout << "\tsaturationparticle:";
586// std::cout << "\tparticle_type=C,";
587// std::cout << "\tA=" << params[SaturationPotential::A] << ",";
588// std::cout << "\tB=" << params[SaturationPotential::B] << ",";
589// std::cout << "\tlambda=" << params[SaturationPotential::lambda] << ",";
590// std::cout << "\tmu=" << params[SaturationPotential::mu] << ",";
591// std::cout << "\tbeta=" << params[SaturationPotential::beta] << ",";
592// std::cout << "\tn=" << params[SaturationPotential::n] << ",";
593// std::cout << "\tc=" << params[SaturationPotential::c] << ",";
594// std::cout << "\td=" << params[SaturationPotential::d] << ",";
595// std::cout << "\th=" << params[SaturationPotential::h] << ",";
596//// std::cout << "\toffset=" << params[SaturationPotential::offset] << ",";
597// std::cout << "\tR=" << saturation.R << ",";
598// std::cout << "\tS=" << saturation.S << ";";
599// std::cout << std::endl;
[a30b7f]600
601 // check L2 and Lmax error against training set
[f68c68]602 LOG(1, "INFO: L2sum = " << TersoffData.getL2Error(model)
603 << ", LMax = " << TersoffData.getLMaxError(model) << ".");
[f06d52]604 }
605
606 return 0;
607}
Note: See TracBrowser for help on using the repository browser.