Index: src/Potentials/Makefile.am
===================================================================
--- src/Potentials/Makefile.am	(revision 6b3e5eabbfb866e42ce576818aeadd95719a1ac6)
+++ src/Potentials/Makefile.am	(revision 98d166e8fbc83bccb5843ecc5d4296f2c25488c0)
@@ -53,4 +53,11 @@
   Potentials/Specifics/PotentialTypes.def \
   Potentials/Specifics/PotentialTypes.undef
+
+if CONDLEVMAR
+POTENTIALSHEADER += \
+  Potentials/PotentialTrainer.hpp
+POTENTIALSSOURCE = \
+  Potentials/PotentialTrainer.cpp
+endif
 
 # add here headers for real potentials (i.e. the PotentialFactory should instantiate)  
Index: src/Potentials/PotentialTrainer.cpp
===================================================================
--- src/Potentials/PotentialTrainer.cpp	(revision 98d166e8fbc83bccb5843ecc5d4296f2c25488c0)
+++ src/Potentials/PotentialTrainer.cpp	(revision 98d166e8fbc83bccb5843ecc5d4296f2c25488c0)
@@ -0,0 +1,228 @@
+/*
+ * Project: MoleCuilder
+ * Description: creates and alters molecular systems
+ * Copyright (C)  2014 Frederik Heber. All rights reserved.
+ *
+ *
+ *   This file is part of MoleCuilder.
+ *
+ *    MoleCuilder is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation, either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    MoleCuilder is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with MoleCuilder.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * PotentialTrainer.cpp
+ *
+ *  Created on: Sep 11, 2014
+ *      Author: heber
+ */
+
+// include config.h
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+// needs to come before MemDebug due to placement new
+#include <boost/archive/text_iarchive.hpp>
+
+#include "CodePatterns/MemDebug.hpp"
+
+#include "PotentialTrainer.hpp"
+
+#include <algorithm>
+#include <boost/lambda/lambda.hpp>
+#include <boost/filesystem.hpp>
+#include <fstream>
+#include <sstream>
+
+#include "CodePatterns/Assert.hpp"
+#include "CodePatterns/Log.hpp"
+
+#include "Element/element.hpp"
+#include "Fragmentation/Homology/HomologyContainer.hpp"
+#include "Fragmentation/Homology/HomologyGraph.hpp"
+#include "FunctionApproximation/Extractors.hpp"
+#include "FunctionApproximation/FunctionApproximation.hpp"
+#include "FunctionApproximation/FunctionModel.hpp"
+#include "FunctionApproximation/TrainingData.hpp"
+#include "FunctionApproximation/writeDistanceEnergyTable.hpp"
+#include "Potentials/CompoundPotential.hpp"
+#include "Potentials/PotentialSerializer.hpp"
+#include "Potentials/SerializablePotential.hpp"
+
+PotentialTrainer::PotentialTrainer()
+{}
+
+PotentialTrainer::~PotentialTrainer()
+{}
+
+bool PotentialTrainer::operator()(
+    const HomologyContainer &_homologies,
+    const HomologyGraph &_graph,
+    const boost::filesystem::path &_trainingfile,
+    const double _threshold,
+    const unsigned int _best_of_howmany) const
+{
+  // fit potential
+  FunctionModel *model = new CompoundPotential(_graph);
+  ASSERT( model != NULL,
+      "PotentialTrainer::operator() - model is NULL.");
+
+  /******************** TRAINING ********************/
+  // fit potential
+  FunctionModel::parameters_t bestparams(model->getParameterDimension(), 0.);
+  {
+    // Afterwards we go through all of this type and gather the distance and the energy value
+    TrainingData data(model->getSpecificFilter());
+    data(_homologies.getHomologousGraphs(_graph));
+
+    // print distances and energies if desired for debugging
+    if (!data.getTrainingInputs().empty()) {
+      // print which distance is which
+      size_t counter=1;
+      if (DoLog(3)) {
+        const FunctionModel::arguments_t &inputs = data.getAllArguments()[0];
+        for (FunctionModel::arguments_t::const_iterator iter = inputs.begin();
+            iter != inputs.end(); ++iter) {
+          const argument_t &arg = *iter;
+          LOG(3, "DEBUG: distance " << counter++ << " is between (#"
+              << arg.indices.first << "c" << arg.types.first << ","
+              << arg.indices.second << "c" << arg.types.second << ").");
+        }
+      }
+
+      // print table
+      if (_trainingfile.string().empty()) {
+        LOG(3, "DEBUG: I gathered the following training data:\n" <<
+            _detail::writeDistanceEnergyTable(data.getDistanceEnergyTable()));
+      } else {
+        std::ofstream trainingstream(_trainingfile.string().c_str());
+        if (trainingstream.good()) {
+          LOG(3, "DEBUG: Writing training data to file " <<
+              _trainingfile.string() << ".");
+          trainingstream << _detail::writeDistanceEnergyTable(data.getDistanceEnergyTable());
+        }
+        trainingstream.close();
+      }
+    }
+
+    if ((_threshold < 1.) && (_best_of_howmany))
+      ELOG(2, "threshold parameter always overrules max_runs, both are specified.");
+    // now perform the function approximation by optimizing the model function
+    FunctionApproximation approximator(data, *model);
+    if (model->isBoxConstraint() && approximator.checkParameterDerivatives()) {
+      double l2error = std::numeric_limits<double>::max();
+      // seed with current time
+      srand((unsigned)time(0));
+      unsigned int runs=0;
+      // threshold overrules max_runs
+      const double threshold = _threshold;
+      const unsigned int max_runs = (threshold >= 1.) ? _best_of_howmany : 1;
+      LOG(1, "INFO: Maximum runs is " << max_runs << " and threshold set to " << threshold << ".");
+      do {
+        // generate new random initial parameter values
+        model->setParametersToRandomInitialValues(data);
+        LOG(1, "INFO: Initial parameters of run " << runs << " are "
+            << model->getParameters() << ".");
+        approximator(FunctionApproximation::ParameterDerivative);
+        LOG(1, "INFO: Final parameters of run " << runs << " are "
+            << model->getParameters() << ".");
+        const double new_l2error = data.getL2Error(*model);
+        if (new_l2error < l2error) {
+          // store currently best parameters
+          l2error = new_l2error;
+          bestparams = model->getParameters();
+          LOG(1, "STATUS: New fit from run " << runs
+              << " has better error of " << l2error << ".");
+        }
+      } while (( ++runs < max_runs) || (l2error > threshold));
+      // reset parameters from best fit
+      model->setParameters(bestparams);
+      LOG(1, "INFO: Best parameters with L2 error of "
+          << l2error << " are " << model->getParameters() << ".");
+    } else {
+      return false;
+    }
+
+    // create a map of each fragment with error.
+    HomologyContainer::range_t fragmentrange = _homologies.getHomologousGraphs(_graph);
+    TrainingData::L2ErrorConfigurationIndexMap_t WorseFragmentMap =
+        data.getWorstFragmentMap(*model, fragmentrange);
+    LOG(0, "RESULT: WorstFragmentMap " << WorseFragmentMap << ".");
+
+  }
+  delete model;
+
+  return true;
+}
+
+void PotentialTrainer::storePotentials(
+    const boost::filesystem::path &_potentialfile
+    )
+{
+  // print fitted potentials
+  std::stringstream potentials;
+  PotentialSerializer serialize(potentials);
+  serialize();
+  std::ofstream returnstream(_potentialfile.string().c_str());
+  if (returnstream.good()) {
+    returnstream << potentials.str();
+  }
+}
+
+HomologyGraph PotentialTrainer::getFirstGraphwithSpecifiedElements(
+    const HomologyContainer &homologies,
+    const SerializablePotential::ParticleTypes_t &types)
+{
+  ASSERT( !types.empty(),
+      "getFirstGraphwithSpecifiedElements() - charges is empty?");
+  // create charges
+  Fragment::charges_t charges;
+  charges.resize(types.size());
+  std::transform(types.begin(), types.end(),
+      charges.begin(), boost::lambda::_1);
+  // convert into count map
+  Extractors::elementcounts_t counts_per_charge =
+      Extractors::_detail::getElementCounts(charges);
+  ASSERT( !counts_per_charge.empty(),
+      "getFirstGraphwithSpecifiedElements() - charge counts are empty?");
+  LOG(2, "DEBUG: counts_per_charge is " << counts_per_charge << ".");
+  // we want to check each (unique) key only once
+  HomologyContainer::const_key_iterator olditer = homologies.key_end();
+  for (HomologyContainer::const_key_iterator iter =
+      homologies.key_begin(); iter != homologies.key_end(); olditer = iter++) {
+    // if it's the same as the old one, skip it
+    if (*olditer == *iter)
+      continue;
+    // if it's a new key, check if every element has the right number of counts
+    Extractors::elementcounts_t::const_iterator countiter = counts_per_charge.begin();
+    for (; countiter != counts_per_charge.end(); ++countiter)
+      if (!(*iter).hasTimesAtomicNumber(
+          static_cast<size_t>(countiter->first),
+          static_cast<size_t>(countiter->second))
+          )
+        break;
+    if( countiter == counts_per_charge.end())
+      return *iter;
+  }
+  return HomologyGraph();
+}
+
+SerializablePotential::ParticleTypes_t PotentialTrainer::getNumbersFromElements(
+    const std::vector<const element *> &fragment)
+{
+  SerializablePotential::ParticleTypes_t fragmentnumbers;
+  std::transform(fragment.begin(), fragment.end(), std::back_inserter(fragmentnumbers),
+      boost::bind(&element::getAtomicNumber, _1));
+  return fragmentnumbers;
+}
Index: src/Potentials/PotentialTrainer.hpp
===================================================================
--- src/Potentials/PotentialTrainer.hpp	(revision 98d166e8fbc83bccb5843ecc5d4296f2c25488c0)
+++ src/Potentials/PotentialTrainer.hpp	(revision 98d166e8fbc83bccb5843ecc5d4296f2c25488c0)
@@ -0,0 +1,56 @@
+/*
+ * PotentialTrainer.hpp
+ *
+ *  Created on: Sep 11, 2014
+ *      Author: heber
+ */
+
+#ifndef POTENTIALTRAINER_HPP_
+#define POTENTIALTRAINER_HPP_
+
+// include config.h
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <boost/filesystem/path.hpp>
+#include <vector>
+
+#include "Potentials/SerializablePotential.hpp"
+
+class element;
+class HomologyContainer;
+class HomologyGraph;
+
+/** This class is a functor for training a (compound) potential from homologies.
+ *
+ */
+class PotentialTrainer
+{
+public:
+  PotentialTrainer();
+  ~PotentialTrainer();
+
+  bool operator()(
+        const HomologyContainer &_homologies,
+        const HomologyGraph &_graph,
+        const boost::filesystem::path &_trainingfile,
+        const double _threshold,
+        const unsigned int _best_of_howmany) const;
+
+  static void storePotentials(
+      const boost::filesystem::path &_potentialfile
+      );
+
+  static
+  HomologyGraph getFirstGraphwithSpecifiedElements(
+      const HomologyContainer &homologies,
+      const SerializablePotential::ParticleTypes_t &types);
+
+  static
+  SerializablePotential::ParticleTypes_t getNumbersFromElements(
+      const std::vector<const element *> &fragment);
+};
+
+
+#endif /* POTENTIALTRAINER_HPP_ */
