Changeset 6e5907


Ignore:
Timestamp:
Jul 5, 2017, 7:40:48 PM (8 years ago)
Author:
Frederik Heber <frederik.heber@…>
Branches:
ForceAnnealing_oldresults, IndependentFragmentGrids_IntegrationTest
Children:
89235ea
Parents:
6afd46
git-author:
Frederik Heber <frederik.heber@…> (05/18/17 17:45:47)
git-committer:
Frederik Heber <frederik.heber@…> (07/05/17 19:40:48)
Message:

Extracted extraction (subset of) nodes from BoostGraph into BreadthFirstSearchGatherer.

  • also added helper namespace BoostGraphHelpers.
  • we now treat the vertex indices and vertex names properly. Before that they had to coincide. Now, the name is the atomic id associated with the node and the index is the boost::graph internal index.
Location:
src
Files:
3 added
5 edited

Legend:

Unmodified
Added
Removed
  • src/Actions/MoleculeAction/StretchBondAction.cpp

    r6afd46 r6e5907  
    3333#endif
    3434
    35 #include <boost/graph/adjacency_list.hpp>
    36 #include <boost/graph/breadth_first_search.hpp>
    37 
    3835//#include "CodePatterns/MemDebug.hpp"
    3936
     
    5249#include "Descriptors/AtomIdDescriptor.hpp"
    5350#include "Graph/BoostGraphCreator.hpp"
     51#include "Graph/BoostGraphHelpers.hpp"
     52#include "Graph/BreadthFirstSearchGatherer.hpp"
    5453#include "molecule.hpp"
    5554#include "World.hpp"
     
    6160#include "Action_impl_pre.hpp"
    6261
    63 
    64 /**
    65  * I have no idea why this is so complicated with BGL ...
    66  *
    67  * This is taken from the book "The Boost Graph Library: User Guide and Reference Manual, Portable Documents",
    68  * chapter "Basic Graph Algorithms", example on calculating the bacon number.
    69  */
    70 template <typename DistanceMap>
    71 class distance_recorder : public boost::default_bfs_visitor
    72 {
    73 public:
    74   distance_recorder(DistanceMap dist) : d(dist) {}
    75 
    76   template <typename Edge, typename Graph>
    77   void tree_edge(Edge e, const Graph &g) const {
    78     typename boost::graph_traits<Graph>::vertex_descriptor u = source(e,g), v = target(e,g);
    79     d[v] = d[u] + 1;
    80   }
    81 
    82 private:
    83   DistanceMap d;
    84 };
    85 
    86 template <typename DistanceMap>
    87 distance_recorder<DistanceMap> record_distance(DistanceMap d)
    88 {
    89   return distance_recorder<DistanceMap>(d);
    90 }
    9162
    9263static bool addEdgePredicate(
     
    11081    return Action::failure;
    11182  }
     83  molecule *mol = World::getInstance().
     84      getMolecule(MoleculeById(atoms[0]->getMolecule()->getId()));
     85  if (mol != atoms[1]->getMolecule()) {
     86    STATUS("The two selected atoms must belong to the same molecule.");
     87    return Action::failure;
     88  }
     89
     90  // gather undo information
     91  const double olddistance = atoms[0]->getPosition().distance(atoms[1]->getPosition());
     92  const double newdistance = params.bonddistance.get();
     93  LOG(1, "INFO: Old bond distance is " << olddistance << ", stretching to " << newdistance << ".");
     94
     95  // gather sorted ids
    11296  std::vector<atomId_t> atomids(2);
    11397  atomids[0] = atoms[0]->getId();
     
    11599  std::sort(atomids.begin(), atomids.end());
    116100  LOG(1, "DEBUG: Selected nodes are " << atomids);
    117   molecule *mol = World::getInstance().
    118       getMolecule(MoleculeById(atoms[0]->getMolecule()->getId()));
    119   if (mol != atoms[1]->getMolecule()) {
    120     STATUS("The two selected atoms must belong to the same molecule.");
    121     return Action::failure;
    122   }
    123   // gather undo information
    124   const double olddistance = atoms[0]->getPosition().distance(atoms[1]->getPosition());
    125   const double newdistance = params.bonddistance.get();
    126   LOG(1, "INFO: Old bond distance is " << olddistance << ", stretching to " << newdistance << ".");
     101
     102  const Vector NormalVector = (atoms[0]->getPosition() - atoms[1]->getPosition())* (1./olddistance);
     103  const double shift = 0.5*(newdistance - olddistance);
     104  std::vector<Vector> Shift(2);
     105  Shift[0] = shift * NormalVector;
     106  Shift[1] = -shift * NormalVector;
     107  Box &domain = World::getInstance().getDomain();
    127108
    128109  // Assume the selected bond splits the molecule into two parts, each one on
     
    133114  // leaving the other positions untouched.
    134115
    135   // convert BondGraph into boost::graph
     116  // get nodes on either side of selected bond via BFS discovery
    136117  BoostGraphCreator BGcreator;
    137118  BGcreator.createFromMolecule(*mol,
    138119      boost::bind(addEdgePredicate, _1, boost::ref(atomids)));
    139   const BoostGraphCreator::UndirectedGraph &molgraph = BGcreator.get();
    140 
    141   const size_t num_vertices = BGcreator.getNumVertices();
    142   std::vector< std::vector<size_t> > distances;
    143   for (size_t i=0;i<2;++i) {
    144     distances.push_back(std::vector<size_t>(num_vertices, num_vertices+1)); // set distance to num+1
    145     distances[i][atomids[i]] = 0;
    146     boost::breadth_first_search(
    147         molgraph,
    148         boost::vertex(atomids[i], molgraph),
    149         boost::visitor(record_distance(&(distances[i][0]))));
    150     LOG(3, "DEBUG: From atom #" << atomids[i]
    151         << " BFS discovered the following distances " << distances[i]);
    152   }
    153 
    154   const Vector NormalVector = (atoms[0]->getPosition() - atoms[1]->getPosition())* (1./olddistance);
    155   const double shift = 0.5*(newdistance - olddistance);
    156   std::vector<Vector> Shift(2);
    157   Shift[0] = shift * NormalVector;
    158   Shift[1] = -shift * NormalVector;
    159   Box &domain = World::getInstance().getDomain();
    160   std::vector< std::vector<size_t> > bondside_sets(2);
    161 
    162   // Check whether there are common nodes in each set of distances
    163   for (size_t i=0;i<num_vertices;++i)
    164     if ((distances[0][i] != (num_vertices+1)) && (distances[1][i] != (num_vertices+1))) {
    165       ELOG(2, "Node #" << i << " is reachable from either side of bond, hence must by cyclic."
     120  BreadthFirstSearchGatherer NodeGatherer(BGcreator);
     121  std::vector< BoostGraphHelpers::Nodeset_t > bondside_sets(2);
     122  for(size_t j=0;j<2;++j) {
     123    bondside_sets[j] = NodeGatherer(atoms[j]->getId());
     124    std::sort(bondside_sets[j].begin(), bondside_sets[j].end());
     125  }
     126
     127  // simple test whether bond has split the system in two disjoint sets or not
     128  bool isCyclic = false;
     129  if ((bondside_sets[0].size() + bondside_sets[1].size()) > BGcreator.getNumVertices()) {
     130      // Check whether there are common nodes in each set of distances
     131    if (BoostGraphHelpers::isCommonNodeInVector(bondside_sets[0], bondside_sets[1])) {
     132      ELOG(2, "Sets contain common node, hence bond must have been by cyclic."
    166133          << " Shifting only bond partners.");
    167134      for(size_t j=0;j<2;++j) {
    168         bondside_sets[j].push_back(atoms[j]->getId());
     135        bondside_sets[j].clear();
     136        bondside_sets[j].push_back( atomids[j] );
    169137        const Vector &position = atoms[j]->getPosition();
    170138        atoms[j]->setPosition( domain.enforceBoundaryConditions(position+Shift[j]) );
    171139      }
    172       break;
    173     }
     140      isCyclic = true;
     141    }
     142  }
    174143
    175144  // go through the molecule and stretch each atom in either set of nodes
    176   if (bondside_sets[0].empty()) {
    177     const BoostGraphCreator::index_map_t index_map = BGcreator.getIndexMap();
     145  if (!isCyclic) {
    178146    for (molecule::iterator iter = mol->begin(); iter != mol->end(); ++iter) {
    179147      const Vector &position = (*iter)->getPosition();
    180148      // for each atom determine in which set of nodes it is and shift accordingly
    181       size_t i=0;
    182       const size_t nodeindex = boost::get(index_map, boost::vertex((*iter)->getId(), molgraph));
    183       for (;i<2;++i) {
    184         if (distances[i][nodeindex] != (num_vertices+1)) {
    185           (*iter)->setPosition( domain.enforceBoundaryConditions(position+Shift[i]) );
    186           bondside_sets[i].push_back((*iter)->getId());
    187           break;
    188         }
    189       }
    190       if (i==2) {
     149      const atomId_t &atomid = (*iter)->getId();
     150      if (std::binary_search(bondside_sets[0].begin(), bondside_sets[0].end(), atomid)) {
     151        (*iter)->setPosition( domain.enforceBoundaryConditions(position+Shift[0]) );
     152      } else if (std::binary_search(bondside_sets[1].begin(), bondside_sets[1].end(), atomid)) {
     153        (*iter)->setPosition( domain.enforceBoundaryConditions(position+Shift[1]) );
     154      } else {
    191155        ELOG(1, "Atom " << *iter << " is not contained on either side of bond? Undoing done shifts");
    192156        // Have to undo shifts
    193         for (i=0;i<2;++i) {
    194           for (std::vector<size_t>::const_iterator iter = bondside_sets[i].begin();
     157        for (size_t i=0;i<2;++i) {
     158          for (BoostGraphHelpers::Nodeset_t::const_iterator iter = bondside_sets[i].begin();
    195159              iter != bondside_sets[i].end(); ++iter) {
    196160            atom &walker = *World::getInstance().getAtom(AtomById(*iter));
     
    214178  Box &domain = World::getInstance().getDomain();
    215179  for (size_t i=0;i<2;++i) {
    216     for (std::vector<size_t>::const_iterator iter = state->bondside_sets[i].begin();
     180    for (BoostGraphHelpers::Nodeset_t::const_iterator iter = state->bondside_sets[i].begin();
    217181        iter != state->bondside_sets[i].end(); ++iter) {
    218182      atom &walker = *World::getInstance().getAtom(AtomById(*iter));
     
    230194  Box &domain = World::getInstance().getDomain();
    231195  for (size_t i=0;i<2;++i) {
    232     for (std::vector<size_t>::const_iterator iter = state->bondside_sets[i].begin();
     196    for (BoostGraphHelpers::Nodeset_t::const_iterator iter = state->bondside_sets[i].begin();
    233197        iter != state->bondside_sets[i].end(); ++iter) {
    234198      atom &walker = *World::getInstance().getAtom(AtomById(*iter));
  • src/Actions/MoleculeAction/StretchBondAction.def

    r6afd46 r6e5907  
    2121(RangeValidator< double >(0., 10.))
    2222
    23 #define statetypes (std::vector<Vector>)(std::vector< std::vector<size_t> >)(const molecule *)
     23#define statetypes (std::vector<Vector>)(std::vector< BoostGraphHelpers::Nodeset_t >)(const molecule *)
    2424#define statereferences (Shift)(bondside_sets)(mol)
    2525
  • src/Graph/BoostGraphCreator.cpp

    r6afd46 r6e5907  
    8585      std::back_inserter(atomids), getAtomId);
    8686  ASSERT( _atoms.size() == atomids.size(),
    87       "BoostGraphCreator::createFromAtom() - atomids and atoms differ in size?");
     87      "BoostGraphCreator::createFromAtom() - atomids "
     88      +toString(atomids.size())+" and atoms "+toString(_atoms.size())
     89      +" differ in size?");
    8890  std::sort(atomids.begin(), atomids.end());
    8991  const predicate_t predicate = boost::bind(inSetPredicate, boost::ref(atomids), _1);
     
    9597}
    9698
     99BoostGraphCreator::nodeId_t BoostGraphCreator::getNodeId(
     100    const atomId_t &_atomid) const
     101{
     102  atomids_nodeids_t::const_iterator iter =
     103      atomids_nodeids.find(_atomid);
     104  return (iter == atomids_nodeids.end()) ? (nodeId_t)-1 : iter->second;
     105}
     106
    97107template <typename iterator>
    98108void BoostGraphCreator::createFromRange(
     
    101111    const size_t &_no_nodes,
    102112    const predicate_t &_pred
    103     ) {
    104   // convert BondGraph into boost::graph
    105   UndirectedGraph molgraph(_no_nodes);
     113    )
     114{
     115  graph = UndirectedGraph();
     116
     117  // add vertices
    106118  for(iterator iter = _begin; iter != _end; ++iter) {
    107     LOG(2, "DEBUG: Looking at node " << (*iter)->getId());
     119    const atomId_t atomid = (*iter)->getId();
     120    Vertex v = boost::add_vertex(atomid, graph);
     121    const atomId_t vertexname = boost::get(boost::get(boost::vertex_name, graph), v);
     122    const nodeId_t vertexindex = boost::get(boost::get(boost::vertex_index, graph), v);
     123    LOG(2, "DEBUG: Adding node " << vertexindex << " associated to atom #" << vertexname);
     124    ASSERT( vertexname == atomid,
     125        "BoostGraphCreator::createFromRange() - atomid "+toString(atomid)
     126        +" is not name of vertex "+toString(vertexname)+".");
     127    atomids_nodeids.insert( std::make_pair(vertexname, vertexindex) );
     128  }
     129
     130  // add edges
     131  for(iterator iter = _begin; iter != _end; ++iter) {
     132    LOG(2, "DEBUG: Looking at atom " << (*iter)->getId());
    108133    const BondList& ListOfBonds = (*iter)->getListOfBonds();
    109134    for(BondList::const_iterator bonditer = ListOfBonds.begin();
    110135        bonditer != ListOfBonds.end(); ++bonditer) {
     136      LOG(2, "DEBUG: Looking at bond " << *(*bonditer));
    111137      const atomId_t leftid = (*bonditer)->leftatom->getId();
     138      const nodeId_t leftnodeid = getNodeId(leftid);
    112139      const atomId_t rightid = (*bonditer)->rightatom->getId();
     140      const nodeId_t rightnodeid = getNodeId(rightid);
    113141      // only pick each bond once and evaluate predicate
    114142      if ((leftid == (*iter)->getId())
    115143          && (_pred(**bonditer))) {
    116         LOG(3, "DEBUG: ADDING edge " << leftid << " <-> " << rightid);
    117         boost::add_edge(leftid, rightid, graph);
     144        LOG(3, "DEBUG: ADDING edge " << leftnodeid << " <-> " << rightnodeid);
     145        boost::add_edge(leftnodeid, rightnodeid, graph);
    118146      } else {
    119         LOG(3, "DEBUG: Discarding edge " << leftid << " <-> " << rightid);
     147        LOG(3, "DEBUG: Discarding edge " << leftnodeid << " <-> " << rightnodeid);
    120148      }
    121149    }
  • src/Graph/BoostGraphCreator.hpp

    r6afd46 r6e5907  
    1515#endif
    1616
     17#include <map>
    1718#include <vector>
    1819
    1920#include <boost/function.hpp>
    2021#include <boost/graph/adjacency_list.hpp>
     22
     23#include "types.hpp"
    2124
    2225class atom;
     
    3235  //!> typedef for an undirected graph using boost::graph
    3336  typedef boost::adjacency_list < boost::vecS, boost::vecS, boost::undirectedS,
    34       boost::no_property, boost::no_property > UndirectedGraph;
     37      boost::property<boost::vertex_name_t, atomId_t>, boost::no_property > UndirectedGraph;
    3538  //!> typedef for a map of graph node indices
    36   typedef boost::property_map < boost::adjacency_list <>, boost::vertex_index_t >::type index_map_t;
     39  typedef boost::property_map < UndirectedGraph, boost::vertex_index_t >::type index_map_t;
     40  typedef boost::property_map < UndirectedGraph, boost::vertex_index_t >::const_type const_index_map_t;
     41  //!> typedef for a map of graph node indices
     42  typedef boost::property_map < UndirectedGraph, boost::vertex_name_t >::type name_map_t;
     43  typedef boost::property_map < UndirectedGraph, boost::vertex_name_t >::const_type const_name_map_t;
    3744  //!> typedef for the  predicate to evaluate for adding the current edge or not
    3845  typedef boost::function<bool (const bond &)> predicate_t;
     46  //!> typedef for a Vertex
     47  typedef boost::graph_traits<UndirectedGraph>::vertex_descriptor Vertex;
     48  //!> typedef for vertex iterator
     49  typedef boost::graph_traits<UndirectedGraph>::vertex_iterator vertex_iter;
    3950
     51  //!> typedef for a node id
     52  typedef size_t nodeId_t;
     53  //!> typedef for map converting between node id in graph and the associated atomic id
     54  typedef std::map<atomId_t, nodeId_t> atomids_nodeids_t;
    4055
    4156  /** Creates the boost::graph using all atoms and bonds in the given \a _mol.
     
    89104  }
    90105
     106  /** Returns the node id to a given atom id \a _atomid.
     107   *
     108   * \param _atomid atom id
     109   * \return node id
     110   */
     111  nodeId_t getNodeId(const atomId_t &_atomid) const;
     112
    91113private:
    92114  /** General purpose function that contains the internal logic of walking the
     
    114136  //!> internal graph that is created by creator functions
    115137  UndirectedGraph graph;
     138  //!> external property map for all the atomic ids of each graph node
     139  atomids_nodeids_t atomids_nodeids;
    116140};
    117141
  • src/Graph/Makefile.am

    r6afd46 r6e5907  
    33
    44GRAPHSOURCE = \
     5        Graph/AdjacencyList.cpp \
    56        Graph/BondGraph.cpp \
    67        Graph/BoostGraphCreator.cpp \
     8        Graph/BreadthFirstSearchGatherer.cpp \
    79        Graph/BuildInducedSubgraph.cpp \
    8         Graph/AdjacencyList.cpp \
    910        Graph/ConnectedSubgraph.cpp \
    1011        Graph/CyclicStructureAnalysis.cpp \
     
    1213                                 
    1314GRAPHHEADER = \
     15        Graph/AdjacencyList.hpp \
    1416        Graph/BondGraph.hpp \
    1517        Graph/BoostGraphCreator.hpp \
     18        Graph/BoostGraphHelpers.hpp \
     19        Graph/BreadthFirstSearchGatherer.hpp \
    1620        Graph/BuildInducedSubgraph.hpp \
    17         Graph/AdjacencyList.hpp \
    1821        Graph/ConnectedSubgraph.hpp \
    1922        Graph/CyclicStructureAnalysis.hpp \
Note: See TracChangeset for help on using the changeset viewer.