Index: src/Actions/GlobalListOfActions.hpp
===================================================================
--- src/Actions/GlobalListOfActions.hpp	(revision 2a6d8c7977c1f749091ead256bcca349538a8b59)
+++ src/Actions/GlobalListOfActions.hpp	(revision 98d166e8fbc83bccb5843ecc5d4296f2c25488c0)
@@ -148,6 +148,9 @@
 #define GLOBALLISTOFACTIONS_LEVMAR \
     BOOST_PP_SEQ_PUSH_BACK( \
-        GLOBALLISTOFACTIONS_initial, \
-        PotentialFitPotential \
+    		BOOST_PP_SEQ_PUSH_BACK( \
+    				GLOBALLISTOFACTIONS_initial, \
+    				PotentialFitPotential \
+    		), \
+        PotentialFitCompoundPotential \
     )
 #else
Index: src/Actions/Makefile.am
===================================================================
--- src/Actions/Makefile.am	(revision 2a6d8c7977c1f749091ead256bcca349538a8b59)
+++ src/Actions/Makefile.am	(revision 98d166e8fbc83bccb5843ecc5d4296f2c25488c0)
@@ -363,8 +363,11 @@
 if CONDLEVMAR
 POTENTIALACTIONSOURCE += \
+  Actions/PotentialAction/FitCompoundPotentialAction.cpp \
   Actions/PotentialAction/FitPotentialAction.cpp
 POTENTIALACTIONHEADER += \
+  Actions/PotentialAction/FitCompoundPotentialAction.hpp \
   Actions/PotentialAction/FitPotentialAction.hpp
 POTENTIALACTIONDEFS += \
+  Actions/PotentialAction/FitCompoundPotentialAction.def \
   Actions/PotentialAction/FitPotentialAction.def
 endif
Index: src/Actions/PotentialAction/FitCompoundPotentialAction.cpp
===================================================================
--- src/Actions/PotentialAction/FitCompoundPotentialAction.cpp	(revision 98d166e8fbc83bccb5843ecc5d4296f2c25488c0)
+++ src/Actions/PotentialAction/FitCompoundPotentialAction.cpp	(revision 98d166e8fbc83bccb5843ecc5d4296f2c25488c0)
@@ -0,0 +1,167 @@
+/*
+ * 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/>.
+ */
+
+/*
+ * FitCompoundPotentialAction.cpp
+ *
+ *  Created on: Sep 10, 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 <algorithm>
+#include <boost/filesystem.hpp>
+#include <fstream>
+
+#include "Actions/PotentialAction/FitCompoundPotentialAction.hpp"
+
+#include "CodePatterns/Log.hpp"
+
+#include "Fragmentation/Homology/HomologyContainer.hpp"
+#include "Fragmentation/Homology/HomologyGraph.hpp"
+#include "Fragmentation/Summation/SetValues/Fragment.hpp"
+#include "Potentials/Exceptions.hpp"
+#include "Potentials/PotentialDeserializer.hpp"
+#include "Potentials/PotentialFactory.hpp"
+#include "Potentials/PotentialRegistry.hpp"
+#include "Potentials/PotentialTrainer.hpp"
+#include "Potentials/SerializablePotential.hpp"
+#include "World.hpp"
+
+using namespace MoleCuilder;
+
+// and construct the stuff
+#include "FitCompoundPotentialAction.def"
+#include "Action_impl_pre.hpp"
+/** =========== define the function ====================== */
+
+ActionState::ptr PotentialFitCompoundPotentialAction::performCall() {
+  // fragment specifies the homology fragment to use
+  SerializablePotential::ParticleTypes_t fragmentnumbers =
+      PotentialTrainer::getNumbersFromElements(params.fragment.get());
+
+  // either charges and a potential is specified or a file
+  if (boost::filesystem::exists(params.potential_file.get())) {
+    std::ifstream returnstream(params.potential_file.get().string().c_str());
+    if (returnstream.good()) {
+      try {
+        PotentialDeserializer deserialize(returnstream);
+        deserialize();
+      } catch (SerializablePotentialMissingValueException &e) {
+        if (const std::string *key = boost::get_error_info<SerializablePotentialKey>(e))
+          STATUS("Missing value when parsing information for potential "+*key+".");
+        else
+          STATUS("Missing value parsing information for potential with unknown key.");
+        return Action::failure;
+      } catch (SerializablePotentialIllegalKeyException &e) {
+        if (const std::string *key = boost::get_error_info<SerializablePotentialKey>(e))
+          STATUS("Illegal key parsing information for potential "+*key+".");
+        else
+          STATUS("Illegal key parsing information for potential with unknown key.");
+        return Action::failure;
+      }
+    } else {
+      STATUS("Failed to parse from "+params.potential_file.get().string()+".");
+      return Action::failure;
+    }
+    returnstream.close();
+
+    LOG(0, "STATUS: I'm training now a set of potentials parsed from "
+        << params.potential_file.get().string() << " on a fragment "
+        << fragmentnumbers << " on data from World's homologies.");
+
+  } else {
+      STATUS("No existing potential file given!");
+      return Action::failure;
+  }
+
+  // parse homologies into container
+  HomologyContainer &homologies = World::getInstance().getHomologies();
+
+  // first we try to look into the HomologyContainer
+  LOG(1, "INFO: Listing all present homologies ...");
+  for (HomologyContainer::container_t::const_iterator iter =
+      homologies.begin(); iter != homologies.end(); ++iter) {
+    LOG(1, "INFO: graph " << iter->first
+        << " has Fragment " << iter->second.fragment
+        << ", associated energy " << iter->second.energy
+        << ", and sampled grid integral " << iter->second.charge_distribution.integral()
+        << ".");
+  }
+
+  // then we ought to pick the right HomologyGraph ...
+  const HomologyGraph graph =
+      PotentialTrainer::getFirstGraphwithSpecifiedElements(homologies,fragmentnumbers);
+  if (graph != HomologyGraph()) {
+    LOG(1, "First representative graph containing fragment "
+        << fragmentnumbers << " is " << graph << ".");
+  } else {
+    STATUS("Specific fragment "+toString(fragmentnumbers)+" not found in homologies!");
+    return Action::failure;
+  }
+
+  // training
+  PotentialTrainer trainer;
+  const bool status = trainer(
+      homologies,
+      graph,
+      params.training_file.get(),
+      params.threshold.get(),
+      params.best_of_howmany.get());
+  if (!status) {
+    STATUS("No required parameter derivatives for a box constraint minimization known.");
+    return Action::failure;
+  }
+
+  // store the potentials
+  if (!params.potential_file.get().string().empty()) {
+    PotentialTrainer::storePotentials(params.potential_file.get());
+  }
+
+  return Action::success;
+}
+
+ActionState::ptr PotentialFitCompoundPotentialAction::performUndo(ActionState::ptr _state) {
+  return Action::success;
+}
+
+ActionState::ptr PotentialFitCompoundPotentialAction::performRedo(ActionState::ptr _state){
+  return Action::success;
+}
+
+bool PotentialFitCompoundPotentialAction::canUndo() {
+  return false;
+}
+
+bool PotentialFitCompoundPotentialAction::shouldUndo() {
+  return false;
+}
+/** =========== end of function ====================== */
Index: src/Actions/PotentialAction/FitCompoundPotentialAction.def
===================================================================
--- src/Actions/PotentialAction/FitCompoundPotentialAction.def	(revision 98d166e8fbc83bccb5843ecc5d4296f2c25488c0)
+++ src/Actions/PotentialAction/FitCompoundPotentialAction.def	(revision 98d166e8fbc83bccb5843ecc5d4296f2c25488c0)
@@ -0,0 +1,51 @@
+/*
+ * FitCompoundPotentialAction.def
+ *
+ *  Created on: Sep 10, 2014
+ *      Author: heber
+ */
+
+// all includes and forward declarations necessary for non-integral types below
+#include <boost/filesystem/path.hpp>
+#include <string>
+#include <vector>
+
+#include "Parameters/Validators/DummyValidator.hpp"
+#include "Parameters/Validators/GenericValidators.hpp"
+#include "Parameters/Validators/Ops_Validator.hpp"
+#include "Parameters/Validators/RangeValidator.hpp"
+#include "Parameters/Validators/STLVectorValidator.hpp"
+#include "Parameters/Validators/Specific/ElementValidator.hpp"
+#include "Parameters/Validators/Specific/FilePresentValidator.hpp"
+#include "Parameters/Validators/Specific/FileSuffixValidator.hpp"
+#include "Parameters/Validators/Specific/PotentialTypeValidator.hpp"
+
+// i.e. there is an integer with variable name Z that can be found in
+// ValueStorage by the token "Z" -> first column: int, Z, "Z"
+// "undefine" if no parameters are required, use (NOPARAM_DEFAULT) for each (undefined) default value
+#define paramtypes (boost::filesystem::path)(boost::filesystem::path)(std::vector<const element *>)(unsigned int)(double)
+#define paramtokens ("training-file")("potential-file")("fragment-charges")("take-best-of")("set-threshold")
+#define paramdescriptions ("optional file to write training data to")("potential file specifying multiple potentials to fit")("charges specifying the fragment")("take the best among this many approximations")("Require L2 error to be smaller than threshold, overrides number of attempts")
+#define paramdefaults (PARAM_DEFAULT(""))(NOPARAM_DEFAULT)(NOPARAM_DEFAULT)(PARAM_DEFAULT(3))(PARAM_DEFAULT(1.))
+#define paramreferences (training_file)(potential_file)(fragment)(best_of_howmany)(threshold)
+#define paramvalids \
+(DummyValidator<boost::filesystem::path>()) \
+(FilePresentValidator() && FileSuffixValidator("potentials")) \
+(STLVectorValidator< std::vector<const element *> >(1,99, ElementValidator())) \
+(PositiveValidator<unsigned int>()) \
+(PositiveValidator<double>())
+
+#undef statetypes
+#undef statereferences
+
+// some defines for all the names, you may use ACTION, STATE and PARAMS
+#define CATEGORY Potential
+#define MENUNAME "potential"
+#define MENUPOSITION 4
+#define ACTIONNAME FitCompoundPotential
+#define TOKEN "fit-compound-potential"
+
+
+// finally the information stored in the ActionTrait specialization
+#define DESCRIPTION "fit an empirical potential to the given part of a specified fragment"
+#undef SHORTFORM
Index: src/Actions/PotentialAction/FitCompoundPotentialAction.hpp
===================================================================
--- src/Actions/PotentialAction/FitCompoundPotentialAction.hpp	(revision 98d166e8fbc83bccb5843ecc5d4296f2c25488c0)
+++ src/Actions/PotentialAction/FitCompoundPotentialAction.hpp	(revision 98d166e8fbc83bccb5843ecc5d4296f2c25488c0)
@@ -0,0 +1,22 @@
+/*
+ * FitCompoundPotentialAction.hpp
+ *
+ *  Created on: Sep 10, 2014
+ *      Author: heber
+ */
+
+#ifndef FITCOMPOUNDPOTENTIALACTION_HPP_
+#define FITCOMPOUNDPOTENTIALACTION_HPP_
+
+// include config.h
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+
+#include "Actions/Action.hpp"
+
+#include "FitCompoundPotentialAction.def"
+#include "Action_impl_header.hpp"
+
+#endif /* FITCOMPOUNDPOTENTIALACTION_HPP_ */
Index: src/Actions/PotentialAction/FitPotentialAction.cpp
===================================================================
--- src/Actions/PotentialAction/FitPotentialAction.cpp	(revision 2a6d8c7977c1f749091ead256bcca349538a8b59)
+++ src/Actions/PotentialAction/FitPotentialAction.cpp	(revision 98d166e8fbc83bccb5843ecc5d4296f2c25488c0)
@@ -55,16 +55,11 @@
 #include "Fragmentation/Homology/HomologyGraph.hpp"
 #include "Fragmentation/Summation/SetValues/Fragment.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/Exceptions.hpp"
-#include "Potentials/PotentialDeserializer.hpp"
+#include "Potentials/EmpiricalPotential.hpp"
 #include "Potentials/PotentialFactory.hpp"
 #include "Potentials/PotentialRegistry.hpp"
 #include "Potentials/PotentialSerializer.hpp"
+#include "Potentials/PotentialTrainer.hpp"
 #include "Potentials/SerializablePotential.hpp"
+#include "World.hpp"
 
 using namespace MoleCuilder;
@@ -75,127 +70,52 @@
 /** =========== define the function ====================== */
 
-HomologyGraph 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
-  for (HomologyContainer::const_key_iterator iter = homologies.key_begin();
-      iter != homologies.key_end(); iter = homologies.getNextKey(iter)) {
-    // 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 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;
-}
-
-
 ActionState::ptr PotentialFitPotentialAction::performCall() {
   // fragment specifies the homology fragment to use
   SerializablePotential::ParticleTypes_t fragmentnumbers =
-      getNumbersFromElements(params.fragment.get());
+      PotentialTrainer::getNumbersFromElements(params.fragment.get());
 
   // either charges and a potential is specified or a file
-  if (boost::filesystem::exists(params.potential_file.get())) {
-    std::ifstream returnstream(params.potential_file.get().string().c_str());
-    if (returnstream.good()) {
-      try {
-        PotentialDeserializer deserialize(returnstream);
-        deserialize();
-      } catch (SerializablePotentialMissingValueException &e) {
-        if (const std::string *key = boost::get_error_info<SerializablePotentialKey>(e))
-          STATUS("Missing value when parsing information for potential "+*key+".");
-        else
-          STATUS("Missing value parsing information for potential with unknown key.");
-        return Action::failure;
-      } catch (SerializablePotentialIllegalKeyException &e) {
-        if (const std::string *key = boost::get_error_info<SerializablePotentialKey>(e))
-          STATUS("Illegal key parsing information for potential "+*key+".");
-        else
-          STATUS("Illegal key parsing information for potential with unknown key.");
-        return Action::failure;
-      }
-    } else {
-      STATUS("Failed to parse from "+params.potential_file.get().string()+".");
-      return Action::failure;
+  if (params.charges.get().empty()) {
+    STATUS("No charges given!");
+    return Action::failure;
+  } else {
+    // charges specify the potential type
+    SerializablePotential::ParticleTypes_t chargenumbers =
+        PotentialTrainer::getNumbersFromElements(params.charges.get());
+
+    LOG(0, "STATUS: I'm training now a " << params.potentialtype.get()
+        << " potential on charges " << chargenumbers << " on data from World's homologies.");
+
+    // register desired potential and an additional constant one
+    {
+      EmpiricalPotential *potential =
+          PotentialFactory::getInstance().createInstance(
+              params.potentialtype.get(),
+              chargenumbers);
+      // check whether such a potential already exists
+      const std::string potential_name = potential->getName();
+      if (PotentialRegistry::getInstance().isPresentByName(potential_name)) {
+        delete potential;
+        potential = PotentialRegistry::getInstance().getByName(potential_name);
+      } else
+        PotentialRegistry::getInstance().registerInstance(potential);
     }
-    returnstream.close();
-
-    LOG(0, "STATUS: I'm training now a set of potentials parsed from "
-        << params.potential_file.get().string() << " on a fragment "
-        << fragmentnumbers << " on data from World's homologies.");
-
-  } else {
-    if (params.charges.get().empty()) {
-      STATUS("Neither charges nor potential file given!");
-      return Action::failure;
-    } else {
-      // charges specify the potential type
-      SerializablePotential::ParticleTypes_t chargenumbers =
-          getNumbersFromElements(params.charges.get());
-
-      LOG(0, "STATUS: I'm training now a " << params.potentialtype.get()
-          << " potential on charges " << chargenumbers << " on data from World's homologies.");
-
-      // register desired potential and an additional constant one
-      {
-        EmpiricalPotential *potential =
-            PotentialFactory::getInstance().createInstance(
-                params.potentialtype.get(),
-                chargenumbers);
-        // check whether such a potential already exists
-        const std::string potential_name = potential->getName();
-        if (PotentialRegistry::getInstance().isPresentByName(potential_name)) {
-          delete potential;
-          potential = PotentialRegistry::getInstance().getByName(potential_name);
-        } else
-          PotentialRegistry::getInstance().registerInstance(potential);
-      }
-      {
-        EmpiricalPotential *constant =
-            PotentialFactory::getInstance().createInstance(
-                std::string("constant"),
-                SerializablePotential::ParticleTypes_t());
-        // check whether such a potential already exists
-        const std::string constant_name = constant->getName();
-        if (PotentialRegistry::getInstance().isPresentByName(constant_name)) {
-          delete constant;
-          constant = PotentialRegistry::getInstance().getByName(constant_name);
-        } else
-          PotentialRegistry::getInstance().registerInstance(constant);
-      }
+    {
+      EmpiricalPotential *constant =
+          PotentialFactory::getInstance().createInstance(
+              std::string("constant"),
+              SerializablePotential::ParticleTypes_t());
+      // check whether such a potential already exists
+      const std::string constant_name = constant->getName();
+      if (PotentialRegistry::getInstance().isPresentByName(constant_name)) {
+        delete constant;
+        constant = PotentialRegistry::getInstance().getByName(constant_name);
+      } else
+        PotentialRegistry::getInstance().registerInstance(constant);
     }
   }
 
   // parse homologies into container
-  HomologyContainer &homologies = World::getInstance().getHomologies();
+  const HomologyContainer &homologies = World::getInstance().getHomologies();
 
   // first we try to look into the HomologyContainer
@@ -211,5 +131,6 @@
 
   // then we ought to pick the right HomologyGraph ...
-  const HomologyGraph graph = getFirstGraphwithSpecifiedElements(homologies,fragmentnumbers);
+  const HomologyGraph graph =
+      PotentialTrainer::getFirstGraphwithSpecifiedElements(homologies,fragmentnumbers);
   if (graph != HomologyGraph()) {
     LOG(1, "First representative graph containing fragment "
@@ -220,104 +141,26 @@
   }
 
-  // fit potential
-  FunctionModel *model = new CompoundPotential(graph);
-  ASSERT( model != NULL,
-      "PotentialFitPotentialAction::performCall() - model is NULL.");
+  // training
+  PotentialTrainer trainer;
+  const bool status = trainer(
+      homologies,
+      graph,
+      params.training_file.get(),
+      params.threshold.get(),
+      params.best_of_howmany.get());
+  if (!status) {
+    STATUS("No required parameter derivatives for a box constraint minimization known.");
+    return Action::failure;
+  }
 
-  /******************** 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 (params.training_file.get().string().empty()) {
-        LOG(3, "DEBUG: I gathered the following training data:\n" <<
-            _detail::writeDistanceEnergyTable(data.getDistanceEnergyTable()));
-      } else {
-        std::ofstream trainingstream(params.training_file.get().string().c_str());
-        if (trainingstream.good()) {
-          LOG(3, "DEBUG: Writing training data to file " <<
-              params.training_file.get().string() << ".");
-          trainingstream << _detail::writeDistanceEnergyTable(data.getDistanceEnergyTable());
-        }
-        trainingstream.close();
-      }
-    }
-
-    if ((params.threshold.get() < 1) && (params.best_of_howmany.isSet()))
-      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 = params.threshold.get();
-      const unsigned int max_runs = (threshold >= 1.) ?
-          (params.best_of_howmany.isSet() ? params.best_of_howmany.get() : 1) : 0;
-      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 {
-      STATUS("No required parameter derivatives for a box constraint minimization known.");
-      return Action::failure;
-    }
-
-    // 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 << ".");
-
-    // print fitted potentials
-    std::stringstream potentials;
-    PotentialSerializer serialize(potentials);
-    serialize();
-    LOG(1, "STATUS: Resulting parameters are " << std::endl << potentials.str());
-    std::ofstream returnstream(params.potential_file.get().string().c_str());
-    if (returnstream.good()) {
-      returnstream << potentials.str();
-    }
+  // store the potentials
+  // print fitted potentials
+  std::stringstream potentials;
+  PotentialSerializer serialize(potentials);
+  serialize();
+  LOG(1, "STATUS: Resulting parameters are " << std::endl << potentials.str());
+  if (!params.potential_file.get().string().empty()) {
+    PotentialTrainer::storePotentials(params.potential_file.get());
   }
-  delete model;
 
   return Action::success;
Index: src/Actions/PotentialAction/FitPotentialAction.def
===================================================================
--- src/Actions/PotentialAction/FitPotentialAction.def	(revision 2a6d8c7977c1f749091ead256bcca349538a8b59)
+++ src/Actions/PotentialAction/FitPotentialAction.def	(revision 98d166e8fbc83bccb5843ecc5d4296f2c25488c0)
@@ -20,4 +20,5 @@
 #include "Parameters/Validators/Specific/FileSuffixValidator.hpp"
 #include "Parameters/Validators/Specific/FilePresentValidator.hpp"
+#include "Parameters/Validators/Specific/FileSuffixValidator.hpp"
 #include "Parameters/Validators/Specific/PotentialTypeValidator.hpp"
 
@@ -25,13 +26,13 @@
 // ValueStorage by the token "Z" -> first column: int, Z, "Z"
 // "undefine" if no parameters are required, use (NOPARAM_DEFAULT) for each (undefined) default value
-#define paramtypes (boost::filesystem::path)(std::string)(boost::filesystem::path)(std::vector<const element *>)(std::vector<const element *>)(unsigned int)(double)
-#define paramtokens ("training-file")("potential-type")("potential-file")("potential-charges")("fragment-charges")("take-best-of")("set-threshold")
-#define paramdescriptions ("optional file to write training data to")("potential type to fit")("optional potential file specifying multiple potentials to fit")("charges specifying the potential")("charges specifying the fragment")("take the best among this many approximations")("Require L2 error to be smaller than threshold, overrides number of attempts")
-#define paramdefaults (PARAM_DEFAULT(""))(NOPARAM_DEFAULT)(NOPARAM_DEFAULT)(NOPARAM_DEFAULT)(NOPARAM_DEFAULT)(PARAM_DEFAULT(3))(PARAM_DEFAULT(1.))
-#define paramreferences (training_file)(potentialtype)(potential_file)(charges)(fragment)(best_of_howmany)(threshold)
+#define paramtypes (boost::filesystem::path)(boost::filesystem::path)(std::string)(std::vector<const element *>)(std::vector<const element *>)(unsigned int)(double)
+#define paramtokens ("training-file")("potential-file")("potential-type")("potential-charges")("fragment-charges")("take-best-of")("set-threshold")
+#define paramdescriptions ("optional file to write training data to")("optional potential file to wrote resulting potentials to")("potential type to fit")("charges specifying the potential")("charges specifying the fragment")("take the best among this many approximations")("Require L2 error to be smaller than threshold, overrides number of attempts")
+#define paramdefaults (PARAM_DEFAULT(""))(PARAM_DEFAULT(""))(NOPARAM_DEFAULT)(NOPARAM_DEFAULT)(NOPARAM_DEFAULT)(PARAM_DEFAULT(3))(PARAM_DEFAULT(1.))
+#define paramreferences (training_file)(potential_file)(potentialtype)(charges)(fragment)(best_of_howmany)(threshold)
 #define paramvalids \
 (DummyValidator<boost::filesystem::path>()) \
-(EmptyStringValidator() || PotentialTypeValidator()) \
 (!FilePresentValidator() || FileSuffixValidator("potentials")) \
+(PotentialTypeValidator()) \
 (STLVectorValidator< std::vector<const element *> >(0,99, ElementValidator())) \
 (STLVectorValidator< std::vector<const element *> >(1,99, ElementValidator())) \
Index: src/Potentials/Makefile.am
===================================================================
--- src/Potentials/Makefile.am	(revision 2a6d8c7977c1f749091ead256bcca349538a8b59)
+++ 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_ */
