Changeset caa00e9


Ignore:
Timestamp:
Feb 27, 2013, 12:39:03 PM (12 years ago)
Author:
Frederik Heber <heber@…>
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:
df350c
Parents:
dbf8c8
git-author:
Frederik Heber <heber@…> (12/06/12 10:35:37)
git-committer:
Frederik Heber <heber@…> (02/27/13 12:39:03)
Message:

Added gatherAllDistancesFromFragment() to Extractors.

  • gatherDistancesFromFragment() did only get the first matching distance, but e.g. for SaturationPotential we need to get all from (8,1,1) for types (8,1).
  • this involved three helper functions initially similar in spirit, but we get all combinations via a simple recursion with pickLastElementAsTarget().
Location:
src/FunctionApproximation
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • src/FunctionApproximation/Extractors.cpp

    rdbf8c8 rcaa00e9  
    3636#include "CodePatterns/MemDebug.hpp"
    3737
     38#include <sstream>
    3839#include <utility>
    3940#include <vector>
    4041#include <boost/assign.hpp>
     42#include <boost/foreach.hpp>
    4143
    4244#include "CodePatterns/Assert.hpp"
     
    210212        chargeiter = ++tempiter;
    211213      } else {
    212         ELOG(1, "Could not find desired number of elements " << count << " in fragment.");
     214        //ELOG(1, "Could not find desired number of elements " << count << " in fragment.");
    213215        return Extractors::elementtargets_t();
    214216      }
     
    217219  return elementtargets;
    218220}
     221
     222Extractors::elementtargets_t
     223Extractors::_detail::convertChargesToTargetMap(
     224    const Fragment::charges_t& charges,
     225    Fragment::charges_t elements
     226    )
     227{
     228  // place each charge into a map
     229  elementtargets_t completeelementtargets;
     230  for (chargeiter_t chargeiter = charges.begin();
     231      chargeiter != charges.end();
     232      ++chargeiter) {
     233    std::pair< elementtargets_t::iterator, bool> inserter =
     234        completeelementtargets.insert( std::make_pair( *chargeiter, chargeiters_t(1, chargeiter)) );
     235    // if already present, append to it
     236    if (!inserter.second) {
     237      inserter.first->second.push_back(chargeiter);
     238    }
     239  }
     240  // pick out desired charges only
     241  std::sort(elements.begin(), elements.end());
     242  Fragment::charges_t::iterator eraseiter =
     243      std::unique(elements.begin(), elements.end());
     244  elements.erase(eraseiter, elements.end());
     245  elementtargets_t elementtargets;
     246  for(Fragment::charges_t::const_iterator iter = elements.begin();
     247      iter != elements.end();
     248      ++iter) {
     249    elementtargets_t::const_iterator finditer = completeelementtargets.find(*iter);
     250    ASSERT( finditer != completeelementtargets.end(),
     251        "Extractors::_detail::convertChargesToTargetMap() - no element "+toString(*iter)+" present?");
     252    std::pair< elementtargets_t::iterator, bool> inserter =
     253        elementtargets.insert( std::make_pair( finditer->first, finditer->second) );
     254    ASSERT( inserter.second,
     255        "Extractors::_detail::convertChargesToTargetMap() - key twice?");
     256  }
     257  return elementtargets;
     258}
     259
    219260
    220261Extractors::chargeiters_t
     
    227268  chargeiters_t targets;
    228269  elementcounts_t counts; // how many chargeiters of this element have been used
    229   targets.reserve(elements.size());
    230   for (Fragment::charges_t::const_iterator elementiter = elements.begin();
    231       elementiter != elements.end(); ++elementiter) {
    232     const element_t &element = *elementiter;
    233     count_t &count = counts[element]; // if not present, std::map creates instances with default of 0
     270  if (!elements.empty()) {  // skip if no elements given
     271    targets.reserve(elements.size());
     272    for (Fragment::charges_t::const_iterator elementiter = elements.begin();
     273        elementiter != elements.end(); ++elementiter) {
     274      const element_t &element = *elementiter;
     275      count_t &count = counts[element]; // if not present, std::map creates instances with default of 0
    234276#ifndef NDEBUG
    235     {
    236       elementcounts_t::const_iterator testiter = elementcounts.find(element);
    237       ASSERT( (testiter != elementcounts.end()) && (count < testiter->second),
    238           "Extractors::_detail::realignElementTargets() - we want to use more chargeiters for element "
    239           +toString(element)+" than we counted initially.");
    240     }
     277      {
     278        elementcounts_t::const_iterator testiter = elementcounts.find(element);
     279        ASSERT( (testiter != elementcounts.end()) && (count < testiter->second),
     280            "Extractors::_detail::realignElementTargets() - we want to use more chargeiters for element "
     281            +toString(element)+" than we counted initially.");
     282      }
    241283#endif
    242     elementtargets_t::const_iterator targetiter = elementtargets.find(element);
    243     ASSERT (targetiter != elementtargets.end(),
    244         "Extractors::_detail::realignElementTargets() - not enough chargeiters for element "
    245         +toString(element)+".");
    246     const chargeiters_t &chargeiters = targetiter->second;
    247     const chargeiter_t &chargeiter = chargeiters[count++];
    248     targets.push_back(chargeiter);
     284      elementtargets_t::const_iterator targetiter = elementtargets.find(element);
     285      if (targetiter != elementtargets.end()) {
     286        const chargeiters_t &chargeiters = targetiter->second;
     287        const chargeiter_t &chargeiter = chargeiters[count++];
     288        targets.push_back(chargeiter);
     289      }
     290    }
    249291  }
    250292  return targets;
     293}
     294
     295FunctionModel::arguments_t
     296Extractors::gatherAllDistancesFromFragment(
     297    const Fragment::positions_t& positions,
     298    const Fragment::charges_t& charges,
     299    const Fragment::charges_t elements,
     300    const size_t globalid
     301    )
     302{
     303  /// The main problem here is that we have to know how many same
     304  /// elements (but different atoms!) we are required to find. Hence,
     305  /// we first have to count same elements, then get different targets
     306  /// for each and then associated them in correct order back again.
     307
     308  // 1. we have to place each charge into a map as unique chargeiter, i.e. map
     309  elementtargets_t elementtargets =
     310      Extractors::_detail::convertChargesToTargetMap(
     311          charges,
     312          elements);
     313
     314  // 2. now we have to combine elementcounts out of elementtargets per desired element
     315  //    in a combinatorial fashion
     316  targets_per_combination_t combinations =
     317      Extractors::_detail::CombineChargesAndTargets(
     318          elements,
     319          elementtargets);
     320
     321  // 3. finally, convert chargeiters into argument list
     322  FunctionModel::arguments_t args =
     323      Extractors::_detail::convertTargetsToArguments(
     324          positions,
     325          charges,
     326          combinations,
     327          globalid);
     328
     329  return args;
     330}
     331
     332Extractors::targets_per_combination_t
     333Extractors::_detail::CombineChargesAndTargets(
     334    const Fragment::charges_t& elements,
     335    const elementtargets_t& elementtargets
     336    )
     337{
     338  // recursively create all correct combinations of targets
     339  targets_per_combination_t combinations;
     340  chargeiters_t currenttargets;
     341  boost::function<void (const chargeiters_t &currenttargets)> addFunction =
     342      boost::bind(&targets_per_combination_t::push_back,
     343          boost::ref(combinations),
     344          _1);
     345  pickLastElementAsTarget(elements, elementtargets, currenttargets, addFunction);
     346
     347  return combinations;
     348}
     349
     350FunctionModel::arguments_t
     351Extractors::_detail::convertTargetsToArguments(
     352    const Fragment::positions_t& positions,
     353    const Fragment::charges_t& charges,
     354    const targets_per_combination_t combinations,
     355    const size_t globalid
     356    )
     357{
     358  FunctionModel::arguments_t args;
     359  // create arguments from each combination
     360  for (targets_per_combination_t::const_iterator iter = combinations.begin();
     361      iter != combinations.end();
     362      ++iter) {
     363    Fragment::positions_t partpositions;
     364    Fragment::charges_t partcharges;
     365    partpositions.reserve(iter->size());
     366    partcharges.reserve(iter->size());
     367    for(chargeiters_t::const_iterator targetiter = iter->begin();
     368        targetiter != iter->end();
     369        ++targetiter) {
     370      Fragment::positions_t::const_iterator positer = positions.begin();
     371      std::advance(positer, std::distance(charges.begin(), *targetiter));
     372      partpositions.push_back(*positer);
     373      partcharges.push_back(**targetiter);
     374    }
     375    FunctionModel::arguments_t partargs =
     376        gatherAllSymmetricDistanceArguments(partpositions, partcharges, globalid);
     377    args.insert(args.end(), partargs.begin(), partargs.end());
     378  }
     379
     380  return args;
     381}
     382
     383void
     384Extractors::_detail::pickLastElementAsTarget(
     385    Fragment::charges_t elements,
     386    elementtargets_t elementtargets,
     387    chargeiters_t &currenttargets,
     388    boost::function<void (const chargeiters_t &currenttargets)> &addFunction
     389    )
     390{
     391  // get last element from charges
     392  const Fragment::charge_t charge = elements.back();
     393  elements.pop_back();
     394  elementtargets_t::iterator iter = elementtargets.find(charge);
     395  if (iter == elementtargets.end())
     396    return;
     397  bool NotEmpty = !iter->second.empty();
     398  while (NotEmpty) {
     399    // get last target from the vector of chargeiters
     400    chargeiter_t target = iter->second.back();
     401    iter->second.pop_back();
     402    // remove this key if empty
     403    if (iter->second.empty()) {
     404      elementtargets.erase(iter);
     405      NotEmpty = false;
     406    }
     407    currenttargets.push_back(target);
     408    if (elements.empty()) {
     409      // call add function
     410      {
     411        std::stringstream targetstream;
     412        BOOST_FOREACH( chargeiter_t target, currenttargets ) {
     413          targetstream << " " << *target;
     414        }
     415        LOG(3, "DEBUG: Adding set" << targetstream.str() << ".");
     416      }
     417      addFunction(currenttargets);
     418    } else {
     419      // if not, call us recursively
     420      pickLastElementAsTarget(elements, elementtargets, currenttargets, addFunction);
     421    }
     422    // pop last in currenset again
     423    currenttargets.pop_back();
     424  }
    251425}
    252426
  • src/FunctionApproximation/Extractors.hpp

    rdbf8c8 rcaa00e9  
    1414#endif
    1515
     16#include <boost/function.hpp>
     17
    1618#include "Fragmentation/SetValues/Fragment.hpp"
    1719#include "FunctionApproximation/FunctionModel.hpp"
     
    3032  typedef std::map< element_t, count_t> elementcounts_t;
    3133  typedef std::map< element_t, chargeiters_t > elementtargets_t;
     34  typedef std::vector< chargeiters_t > targets_per_combination_t;
    3235
    3336  /** Namespace for some internal helper functions.
     
    117120        const Fragment::charges_t& charges,
    118121        const Fragment::charges_t elements
     122        );
     123
     124    /** Brings all charges together in a map.
     125     *
     126     * @param charges charges as possible keys and their iterators as values in the map
     127     * @param elements list of charges to pick as keys
     128     * @return map of key and a vector of charge iterators
     129     */
     130    elementtargets_t convertChargesToTargetMap(
     131        const Fragment::charges_t& charges,
     132        Fragment::charges_t elements
     133        );
     134
     135    /** Brings combinatorially together desired list of \a charges and \a targets.
     136     *
     137     * @param charges list of desired charges
     138     * @param elementtargets map of available targets per element
     139     * @return vector of chargeiters with all unique combinations
     140     */
     141    targets_per_combination_t
     142    CombineChargesAndTargets(
     143        const Fragment::charges_t& charges,
     144        const elementtargets_t& elementtargets
     145        );
     146
     147    /** Recursive function to pick the next target.
     148     *
     149     * This is used by \sa CombineChargesAndTargets()
     150     *
     151     * @param charges set of charges, reduced by one per recursion
     152     * @param elementtargets targets, map of targets to pick from
     153     * @param currenttargets current set of targets, "global" through recursion
     154     * @param addFunction bound function to add a set when complete
     155     */
     156    void pickLastElementAsTarget(
     157        Fragment::charges_t elements,
     158        elementtargets_t elementtargets,
     159        chargeiters_t& currenttargets,
     160        boost::function<void (const chargeiters_t &currenttargets)> &addFunction
     161        );
     162
     163    /** Converts a list of chargeiters to a list of respective arguments.
     164     *
     165     * @param positions positions from fragment
     166     * @param charges charges associated to each element in \a positions
     167     * @param combinations vector of chargeiters
     168     * \param globalid refers to the index within the global set of configurations
     169     * @return list of arguments
     170     */
     171    FunctionModel::arguments_t
     172    convertTargetsToArguments(
     173        const Fragment::positions_t& positions,
     174        const Fragment::charges_t& charges,
     175        const targets_per_combination_t combinations,
     176        const size_t globalid
    119177        );
    120178  }
     
    199257   * \param charges all nuclei charges
    200258   * \param elements tuple of desired elements
     259   * \param globalid refers to the index within the global set of configurations
    201260   * \return vector of arguments_t containing those matched with elements
    202261   */
     
    208267      );
    209268
     269  /** Gather all combinations of charges as distance arguments from the fragment.
     270   *
     271   * E.g. we have a water fragment, i.e. (8,1,1) and we we want elements (8,1),
     272   * then two arguments are returned, first to second and first to third.
     273   *
     274   * With \sa gatherDistancesFromFragment() only the first distance would be
     275   * returned.
     276   *
     277   * @param positions positions in fragment
     278   * @param charges charges in fragment
     279   * @param elements list of desired elements
     280   * @param globalid some global id to discern training data tuples
     281   * @return list of arguments with distances
     282   */
     283  FunctionModel::arguments_t gatherAllDistancesFromFragment(
     284      const Fragment::positions_t& positions,
     285      const Fragment::charges_t& charges,
     286      const Fragment::charges_t elements,
     287      const size_t globalid
     288      );
     289
    210290  /** Reorder arguments by increasing distance.
    211291   *
Note: See TracChangeset for help on using the changeset viewer.