Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/molecule_graph.cpp

    rf66195 r99593f  
    88#include "atom.hpp"
    99#include "bond.hpp"
     10#include "bondgraph.hpp"
    1011#include "config.hpp"
    1112#include "element.hpp"
    1213#include "helpers.hpp"
     14#include "linkedcell.hpp"
    1315#include "lists.hpp"
    1416#include "memoryallocator.hpp"
    1517#include "molecule.hpp"
    1618
     19struct BFSAccounting
     20{
     21  atom **PredecessorList;
     22  int *ShortestPathList;
     23  enum Shading *ColorList;
     24  class StackClass<atom *> *BFSStack;
     25  class StackClass<atom *> *TouchedStack;
     26  int AtomCount;
     27  int BondOrder;
     28  atom *Root;
     29  bool BackStepping;
     30  int CurrentGraphNr;
     31  int ComponentNr;
     32};
     33
     34/** Accounting data for Depth First Search.
     35 */
     36struct DFSAccounting
     37{
     38  class StackClass<atom *> *AtomStack;
     39  class StackClass<bond *> *BackEdgeStack;
     40  int CurrentGraphNr;
     41  int ComponentNumber;
     42  atom *Root;
     43  bool BackStepping;
     44};
     45
    1746/************************************* Functions for class molecule *********************************/
    18 
    1947
    2048/** Creates an adjacency list of the molecule.
    2149 * We obtain an outside file with the indices of atoms which are bondmembers.
    2250 */
    23 void molecule::CreateAdjacencyList2(ofstream *out, ifstream *input)
     51void molecule::CreateAdjacencyListFromDbondFile(ofstream *out, ifstream *input)
    2452{
    2553
    2654  // 1 We will parse bonds out of the dbond file created by tremolo.
    27       int atom1, atom2, temp;
    28       atom *Walker, *OtherWalker;
    29 
    30           if (!input)
    31           {
    32             cout << Verbose(1) << "Opening silica failed \n";
    33           };
    34 
    35       *input >> ws >> atom1;
    36       *input >> ws >> atom2;
    37           cout << Verbose(1) << "Scanning file\n";
    38           while (!input->eof()) // Check whether we read everything already
    39           {
    40         *input >> ws >> atom1;
    41         *input >> ws >> atom2;
    42             if(atom2<atom1) //Sort indices of atoms in order
    43             {
    44               temp=atom1;
    45               atom1=atom2;
    46               atom2=temp;
    47             };
    48 
    49             Walker=start;
    50             while(Walker-> nr != atom1) // Find atom corresponding to first index
    51             {
    52               Walker = Walker->next;
    53             };
    54             OtherWalker = Walker->next;
    55             while(OtherWalker->nr != atom2) // Find atom corresponding to second index
    56             {
    57               OtherWalker= OtherWalker->next;
    58             };
    59             AddBond(Walker, OtherWalker); //Add the bond between the two atoms with respective indices.
    60 
    61           }
    62 
    63           CreateListOfBondsPerAtom(out);
    64 
    65 };
    66 
     55  int atom1, atom2;
     56  atom *Walker, *OtherWalker;
     57
     58  if (!input) {
     59    cout << Verbose(1) << "Opening silica failed \n";
     60  };
     61
     62  *input >> ws >> atom1;
     63  *input >> ws >> atom2;
     64  cout << Verbose(1) << "Scanning file\n";
     65  while (!input->eof()) // Check whether we read everything already
     66  {
     67    *input >> ws >> atom1;
     68    *input >> ws >> atom2;
     69
     70    if (atom2 < atom1) //Sort indices of atoms in order
     71      flip(atom1, atom2);
     72    Walker = FindAtom(atom1);
     73    OtherWalker = FindAtom(atom2);
     74    AddBond(Walker, OtherWalker); //Add the bond between the two atoms with respective indices.
     75  }
     76}
     77;
    6778
    6879/** Creates an adjacency list of the molecule.
     
    7788 *  -# put each atom into its corresponding cell
    7889 *  -# go through every cell, check the atoms therein against all possible bond partners in the 27 adjacent cells, add bond if true
    79  *  -# create the list of bonds via CreateListOfBondsPerAtom()
    8090 *  -# correct the bond degree iteratively (single->double->triple bond)
    8191 *  -# finally print the bond list to \a *out if desired
     
    8393 * \param bonddistance length of linked cells (i.e. maximum minimal length checked)
    8494 * \param IsAngstroem whether coordinate system is gauged to Angstroem or Bohr radii
    85  */
    86 void molecule::CreateAdjacencyList(ofstream *out, double bonddistance, bool IsAngstroem)
    87 {
    88 
    89   atom *Walker = NULL, *OtherWalker = NULL, *Candidate = NULL;
    90   int No, NoBonds, CandidateBondNo;
    91   int NumberCells, divisor[NDIM], n[NDIM], N[NDIM], index, Index, j;
    92   molecule **CellList;
    93   double distance, MinDistance, MaxDistance;
    94   double *matrix = ReturnFullMatrixforSymmetric(cell_size);
    95   Vector x;
    96   int FalseBondDegree = 0;
     95 * \param *minmaxdistance function to give upper and lower bound on whether particle is bonded to some other
     96 * \param *BG BondGraph with the member function above or NULL, if just standard covalent should be used.
     97 */
     98void molecule::CreateAdjacencyList(ofstream *out, double bonddistance, bool IsAngstroem, void (BondGraph::*minmaxdistance)(BondedParticle * const , BondedParticle * const , double &, double &, bool), BondGraph *BG)
     99{
     100  atom *Walker = NULL;
     101  atom *OtherWalker = NULL;
     102  atom **AtomMap = NULL;
     103  int n[NDIM];
     104  double MinDistance, MaxDistance;
     105  LinkedCell *LC = NULL;
     106  bool free_BG = false;
     107
     108  if (BG == NULL) {
     109    BG = new BondGraph(IsAngstroem);
     110    free_BG = true;
     111  }
    97112
    98113  BondDistance = bonddistance; // * ((IsAngstroem) ? 1. : 1./AtomicLengthToAngstroem);
    99114  *out << Verbose(0) << "Begin of CreateAdjacencyList." << endl;
    100115  // remove every bond from the list
    101   if ((first->next != last) && (last->previous != first)) {  // there are bonds present
    102     cleanup(first,last);
    103   }
     116  bond *Binder = NULL;
     117  while (last->previous != first) {
     118    Binder = last->previous;
     119    Binder->leftatom->UnregisterBond(Binder);
     120    Binder->rightatom->UnregisterBond(Binder);
     121    removewithoutcheck(Binder);
     122  }
     123  BondCount = 0;
    104124
    105125  // count atoms in molecule = dimension of matrix (also give each unique name and continuous numbering)
    106126  CountAtoms(out);
    107   *out << Verbose(1) << "AtomCount " << AtomCount << "." << endl;
    108 
    109   if (AtomCount != 0) {
    110     // 1. find divisor for each axis, such that a sphere with radius of at least bonddistance can be placed into each cell
    111     j=-1;
    112     for (int i=0;i<NDIM;i++) {
    113       j += i+1;
    114       divisor[i] = (int)floor(cell_size[j]/bonddistance); // take smaller value such that size of linked cell is at least bonddistance
    115       //*out << Verbose(1) << "divisor[" << i << "]  = " << divisor[i] << "." << endl;
    116     }
    117     // 2a. allocate memory for the cell list
    118     NumberCells = divisor[0]*divisor[1]*divisor[2];
    119     *out << Verbose(1) << "Allocating " << NumberCells << " cells." << endl;
    120     CellList = Malloc<molecule*>(NumberCells, "molecule::CreateAdjacencyList - ** CellList");
    121     for (int i=NumberCells;i--;)
    122       CellList[i] = NULL;
    123 
    124     // 2b. put all atoms into its corresponding list
     127  *out << Verbose(1) << "AtomCount " << AtomCount << " and bonddistance is " << bonddistance << "." << endl;
     128
     129  if ((AtomCount > 1) && (bonddistance > 1.)) {
     130    *out << Verbose(2) << "Creating Linked Cell structure ... " << endl;
     131    LC = new LinkedCell(this, bonddistance);
     132
     133    // create a list to map Tesselpoint::nr to atom *
     134    *out << Verbose(2) << "Creating TesselPoint to atom map ... " << endl;
     135    AtomMap = Calloc<atom *> (AtomCount, "molecule::CreateAdjacencyList - **AtomCount");
    125136    Walker = start;
    126     while(Walker->next != end) {
     137    while (Walker->next != end) {
    127138      Walker = Walker->next;
    128       //*out << Verbose(1) << "Current atom is " << *Walker << " with coordinates ";
    129       //Walker->x.Output(out);
    130       //*out << "." << endl;
    131       // compute the cell by the atom's coordinates
    132       j=-1;
    133       for (int i=0;i<NDIM;i++) {
    134         j += i+1;
    135         x.CopyVector(&(Walker->x));
    136         x.KeepPeriodic(out, matrix);
    137         n[i] = (int)floor(x.x[i]/cell_size[j]*(double)divisor[i]);
    138       }
    139       index = n[2] + (n[1] + n[0] * divisor[1]) * divisor[2];
    140       //*out << Verbose(1) << "Atom " << *Walker << " goes into cell number [" << n[0] << "," << n[1] << "," << n[2] << "] = " << index << "." << endl;
    141       // add copy atom to this cell
    142       if (CellList[index] == NULL)  // allocate molecule if not done
    143         CellList[index] = new molecule(elemente);
    144       OtherWalker = CellList[index]->AddCopyAtom(Walker); // add a copy of walker to this atom, father will be walker for later reference
    145       //*out << Verbose(1) << "Copy Atom is " << *OtherWalker << "." << endl;
    146     }
    147     //for (int i=0;i<NumberCells;i++)
    148       //*out << Verbose(1) << "Cell number " << i << ": " << CellList[i] << "." << endl;
    149 
     139      AtomMap[Walker->nr] = Walker;
     140    }
    150141
    151142    // 3a. go through every cell
    152     for (N[0]=divisor[0];N[0]--;)
    153       for (N[1]=divisor[1];N[1]--;)
    154         for (N[2]=divisor[2];N[2]--;) {
    155           Index = N[2] + (N[1] + N[0] * divisor[1]) * divisor[2];
    156           if (CellList[Index] != NULL) { // if there atoms in this cell
    157             //*out << Verbose(1) << "Current cell is " << Index << "." << endl;
    158             // 3b. for every atom therein
    159             Walker = CellList[Index]->start;
    160             while (Walker->next != CellList[Index]->end) {  // go through every atom
    161               Walker = Walker->next;
     143    *out << Verbose(2) << "Celling ... " << endl;
     144    for (LC->n[0] = 0; LC->n[0] < LC->N[0]; LC->n[0]++)
     145      for (LC->n[1] = 0; LC->n[1] < LC->N[1]; LC->n[1]++)
     146        for (LC->n[2] = 0; LC->n[2] < LC->N[2]; LC->n[2]++) {
     147          const LinkedNodes *List = LC->GetCurrentCell();
     148          //*out << Verbose(2) << "Current cell is " << LC->n[0] << ", " << LC->n[1] << ", " << LC->n[2] << " with No. " << LC->index << " containing " << List->size() << " points." << endl;
     149          if (List != NULL) {
     150            for (LinkedNodes::const_iterator Runner = List->begin(); Runner != List->end(); Runner++) {
     151              Walker = AtomMap[(*Runner)->nr];
    162152              //*out << Verbose(0) << "Current Atom is " << *Walker << "." << endl;
    163153              // 3c. check for possible bond between each atom in this and every one in the 27 cells
    164               for (n[0]=-1;n[0]<=1;n[0]++)
    165                 for (n[1]=-1;n[1]<=1;n[1]++)
    166                   for (n[2]=-1;n[2]<=1;n[2]++) {
    167                      // compute the index of this comparison cell and make it periodic
    168                     index = ((N[2]+n[2]+divisor[2])%divisor[2]) + (((N[1]+n[1]+divisor[1])%divisor[1]) + ((N[0]+n[0]+divisor[0])%divisor[0]) * divisor[1]) * divisor[2];
    169                     //*out << Verbose(1) << "Number of comparison cell is " << index << "." << endl;
    170                     if (CellList[index] != NULL) {  // if there are any atoms in this cell
    171                       OtherWalker = CellList[index]->start;
    172                       while(OtherWalker->next != CellList[index]->end) {  // go through every atom in this cell
    173                         OtherWalker = OtherWalker->next;
    174                         //*out << Verbose(0) << "Current comparison atom is " << *OtherWalker << "." << endl;
    175                         /// \todo periodic check is missing here!
    176                         //*out << Verbose(1) << "Checking distance " << OtherWalker->x.PeriodicDistanceSquared(&(Walker->x), cell_size) << " against typical bond length of " << bonddistance*bonddistance << "." << endl;
    177                         MinDistance = OtherWalker->type->CovalentRadius + Walker->type->CovalentRadius;
    178                         MinDistance *= (IsAngstroem) ? 1. : 1./AtomicLengthToAngstroem;
    179                         MaxDistance = MinDistance + BONDTHRESHOLD;
    180                         MinDistance -= BONDTHRESHOLD;
    181                         distance = OtherWalker->x.PeriodicDistanceSquared(&(Walker->x), cell_size);
    182                         if ((OtherWalker->father->nr > Walker->father->nr) && (distance <= MaxDistance*MaxDistance) && (distance >= MinDistance*MinDistance)) { // create bond if distance is smaller
    183                           //*out << Verbose(1) << "Adding Bond between " << *Walker << " and " << *OtherWalker << " in distance " << sqrt(distance) << "." << endl;
    184                           AddBond(Walker->father, OtherWalker->father, 1);  // also increases molecule::BondCount
    185                         } else {
    186                           //*out << Verbose(1) << "Not Adding: Wrong label order or distance too great." << endl;
     154              for (n[0] = -1; n[0] <= 1; n[0]++)
     155                for (n[1] = -1; n[1] <= 1; n[1]++)
     156                  for (n[2] = -1; n[2] <= 1; n[2]++) {
     157                    const LinkedNodes *OtherList = LC->GetRelativeToCurrentCell(n);
     158                    //*out << Verbose(2) << "Current relative cell is " << LC->n[0] << ", " << LC->n[1] << ", " << LC->n[2] << " with No. " << LC->index << " containing " << List->size() << " points." << endl;
     159                    if (OtherList != NULL) {
     160                      for (LinkedNodes::const_iterator OtherRunner = OtherList->begin(); OtherRunner != OtherList->end(); OtherRunner++) {
     161                        if ((*OtherRunner)->nr > Walker->nr) {
     162                          OtherWalker = AtomMap[(*OtherRunner)->nr];
     163                          //*out << Verbose(1) << "Checking distance " << OtherWalker->x.PeriodicDistanceSquared(&(Walker->x), cell_size) << " against typical bond length of " << bonddistance*bonddistance << "." << endl;
     164                          (BG->*minmaxdistance)(Walker, OtherWalker, MinDistance, MaxDistance, IsAngstroem);
     165                          const double distance = OtherWalker->x.PeriodicDistanceSquared(&(Walker->x), cell_size);
     166                          const bool status = (distance <= MaxDistance * MaxDistance) && (distance >= MinDistance * MinDistance);
     167                          if ((OtherWalker->father->nr > Walker->father->nr) && (status)) { // create bond if distance is smaller
     168                            //*out << Verbose(1) << "Adding Bond between " << *Walker << " and " << *OtherWalker << " in distance " << sqrt(distance) << "." << endl;
     169                            AddBond(Walker->father, OtherWalker->father, 1); // also increases molecule::BondCount
     170                          } else {
     171                            //*out << Verbose(1) << "Not Adding: Wrong label order or distance too great." << endl;
     172                          }
    187173                        }
    188174                      }
     
    192178          }
    193179        }
    194 
    195 
    196 
    197     // 4. free the cell again
    198     for (int i=NumberCells;i--;)
    199       if (CellList[i] != NULL) {
    200         delete(CellList[i]);
    201       }
    202     Free(&CellList);
    203 
    204     // create the adjacency list per atom
    205     CreateListOfBondsPerAtom(out);
    206 
    207     // correct Bond degree of each bond by checking both bond partners for a mismatch between valence and current sum of bond degrees,
    208     // iteratively increase the one first where the other bond partner has the fewest number of bonds (i.e. in general bonds oxygene
    209     // preferred over carbon bonds). Beforehand, we had picked the first mismatching partner, which lead to oxygenes with single instead of
    210     // double bonds as was expected.
    211     if (BondCount != 0) {
    212       NoCyclicBonds = 0;
    213       *out << Verbose(1) << "Correcting Bond degree of each bond ... ";
    214       do {
    215         No = 0; // No acts as breakup flag (if 1 we still continue)
    216         Walker = start;
    217         while (Walker->next != end) { // go through every atom
    218           Walker = Walker->next;
    219           // count valence of first partner
    220           NoBonds = 0;
    221           for(j=0;j<NumberOfBondsPerAtom[Walker->nr];j++)
    222             NoBonds += ListOfBondsPerAtom[Walker->nr][j]->BondDegree;
    223           *out << Verbose(3) << "Walker " << *Walker << ": " << (int)Walker->type->NoValenceOrbitals << " > " << NoBonds << "?" << endl;
    224           if ((int)(Walker->type->NoValenceOrbitals) > NoBonds) { // we have a mismatch, check all bonding partners for mismatch
    225             Candidate = NULL;
    226             CandidateBondNo = -1;
    227             for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { // go through each of its bond partners
    228               OtherWalker = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker);
    229               // count valence of second partner
    230               NoBonds = 0;
    231               for(j=0;j<NumberOfBondsPerAtom[OtherWalker->nr];j++)
    232                 NoBonds += ListOfBondsPerAtom[OtherWalker->nr][j]->BondDegree;
    233               *out << Verbose(3) << "OtherWalker " << *OtherWalker << ": " << (int)OtherWalker->type->NoValenceOrbitals << " > " << NoBonds << "?" << endl;
    234               if ((int)(OtherWalker->type->NoValenceOrbitals) > NoBonds) { // check if possible candidate
    235                 if ((Candidate == NULL) || (NumberOfBondsPerAtom[Candidate->nr] > NumberOfBondsPerAtom[OtherWalker->nr])) { // pick the one with fewer number of bonds first
    236                   Candidate = OtherWalker;
    237                   CandidateBondNo = i;
    238                   *out << Verbose(3) << "New candidate is " << *Candidate << "." << endl;
    239                 }
    240               }
    241             }
    242             if ((Candidate != NULL) && (CandidateBondNo != -1)) {
    243               ListOfBondsPerAtom[Walker->nr][CandidateBondNo]->BondDegree++;
    244               *out << Verbose(2) << "Increased bond degree for bond " << *ListOfBondsPerAtom[Walker->nr][CandidateBondNo] << "." << endl;
    245             } else
    246               *out << Verbose(2) << "Could not find correct degree for atom " << *Walker << "." << endl;
    247               FalseBondDegree++;
    248           }
    249         }
    250       } while (No);
    251     *out << " done." << endl;
    252     } else
    253       *out << Verbose(1) << "BondCount is " << BondCount << ", no bonds between any of the " << AtomCount << " atoms." << endl;
    254     *out << Verbose(1) << "I detected " << BondCount << " bonds in the molecule with distance " << bonddistance << ", " << FalseBondDegree << " bonds could not be corrected." << endl;
     180    Free(&AtomMap);
     181    delete (LC);
     182    *out << Verbose(1) << "I detected " << BondCount << " bonds in the molecule with distance " << BondDistance << "." << endl;
     183
     184    // correct bond degree by comparing valence and bond degree
     185    *out << Verbose(2) << "Correcting bond degree ... " << endl;
     186    CorrectBondDegree(out);
    255187
    256188    // output bonds for debugging (if bond chain list was correctly installed)
    257     *out << Verbose(1) << endl << "From contents of bond chain list:";
    258     bond *Binder = first;
    259     while(Binder->next != last) {
    260       Binder = Binder->next;
    261       *out << *Binder << "\t" << endl;
    262     }
    263     *out << endl;
     189    ActOnAllAtoms(&atom::OutputBondOfAtom, out);
    264190  } else
    265191    *out << Verbose(1) << "AtomCount is " << AtomCount << ", thus no bonds, no connections!." << endl;
    266192  *out << Verbose(0) << "End of CreateAdjacencyList." << endl;
    267   Free(&matrix);
    268 
    269 };
     193  if (free_BG)
     194    delete(BG);
     195}
     196;
     197
     198/** Prints a list of all bonds to \a *out.
     199 * \param output stream
     200 */
     201void molecule::OutputBondsList(ofstream *out) const
     202{
     203  *out << Verbose(1) << endl << "From contents of bond chain list:";
     204  bond *Binder = first;
     205  while (Binder->next != last) {
     206    Binder = Binder->next;
     207    *out << *Binder << "\t" << endl;
     208  }
     209  *out << endl;
     210}
     211;
     212
     213/** correct bond degree by comparing valence and bond degree.
     214 * correct Bond degree of each bond by checking both bond partners for a mismatch between valence and current sum of bond degrees,
     215 * iteratively increase the one first where the other bond partner has the fewest number of bonds (i.e. in general bonds oxygene
     216 * preferred over carbon bonds). Beforehand, we had picked the first mismatching partner, which lead to oxygenes with single instead of
     217 * double bonds as was expected.
     218 * \param *out output stream for debugging
     219 * \return number of bonds that could not be corrected
     220 */
     221int molecule::CorrectBondDegree(ofstream *out) const
     222{
     223  int No = 0, OldNo = -1;
     224
     225  if (BondCount != 0) {
     226    *out << Verbose(1) << "Correcting Bond degree of each bond ... " << endl;
     227    do {
     228      OldNo = No;
     229      No = SumPerAtom(&atom::CorrectBondDegree, out);
     230    } while (OldNo != No);
     231    *out << " done." << endl;
     232  } else {
     233    *out << Verbose(1) << "BondCount is " << BondCount << ", no bonds between any of the " << AtomCount << " atoms." << endl;
     234  }
     235  *out << No << " bonds could not be corrected." << endl;
     236
     237  return (No);
     238}
     239;
    270240
    271241/** Counts all cyclic bonds and returns their number.
     
    276246int molecule::CountCyclicBonds(ofstream *out)
    277247{
    278   int No = 0;
     248  NoCyclicBonds = 0;
    279249  int *MinimumRingSize = NULL;
    280250  MoleculeLeafClass *Subgraphs = NULL;
     
    286256    while (Subgraphs->next != NULL) {
    287257      Subgraphs = Subgraphs->next;
    288       delete(Subgraphs->previous);
    289     }
    290     delete(Subgraphs);
    291     delete[](MinimumRingSize);
    292   }
    293   while(Binder->next != last) {
     258      delete (Subgraphs->previous);
     259    }
     260    delete (Subgraphs);
     261    delete[] (MinimumRingSize);
     262  }
     263  while (Binder->next != last) {
    294264    Binder = Binder->next;
    295265    if (Binder->Cyclic)
    296       No++;
    297   }
    298   delete(BackEdgeStack);
    299   return No;
    300 };
     266      NoCyclicBonds++;
     267  }
     268  delete (BackEdgeStack);
     269  return NoCyclicBonds;
     270}
     271;
     272
    301273/** Returns Shading as a char string.
    302274 * \param color the Shading
    303275 * \return string of the flag
    304276 */
    305 string molecule::GetColor(enum Shading color)
    306 {
    307   switch(color) {
     277string molecule::GetColor(enum Shading color) const
     278{
     279  switch (color) {
    308280    case white:
    309281      return "white";
     
    322294      break;
    323295  };
    324 };
     296}
     297;
     298
     299/** Sets atom::GraphNr and atom::LowpointNr to BFSAccounting::CurrentGraphNr.
     300 * \param *out output stream for debugging
     301 * \param *Walker current node
     302 * \param &BFS structure with accounting data for BFS
     303 */
     304void DepthFirstSearchAnalysis_SetWalkersGraphNr(ofstream *out, atom *&Walker, struct DFSAccounting &DFS)
     305{
     306  if (!DFS.BackStepping) { // if we don't just return from (8)
     307    Walker->GraphNr = DFS.CurrentGraphNr;
     308    Walker->LowpointNr = DFS.CurrentGraphNr;
     309    *out << Verbose(1) << "Setting Walker[" << Walker->Name << "]'s number to " << Walker->GraphNr << " with Lowpoint " << Walker->LowpointNr << "." << endl;
     310    DFS.AtomStack->Push(Walker);
     311    DFS.CurrentGraphNr++;
     312  }
     313}
     314;
     315
     316/** During DFS goes along unvisited bond and touches other atom.
     317 * Sets bond::type, if
     318 *  -# BackEdge: set atom::LowpointNr and push on \a BackEdgeStack
     319 *  -# TreeEgde: set atom::Ancestor and continue with Walker along this edge
     320 * Continue until molecule::FindNextUnused() finds no more unused bonds.
     321 * \param *out output stream for debugging
     322 * \param *mol molecule with atoms and finding unused bonds
     323 * \param *&Binder current edge
     324 * \param &DFS DFS accounting data
     325 */
     326void DepthFirstSearchAnalysis_ProbeAlongUnusedBond(ofstream *out, const molecule * const mol, atom *&Walker, bond *&Binder, struct DFSAccounting &DFS)
     327{
     328  atom *OtherAtom = NULL;
     329
     330  do { // (3) if Walker has no unused egdes, go to (5)
     331    DFS.BackStepping = false; // reset backstepping flag for (8)
     332    if (Binder == NULL) // if we don't just return from (11), Binder is already set to next unused
     333      Binder = mol->FindNextUnused(Walker);
     334    if (Binder == NULL)
     335      break;
     336    *out << Verbose(2) << "Current Unused Bond is " << *Binder << "." << endl;
     337    // (4) Mark Binder used, ...
     338    Binder->MarkUsed(black);
     339    OtherAtom = Binder->GetOtherAtom(Walker);
     340    *out << Verbose(2) << "(4) OtherAtom is " << OtherAtom->Name << "." << endl;
     341    if (OtherAtom->GraphNr != -1) {
     342      // (4a) ... if "other" atom has been visited (GraphNr != 0), set lowpoint to minimum of both, go to (3)
     343      Binder->Type = BackEdge;
     344      DFS.BackEdgeStack->Push(Binder);
     345      Walker->LowpointNr = (Walker->LowpointNr < OtherAtom->GraphNr) ? Walker->LowpointNr : OtherAtom->GraphNr;
     346      *out << Verbose(3) << "(4a) Visited: Setting Lowpoint of Walker[" << Walker->Name << "] to " << Walker->LowpointNr << "." << endl;
     347    } else {
     348      // (4b) ... otherwise set OtherAtom as Ancestor of Walker and Walker as OtherAtom, go to (2)
     349      Binder->Type = TreeEdge;
     350      OtherAtom->Ancestor = Walker;
     351      Walker = OtherAtom;
     352      *out << Verbose(3) << "(4b) Not Visited: OtherAtom[" << OtherAtom->Name << "]'s Ancestor is now " << OtherAtom->Ancestor->Name << ", Walker is OtherAtom " << OtherAtom->Name << "." << endl;
     353      break;
     354    }
     355    Binder = NULL;
     356  } while (1); // (3)
     357}
     358;
     359
     360/** Checks whether we have a new component.
     361 * if atom::LowpointNr of \a *&Walker is greater than atom::GraphNr of its atom::Ancestor, we have a new component.
     362 * Meaning that if we touch upon a node who suddenly has a smaller atom::LowpointNr than its ancestor, then we
     363 * have a found a new branch in the graph tree.
     364 * \param *out output stream for debugging
     365 * \param *mol molecule with atoms and finding unused bonds
     366 * \param *&Walker current node
     367 * \param &DFS DFS accounting data
     368 */
     369void DepthFirstSearchAnalysis_CheckForaNewComponent(ofstream *out, const molecule * const mol, atom *&Walker, struct DFSAccounting &DFS, MoleculeLeafClass *&LeafWalker)
     370{
     371  atom *OtherAtom = NULL;
     372
     373  // (5) if Ancestor of Walker is ...
     374  *out << Verbose(1) << "(5) Number of Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "] is " << Walker->Ancestor->GraphNr << "." << endl;
     375
     376  if (Walker->Ancestor->GraphNr != DFS.Root->GraphNr) {
     377    // (6)  (Ancestor of Walker is not Root)
     378    if (Walker->LowpointNr < Walker->Ancestor->GraphNr) {
     379      // (6a) set Ancestor's Lowpoint number to minimum of of its Ancestor and itself, go to Step(8)
     380      Walker->Ancestor->LowpointNr = (Walker->Ancestor->LowpointNr < Walker->LowpointNr) ? Walker->Ancestor->LowpointNr : Walker->LowpointNr;
     381      *out << Verbose(2) << "(6) Setting Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "]'s Lowpoint to " << Walker->Ancestor->LowpointNr << "." << endl;
     382    } else {
     383      // (7) (Ancestor of Walker is a separating vertex, remove all from stack till Walker (including), these and Ancestor form a component
     384      Walker->Ancestor->SeparationVertex = true;
     385      *out << Verbose(2) << "(7) Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "]'s is a separating vertex, creating component." << endl;
     386      mol->SetNextComponentNumber(Walker->Ancestor, DFS.ComponentNumber);
     387      *out << Verbose(3) << "(7) Walker[" << Walker->Name << "]'s Ancestor's Compont is " << DFS.ComponentNumber << "." << endl;
     388      mol->SetNextComponentNumber(Walker, DFS.ComponentNumber);
     389      *out << Verbose(3) << "(7) Walker[" << Walker->Name << "]'s Compont is " << DFS.ComponentNumber << "." << endl;
     390      do {
     391        OtherAtom = DFS.AtomStack->PopLast();
     392        LeafWalker->Leaf->AddCopyAtom(OtherAtom);
     393        mol->SetNextComponentNumber(OtherAtom, DFS.ComponentNumber);
     394        *out << Verbose(3) << "(7) Other[" << OtherAtom->Name << "]'s Compont is " << DFS.ComponentNumber << "." << endl;
     395      } while (OtherAtom != Walker);
     396      DFS.ComponentNumber++;
     397    }
     398    // (8) Walker becomes its Ancestor, go to (3)
     399    *out << Verbose(2) << "(8) Walker[" << Walker->Name << "] is now its Ancestor " << Walker->Ancestor->Name << ", backstepping. " << endl;
     400    Walker = Walker->Ancestor;
     401    DFS.BackStepping = true;
     402  }
     403}
     404;
     405
     406/** Cleans the root stack when we have found a component.
     407 * If we are not DFSAccounting::BackStepping, then we clear the root stack by putting everything into a
     408 * component down till we meet DFSAccounting::Root.
     409 * \param *out output stream for debugging
     410 * \param *mol molecule with atoms and finding unused bonds
     411 * \param *&Walker current node
     412 * \param *&Binder current edge
     413 * \param &DFS DFS accounting data
     414 */
     415void DepthFirstSearchAnalysis_CleanRootStackDownTillWalker(ofstream *out, const molecule * const mol, atom *&Walker, bond *&Binder, struct DFSAccounting &DFS, MoleculeLeafClass *&LeafWalker)
     416{
     417  atom *OtherAtom = NULL;
     418
     419  if (!DFS.BackStepping) { // coming from (8) want to go to (3)
     420    // (9) remove all from stack till Walker (including), these and Root form a component
     421    //DFS.AtomStack->Output(out);
     422    mol->SetNextComponentNumber(DFS.Root, DFS.ComponentNumber);
     423    *out << Verbose(3) << "(9) Root[" << DFS.Root->Name << "]'s Component is " << DFS.ComponentNumber << "." << endl;
     424    mol->SetNextComponentNumber(Walker, DFS.ComponentNumber);
     425    *out << Verbose(3) << "(9) Walker[" << Walker->Name << "]'s Component is " << DFS.ComponentNumber << "." << endl;
     426    do {
     427      OtherAtom = DFS.AtomStack->PopLast();
     428      LeafWalker->Leaf->AddCopyAtom(OtherAtom);
     429      mol->SetNextComponentNumber(OtherAtom, DFS.ComponentNumber);
     430      *out << Verbose(3) << "(7) Other[" << OtherAtom->Name << "]'s Compont is " << DFS.ComponentNumber << "." << endl;
     431    } while (OtherAtom != Walker);
     432    DFS.ComponentNumber++;
     433
     434    // (11) Root is separation vertex,  set Walker to Root and go to (4)
     435    Walker = DFS.Root;
     436    Binder = mol->FindNextUnused(Walker);
     437    *out << Verbose(1) << "(10) Walker is Root[" << DFS.Root->Name << "], next Unused Bond is " << Binder << "." << endl;
     438    if (Binder != NULL) { // Root is separation vertex
     439      *out << Verbose(1) << "(11) Root is a separation vertex." << endl;
     440      Walker->SeparationVertex = true;
     441    }
     442  }
     443}
     444;
     445
     446/** Initializes DFSAccounting structure.
     447 * \param *out output stream for debugging
     448 * \param &DFS accounting structure to allocate
     449 * \param *mol molecule with AtomCount, BondCount and all atoms
     450 */
     451void DepthFirstSearchAnalysis_Init(ofstream *out, struct DFSAccounting &DFS, const molecule * const mol)
     452{
     453  DFS.AtomStack = new StackClass<atom *> (mol->AtomCount);
     454  DFS.CurrentGraphNr = 0;
     455  DFS.ComponentNumber = 0;
     456  DFS.BackStepping = false;
     457  mol->ResetAllBondsToUnused();
     458  mol->SetAtomValueToValue(-1, &atom::GraphNr);
     459  mol->ActOnAllAtoms(&atom::InitComponentNr);
     460  DFS.BackEdgeStack->ClearStack();
     461}
     462;
     463
     464/** Free's DFSAccounting structure.
     465 * \param *out output stream for debugging
     466 * \param &DFS accounting structure to free
     467 */
     468void DepthFirstSearchAnalysis_Finalize(ofstream *out, struct DFSAccounting &DFS)
     469{
     470  delete (DFS.AtomStack);
     471  // delete (DFS.BackEdgeStack); // DON'T free, see DepthFirstSearchAnalysis(), is returned as allocated
     472}
     473;
    325474
    326475/** Performs a Depth-First search on this molecule.
     
    332481 * \return list of each disconnected subgraph as an individual molecule class structure
    333482 */
    334 MoleculeLeafClass * molecule::DepthFirstSearchAnalysis(ofstream *out, class StackClass<bond *> *&BackEdgeStack)
    335 {
    336   class StackClass<atom *> *AtomStack = new StackClass<atom *>(AtomCount);
     483MoleculeLeafClass * molecule::DepthFirstSearchAnalysis(ofstream *out, class StackClass<bond *> *&BackEdgeStack) const
     484{
     485  struct DFSAccounting DFS;
    337486  BackEdgeStack = new StackClass<bond *> (BondCount);
     487  DFS.BackEdgeStack = BackEdgeStack;
    338488  MoleculeLeafClass *SubGraphs = new MoleculeLeafClass(NULL);
    339489  MoleculeLeafClass *LeafWalker = SubGraphs;
    340   int CurrentGraphNr = 0, OldGraphNr;
    341   int ComponentNumber = 0;
    342   atom *Walker = NULL, *OtherAtom = NULL, *Root = start->next;
     490  int OldGraphNr = 0;
     491  atom *Walker = NULL;
    343492  bond *Binder = NULL;
    344   bool BackStepping = false;
    345493
    346494  *out << Verbose(0) << "Begin of DepthFirstSearchAnalysis" << endl;
    347 
    348   ResetAllBondsToUnused();
    349   ResetAllAtomNumbers();
    350   InitComponentNumbers();
    351   BackEdgeStack->ClearStack();
    352   while (Root != end) { // if there any atoms at all
    353     // (1) mark all edges unused, empty stack, set atom->GraphNr = 0 for all
    354     AtomStack->ClearStack();
     495  DepthFirstSearchAnalysis_Init(out, DFS, this);
     496
     497  DFS.Root = start->next;
     498  while (DFS.Root != end) { // if there any atoms at all
     499    // (1) mark all edges unused, empty stack, set atom->GraphNr = -1 for all
     500    DFS.AtomStack->ClearStack();
    355501
    356502    // put into new subgraph molecule and add this to list of subgraphs
    357503    LeafWalker = new MoleculeLeafClass(LeafWalker);
    358504    LeafWalker->Leaf = new molecule(elemente);
    359     LeafWalker->Leaf->AddCopyAtom(Root);
    360 
    361     OldGraphNr = CurrentGraphNr;
    362     Walker = Root;
     505    LeafWalker->Leaf->AddCopyAtom(DFS.Root);
     506
     507    OldGraphNr = DFS.CurrentGraphNr;
     508    Walker = DFS.Root;
    363509    do { // (10)
    364510      do { // (2) set number and Lowpoint of Atom to i, increase i, push current atom
    365         if (!BackStepping) { // if we don't just return from (8)
    366           Walker->GraphNr = CurrentGraphNr;
    367           Walker->LowpointNr = CurrentGraphNr;
    368           *out << Verbose(1) << "Setting Walker[" << Walker->Name << "]'s number to " << Walker->GraphNr << " with Lowpoint " << Walker->LowpointNr << "." << endl;
    369           AtomStack->Push(Walker);
    370           CurrentGraphNr++;
    371         }
    372         do { // (3) if Walker has no unused egdes, go to (5)
    373           BackStepping = false; // reset backstepping flag for (8)
    374           if (Binder == NULL) // if we don't just return from (11), Binder is already set to next unused
    375             Binder = FindNextUnused(Walker);
    376           if (Binder == NULL)
    377             break;
    378           *out << Verbose(2) << "Current Unused Bond is " << *Binder << "." << endl;
    379           // (4) Mark Binder used, ...
    380           Binder->MarkUsed(black);
    381           OtherAtom = Binder->GetOtherAtom(Walker);
    382           *out << Verbose(2) << "(4) OtherAtom is " << OtherAtom->Name << "." << endl;
    383           if (OtherAtom->GraphNr != -1) {
    384             // (4a) ... if "other" atom has been visited (GraphNr != 0), set lowpoint to minimum of both, go to (3)
    385             Binder->Type = BackEdge;
    386             BackEdgeStack->Push(Binder);
    387             Walker->LowpointNr = ( Walker->LowpointNr < OtherAtom->GraphNr ) ? Walker->LowpointNr : OtherAtom->GraphNr;
    388             *out << Verbose(3) << "(4a) Visited: Setting Lowpoint of Walker[" << Walker->Name << "] to " << Walker->LowpointNr << "." << endl;
    389           } else {
    390             // (4b) ... otherwise set OtherAtom as Ancestor of Walker and Walker as OtherAtom, go to (2)
    391             Binder->Type = TreeEdge;
    392             OtherAtom->Ancestor = Walker;
    393             Walker = OtherAtom;
    394             *out << Verbose(3) << "(4b) Not Visited: OtherAtom[" << OtherAtom->Name << "]'s Ancestor is now " << OtherAtom->Ancestor->Name << ", Walker is OtherAtom " << OtherAtom->Name << "." << endl;
    395             break;
    396           }
    397           Binder = NULL;
    398         } while (1);  // (3)
     511        DepthFirstSearchAnalysis_SetWalkersGraphNr(out, Walker, DFS);
     512
     513        DepthFirstSearchAnalysis_ProbeAlongUnusedBond(out, this, Walker, Binder, DFS);
     514
    399515        if (Binder == NULL) {
    400516          *out << Verbose(2) << "No more Unused Bonds." << endl;
     
    402518        } else
    403519          Binder = NULL;
    404       } while (1);  // (2)
     520      } while (1); // (2)
    405521
    406522      // if we came from backstepping, yet there were no more unused bonds, we end up here with no Ancestor, because Walker is Root! Then we are finished!
    407       if ((Walker == Root) && (Binder == NULL))
     523      if ((Walker == DFS.Root) && (Binder == NULL))
    408524        break;
    409525
    410       // (5) if Ancestor of Walker is ...
    411       *out << Verbose(1) << "(5) Number of Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "] is " << Walker->Ancestor->GraphNr << "." << endl;
    412       if (Walker->Ancestor->GraphNr != Root->GraphNr) {
    413         // (6)  (Ancestor of Walker is not Root)
    414         if (Walker->LowpointNr < Walker->Ancestor->GraphNr) {
    415           // (6a) set Ancestor's Lowpoint number to minimum of of its Ancestor and itself, go to Step(8)
    416           Walker->Ancestor->LowpointNr = (Walker->Ancestor->LowpointNr < Walker->LowpointNr) ? Walker->Ancestor->LowpointNr : Walker->LowpointNr;
    417           *out << Verbose(2) << "(6) Setting Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "]'s Lowpoint to " << Walker->Ancestor->LowpointNr << "." << endl;
    418         } else {
    419           // (7) (Ancestor of Walker is a separating vertex, remove all from stack till Walker (including), these and Ancestor form a component
    420           Walker->Ancestor->SeparationVertex = true;
    421           *out << Verbose(2) << "(7) Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "]'s is a separating vertex, creating component." << endl;
    422           SetNextComponentNumber(Walker->Ancestor, ComponentNumber);
    423           *out << Verbose(3) << "(7) Walker[" << Walker->Name << "]'s Ancestor's Compont is " << ComponentNumber << "." << endl;
    424           SetNextComponentNumber(Walker, ComponentNumber);
    425           *out << Verbose(3) << "(7) Walker[" << Walker->Name << "]'s Compont is " << ComponentNumber << "." << endl;
    426           do {
    427             OtherAtom = AtomStack->PopLast();
    428             LeafWalker->Leaf->AddCopyAtom(OtherAtom);
    429             SetNextComponentNumber(OtherAtom, ComponentNumber);
    430             *out << Verbose(3) << "(7) Other[" << OtherAtom->Name << "]'s Compont is " << ComponentNumber << "." << endl;
    431           } while (OtherAtom != Walker);
    432           ComponentNumber++;
    433         }
    434         // (8) Walker becomes its Ancestor, go to (3)
    435         *out << Verbose(2) << "(8) Walker[" << Walker->Name << "] is now its Ancestor " << Walker->Ancestor->Name << ", backstepping. " << endl;
    436         Walker = Walker->Ancestor;
    437         BackStepping = true;
    438       }
    439       if (!BackStepping) {  // coming from (8) want to go to (3)
    440         // (9) remove all from stack till Walker (including), these and Root form a component
    441         AtomStack->Output(out);
    442         SetNextComponentNumber(Root, ComponentNumber);
    443         *out << Verbose(3) << "(9) Root[" << Root->Name << "]'s Component is " << ComponentNumber << "." << endl;
    444         SetNextComponentNumber(Walker, ComponentNumber);
    445         *out << Verbose(3) << "(9) Walker[" << Walker->Name << "]'s Component is " << ComponentNumber << "." << endl;
    446         do {
    447           OtherAtom = AtomStack->PopLast();
    448           LeafWalker->Leaf->AddCopyAtom(OtherAtom);
    449           SetNextComponentNumber(OtherAtom, ComponentNumber);
    450           *out << Verbose(3) << "(7) Other[" << OtherAtom->Name << "]'s Compont is " << ComponentNumber << "." << endl;
    451         } while (OtherAtom != Walker);
    452         ComponentNumber++;
    453 
    454         // (11) Root is separation vertex,  set Walker to Root and go to (4)
    455         Walker = Root;
    456         Binder = FindNextUnused(Walker);
    457         *out << Verbose(1) << "(10) Walker is Root[" << Root->Name << "], next Unused Bond is " << Binder << "." << endl;
    458         if (Binder != NULL) { // Root is separation vertex
    459           *out << Verbose(1) << "(11) Root is a separation vertex." << endl;
    460           Walker->SeparationVertex = true;
    461         }
    462       }
    463     } while ((BackStepping) || (Binder != NULL)); // (10) halt only if Root has no unused edges
     526      DepthFirstSearchAnalysis_CheckForaNewComponent(out, this, Walker, DFS, LeafWalker);
     527
     528      DepthFirstSearchAnalysis_CleanRootStackDownTillWalker(out, this, Walker, Binder, DFS, LeafWalker);
     529
     530    } while ((DFS.BackStepping) || (Binder != NULL)); // (10) halt only if Root has no unused edges
    464531
    465532    // From OldGraphNr to CurrentGraphNr ranges an disconnected subgraph
    466     *out << Verbose(0) << "Disconnected subgraph ranges from " << OldGraphNr << " to " << CurrentGraphNr << "." << endl;
     533    *out << Verbose(0) << "Disconnected subgraph ranges from " << OldGraphNr << " to " << DFS.CurrentGraphNr << "." << endl;
    467534    LeafWalker->Leaf->Output(out);
    468535    *out << endl;
    469536
    470537    // step on to next root
    471     while ((Root != end) && (Root->GraphNr != -1)) {
     538    while ((DFS.Root != end) && (DFS.Root->GraphNr != -1)) {
    472539      //*out << Verbose(1) << "Current next subgraph root candidate is " << Root->Name << "." << endl;
    473       if (Root->GraphNr != -1) // if already discovered, step on
    474         Root = Root->next;
     540      if (DFS.Root->GraphNr != -1) // if already discovered, step on
     541        DFS.Root = DFS.Root->next;
    475542    }
    476543  }
    477544  // set cyclic bond criterium on "same LP" basis
    478   Binder = first;
    479   while(Binder->next != last) {
     545  CyclicBondAnalysis();
     546
     547  OutputGraphInfoPerAtom(out);
     548
     549  OutputGraphInfoPerBond(out);
     550
     551  // free all and exit
     552  DepthFirstSearchAnalysis_Finalize(out, DFS);
     553  *out << Verbose(0) << "End of DepthFirstSearchAnalysis" << endl;
     554  return SubGraphs;
     555}
     556;
     557
     558/** Scans through all bonds and set bond::Cyclic to true where atom::LowpointNr of both ends is equal: LP criterion.
     559 */
     560void molecule::CyclicBondAnalysis() const
     561{
     562  NoCyclicBonds = 0;
     563  bond *Binder = first;
     564  while (Binder->next != last) {
    480565    Binder = Binder->next;
    481566    if (Binder->rightatom->LowpointNr == Binder->leftatom->LowpointNr) { // cyclic ??
     
    484569    }
    485570  }
    486 
    487 
     571}
     572;
     573
     574/** Output graph information per atom.
     575 * \param *out output stream
     576 */
     577void molecule::OutputGraphInfoPerAtom(ofstream *out) const
     578{
    488579  *out << Verbose(1) << "Final graph info for each atom is:" << endl;
    489   Walker = start;
    490   while (Walker->next != end) {
    491     Walker = Walker->next;
    492     *out << Verbose(2) << "Atom " << Walker->Name << " is " << ((Walker->SeparationVertex) ? "a" : "not a") << " separation vertex, components are ";
    493     OutputComponentNumber(out, Walker);
    494     *out << " with Lowpoint " << Walker->LowpointNr << " and Graph Nr. " << Walker->GraphNr << "." << endl;
    495   }
    496 
     580  ActOnAllAtoms(&atom::OutputGraphInfo, out);
     581}
     582;
     583
     584/** Output graph information per bond.
     585 * \param *out output stream
     586 */
     587void molecule::OutputGraphInfoPerBond(ofstream *out) const
     588{
    497589  *out << Verbose(1) << "Final graph info for each bond is:" << endl;
    498   Binder = first;
    499   while(Binder->next != last) {
     590  bond *Binder = first;
     591  while (Binder->next != last) {
    500592    Binder = Binder->next;
    501593    *out << Verbose(2) << ((Binder->Type == TreeEdge) ? "TreeEdge " : "BackEdge ") << *Binder << ": <";
    502594    *out << ((Binder->leftatom->SeparationVertex) ? "SP," : "") << "L" << Binder->leftatom->LowpointNr << " G" << Binder->leftatom->GraphNr << " Comp.";
    503     OutputComponentNumber(out, Binder->leftatom);
     595    Binder->leftatom->OutputComponentNumber(out);
    504596    *out << " ===  ";
    505597    *out << ((Binder->rightatom->SeparationVertex) ? "SP," : "") << "L" << Binder->rightatom->LowpointNr << " G" << Binder->rightatom->GraphNr << " Comp.";
    506     OutputComponentNumber(out, Binder->rightatom);
     598    Binder->rightatom->OutputComponentNumber(out);
    507599    *out << ">." << endl;
    508600    if (Binder->Cyclic) // cyclic ??
    509601      *out << Verbose(3) << "Lowpoint at each side are equal: CYCLIC!" << endl;
    510602  }
    511 
    512   // free all and exit
    513   delete(AtomStack);
    514   *out << Verbose(0) << "End of DepthFirstSearchAnalysis" << endl;
    515   return SubGraphs;
     603}
     604;
     605
     606/** Initialise each vertex as white with no predecessor, empty queue, color Root lightgray.
     607 * \param *out output stream for debugging
     608 * \param &BFS accounting structure
     609 * \param AtomCount number of entries in the array to allocate
     610 */
     611void InitializeBFSAccounting(ofstream *out, struct BFSAccounting &BFS, int AtomCount)
     612{
     613  BFS.AtomCount = AtomCount;
     614  BFS.PredecessorList = Calloc<atom*> (AtomCount, "molecule::BreadthFirstSearchAdd_Init: **PredecessorList");
     615  BFS.ShortestPathList = Malloc<int> (AtomCount, "molecule::BreadthFirstSearchAdd_Init: *ShortestPathList");
     616  BFS.ColorList = Calloc<enum Shading> (AtomCount, "molecule::BreadthFirstSearchAdd_Init: *ColorList");
     617  BFS.BFSStack = new StackClass<atom *> (AtomCount);
     618
     619  for (int i = AtomCount; i--;)
     620    BFS.ShortestPathList[i] = -1;
    516621};
     622
     623/** Free's accounting structure.
     624 * \param *out output stream for debugging
     625 * \param &BFS accounting structure
     626 */
     627void FinalizeBFSAccounting(ofstream *out, struct BFSAccounting &BFS)
     628{
     629  Free(&BFS.PredecessorList);
     630  Free(&BFS.ShortestPathList);
     631  Free(&BFS.ColorList);
     632  delete (BFS.BFSStack);
     633  BFS.AtomCount = 0;
     634};
     635
     636/** Clean the accounting structure.
     637 * \param *out output stream for debugging
     638 * \param &BFS accounting structure
     639 */
     640void CleanBFSAccounting(ofstream *out, struct BFSAccounting &BFS)
     641{
     642  atom *Walker = NULL;
     643  while (!BFS.TouchedStack->IsEmpty()) {
     644    Walker = BFS.TouchedStack->PopFirst();
     645    BFS.PredecessorList[Walker->nr] = NULL;
     646    BFS.ShortestPathList[Walker->nr] = -1;
     647    BFS.ColorList[Walker->nr] = white;
     648  }
     649};
     650
     651/** Resets shortest path list and BFSStack.
     652 * \param *out output stream for debugging
     653 * \param *&Walker current node, pushed onto BFSAccounting::BFSStack and BFSAccounting::TouchedStack
     654 * \param &BFS accounting structure
     655 */
     656void ResetBFSAccounting(ofstream *out, atom *&Walker, struct BFSAccounting &BFS)
     657{
     658  BFS.ShortestPathList[Walker->nr] = 0;
     659  BFS.BFSStack->ClearStack(); // start with empty BFS stack
     660  BFS.BFSStack->Push(Walker);
     661  BFS.TouchedStack->Push(Walker);
     662};
     663
     664/** Performs a BFS from \a *Root, trying to find the same node and hence a cycle.
     665 * \param *out output stream for debugging
     666 * \param *&BackEdge the edge from root that we don't want to move along
     667 * \param &BFS accounting structure
     668 */
     669void CyclicStructureAnalysis_CyclicBFSFromRootToRoot(ofstream *out, bond *&BackEdge, struct BFSAccounting &BFS)
     670{
     671  atom *Walker = NULL;
     672  atom *OtherAtom = NULL;
     673  do { // look for Root
     674    Walker = BFS.BFSStack->PopFirst();
     675    *out << Verbose(2) << "Current Walker is " << *Walker << ", we look for SP to Root " << *BFS.Root << "." << endl;
     676    for (BondList::const_iterator Runner = Walker->ListOfBonds.begin(); Runner != Walker->ListOfBonds.end(); (++Runner)) {
     677      if ((*Runner) != BackEdge) { // only walk along DFS spanning tree (otherwise we always find SP of one being backedge Binder)
     678        OtherAtom = (*Runner)->GetOtherAtom(Walker);
     679#ifdef ADDHYDROGEN
     680        if (OtherAtom->type->Z != 1) {
     681#endif
     682        *out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *(*Runner) << "." << endl;
     683        if (BFS.ColorList[OtherAtom->nr] == white) {
     684          BFS.TouchedStack->Push(OtherAtom);
     685          BFS.ColorList[OtherAtom->nr] = lightgray;
     686          BFS.PredecessorList[OtherAtom->nr] = Walker; // Walker is the predecessor
     687          BFS.ShortestPathList[OtherAtom->nr] = BFS.ShortestPathList[Walker->nr] + 1;
     688          *out << Verbose(2) << "Coloring OtherAtom " << OtherAtom->Name << " lightgray, its predecessor is " << Walker->Name << " and its Shortest Path is " << BFS.ShortestPathList[OtherAtom->nr] << " egde(s) long." << endl;
     689          //if (BFS.ShortestPathList[OtherAtom->nr] < MinimumRingSize[Walker->GetTrueFather()->nr]) { // Check for maximum distance
     690          *out << Verbose(3) << "Putting OtherAtom into queue." << endl;
     691          BFS.BFSStack->Push(OtherAtom);
     692          //}
     693        } else {
     694          *out << Verbose(3) << "Not Adding, has already been visited." << endl;
     695        }
     696        if (OtherAtom == BFS.Root)
     697          break;
     698#ifdef ADDHYDROGEN
     699      } else {
     700        *out << Verbose(2) << "Skipping hydrogen atom " << *OtherAtom << "." << endl;
     701        BFS.ColorList[OtherAtom->nr] = black;
     702      }
     703#endif
     704      } else {
     705        *out << Verbose(2) << "Bond " << *(*Runner) << " not Visiting, is the back edge." << endl;
     706      }
     707    }
     708    BFS.ColorList[Walker->nr] = black;
     709    *out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl;
     710    if (OtherAtom == BFS.Root) { // if we have found the root, check whether this cycle wasn't already found beforehand
     711      // step through predecessor list
     712      while (OtherAtom != BackEdge->rightatom) {
     713        if (!OtherAtom->GetTrueFather()->IsCyclic) // if one bond in the loop is not marked as cyclic, we haven't found this cycle yet
     714          break;
     715        else
     716          OtherAtom = BFS.PredecessorList[OtherAtom->nr];
     717      }
     718      if (OtherAtom == BackEdge->rightatom) { // if each atom in found cycle is cyclic, loop's been found before already
     719        *out << Verbose(3) << "This cycle was already found before, skipping and removing seeker from search." << endl;
     720        do {
     721          OtherAtom = BFS.TouchedStack->PopLast();
     722          if (BFS.PredecessorList[OtherAtom->nr] == Walker) {
     723            *out << Verbose(4) << "Removing " << *OtherAtom << " from lists and stacks." << endl;
     724            BFS.PredecessorList[OtherAtom->nr] = NULL;
     725            BFS.ShortestPathList[OtherAtom->nr] = -1;
     726            BFS.ColorList[OtherAtom->nr] = white;
     727            BFS.BFSStack->RemoveItem(OtherAtom);
     728          }
     729        } while ((!BFS.TouchedStack->IsEmpty()) && (BFS.PredecessorList[OtherAtom->nr] == NULL));
     730        BFS.TouchedStack->Push(OtherAtom); // last was wrongly popped
     731        OtherAtom = BackEdge->rightatom; // set to not Root
     732      } else
     733        OtherAtom = BFS.Root;
     734    }
     735  } while ((!BFS.BFSStack->IsEmpty()) && (OtherAtom != BFS.Root) && (OtherAtom != NULL)); // || (ShortestPathList[OtherAtom->nr] < MinimumRingSize[Walker->GetTrueFather()->nr])));
     736};
     737
     738/** Climb back the BFSAccounting::PredecessorList and find cycle members.
     739 * \param *out output stream for debugging
     740 * \param *&OtherAtom
     741 * \param *&BackEdge denotes the edge we did not want to travel along when doing CyclicBFSFromRootToRoot()
     742 * \param &BFS accounting structure
     743 * \param *&MinimumRingSize minimum distance from this node possible without encountering oneself, set on return for each atom
     744 * \param &MinRingSize global minimum distance from one node without encountering oneself, set on return
     745 */
     746void CyclicStructureAnalysis_RetrieveCycleMembers(ofstream *out, atom *&OtherAtom, bond *&BackEdge, struct BFSAccounting &BFS, int *&MinimumRingSize, int &MinRingSize)
     747{
     748  atom *Walker = NULL;
     749  int NumCycles = 0;
     750  int RingSize = -1;
     751
     752  if (OtherAtom == BFS.Root) {
     753    // now climb back the predecessor list and thus find the cycle members
     754    NumCycles++;
     755    RingSize = 1;
     756    BFS.Root->GetTrueFather()->IsCyclic = true;
     757    *out << Verbose(1) << "Found ring contains: ";
     758    Walker = BFS.Root;
     759    while (Walker != BackEdge->rightatom) {
     760      *out << Walker->Name << " <-> ";
     761      Walker = BFS.PredecessorList[Walker->nr];
     762      Walker->GetTrueFather()->IsCyclic = true;
     763      RingSize++;
     764    }
     765    *out << Walker->Name << "  with a length of " << RingSize << "." << endl << endl;
     766    // walk through all and set MinimumRingSize
     767    Walker = BFS.Root;
     768    MinimumRingSize[Walker->GetTrueFather()->nr] = RingSize;
     769    while (Walker != BackEdge->rightatom) {
     770      Walker = BFS.PredecessorList[Walker->nr];
     771      if (RingSize < MinimumRingSize[Walker->GetTrueFather()->nr])
     772        MinimumRingSize[Walker->GetTrueFather()->nr] = RingSize;
     773    }
     774    if ((RingSize < MinRingSize) || (MinRingSize == -1))
     775      MinRingSize = RingSize;
     776  } else {
     777    *out << Verbose(1) << "No ring containing " << *BFS.Root << " with length equal to or smaller than " << MinimumRingSize[Walker->GetTrueFather()->nr] << " found." << endl;
     778  }
     779};
     780
     781/** From a given node performs a BFS to touch the next cycle, for whose nodes \a *&MinimumRingSize is set and set it accordingly.
     782 * \param *out output stream for debugging
     783 * \param *&Root node to look for closest cycle from, i.e. \a *&MinimumRingSize is set for this node
     784 * \param *&MinimumRingSize minimum distance from this node possible without encountering oneself, set on return for each atom
     785 * \param AtomCount number of nodes in graph
     786 */
     787void CyclicStructureAnalysis_BFSToNextCycle(ofstream *out, atom *&Root, atom *&Walker, int *&MinimumRingSize, int AtomCount)
     788{
     789  struct BFSAccounting BFS;
     790  atom *OtherAtom = Walker;
     791
     792  InitializeBFSAccounting(out, BFS, AtomCount);
     793
     794  ResetBFSAccounting(out, Walker, BFS);
     795  while (OtherAtom != NULL) { // look for Root
     796    Walker = BFS.BFSStack->PopFirst();
     797    //*out << Verbose(2) << "Current Walker is " << *Walker << ", we look for SP to Root " << *Root << "." << endl;
     798    for (BondList::const_iterator Runner = Walker->ListOfBonds.begin(); Runner != Walker->ListOfBonds.end(); (++Runner)) {
     799      // "removed (*Runner) != BackEdge) || " from next if, is u
     800      if ((Walker->ListOfBonds.size() == 1)) { // only walk along DFS spanning tree (otherwise we always find SP of 1 being backedge Binder), but terminal hydrogens may be connected via backedge, hence extra check
     801        OtherAtom = (*Runner)->GetOtherAtom(Walker);
     802        //*out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl;
     803        if (BFS.ColorList[OtherAtom->nr] == white) {
     804          BFS.TouchedStack->Push(OtherAtom);
     805          BFS.ColorList[OtherAtom->nr] = lightgray;
     806          BFS.PredecessorList[OtherAtom->nr] = Walker; // Walker is the predecessor
     807          BFS.ShortestPathList[OtherAtom->nr] = BFS.ShortestPathList[Walker->nr] + 1;
     808          //*out << Verbose(2) << "Coloring OtherAtom " << OtherAtom->Name << " lightgray, its predecessor is " << Walker->Name << " and its Shortest Path is " << ShortestPathList[OtherAtom->nr] << " egde(s) long." << endl;
     809          if (OtherAtom->GetTrueFather()->IsCyclic) { // if the other atom is connected to a ring
     810            MinimumRingSize[Root->GetTrueFather()->nr] = BFS.ShortestPathList[OtherAtom->nr] + MinimumRingSize[OtherAtom->GetTrueFather()->nr];
     811            OtherAtom = NULL; //break;
     812            break;
     813          } else
     814            BFS.BFSStack->Push(OtherAtom);
     815        } else {
     816          //*out << Verbose(3) << "Not Adding, has already been visited." << endl;
     817        }
     818      } else {
     819        //*out << Verbose(3) << "Not Visiting, is a back edge." << endl;
     820      }
     821    }
     822    BFS.ColorList[Walker->nr] = black;
     823    //*out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl;
     824  }
     825  //CleanAccountingLists(TouchedStack, PredecessorList, ShortestPathList, ColorList);
     826
     827  FinalizeBFSAccounting(out, BFS);
     828}
     829;
     830
     831/** All nodes that are not in cycles get assigned a \a *&MinimumRingSizeby BFS to next cycle.
     832 * \param *out output stream for debugging
     833 * \param *&MinimumRingSize array with minimum distance without encountering onself for each atom
     834 * \param &MinRingSize global minium distance
     835 * \param &NumCyles number of cycles in graph
     836 * \param *mol molecule with atoms
     837 */
     838void CyclicStructureAnalysis_AssignRingSizetoNonCycleMembers(ofstream *out, int *&MinimumRingSize, int &MinRingSize, int &NumCycles, const molecule * const mol)
     839{
     840  atom *Root = NULL;
     841  atom *Walker = NULL;
     842  if (MinRingSize != -1) { // if rings are present
     843    // go over all atoms
     844    Root = mol->start;
     845    while (Root->next != mol->end) {
     846      Root = Root->next;
     847
     848      if (MinimumRingSize[Root->GetTrueFather()->nr] == mol->AtomCount) { // check whether MinimumRingSize is set, if not BFS to next where it is
     849        Walker = Root;
     850
     851        //*out << Verbose(1) << "---------------------------------------------------------------------------------------------------------" << endl;
     852        CyclicStructureAnalysis_BFSToNextCycle(out, Root, Walker, MinimumRingSize, mol->AtomCount);
     853
     854      }
     855      *out << Verbose(1) << "Minimum ring size of " << *Root << " is " << MinimumRingSize[Root->GetTrueFather()->nr] << "." << endl;
     856    }
     857    *out << Verbose(1) << "Minimum ring size is " << MinRingSize << ", over " << NumCycles << " cycles total." << endl;
     858  } else
     859    *out << Verbose(1) << "No rings were detected in the molecular structure." << endl;
     860}
     861;
    517862
    518863/** Analyses the cycles found and returns minimum of all cycle lengths.
     
    526871 * \todo BFS from the not-same-LP to find back to starting point of tributary cycle over more than one bond
    527872 */
    528 void molecule::CyclicStructureAnalysis(ofstream *out, class StackClass<bond *> *  BackEdgeStack, int *&MinimumRingSize)
    529 {
    530   atom **PredecessorList = Malloc<atom*>(AtomCount, "molecule::CyclicStructureAnalysis: **PredecessorList");
    531   int *ShortestPathList = Malloc<int>(AtomCount, "molecule::CyclicStructureAnalysis: *ShortestPathList");
    532   enum Shading *ColorList = Malloc<enum Shading>(AtomCount, "molecule::CyclicStructureAnalysis: *ColorList");
    533   class StackClass<atom *> *BFSStack = new StackClass<atom *> (AtomCount);   // will hold the current ring
    534   class StackClass<atom *> *TouchedStack = new StackClass<atom *> (AtomCount);   // contains all "touched" atoms (that need to be reset after BFS loop)
    535   atom *Walker = NULL, *OtherAtom = NULL, *Root = NULL;
    536   bond *Binder = NULL, *BackEdge = NULL;
    537   int RingSize, NumCycles, MinRingSize = -1;
    538 
    539   // initialise each vertex as white with no predecessor, empty queue, color Root lightgray
    540   for (int i=AtomCount;i--;) {
    541     PredecessorList[i] = NULL;
    542     ShortestPathList[i] = -1;
    543     ColorList[i] = white;
    544   }
    545 
    546   *out << Verbose(1) << "Back edge list - ";
    547   BackEdgeStack->Output(out);
     873void molecule::CyclicStructureAnalysis(ofstream *out, class StackClass<bond *> * BackEdgeStack, int *&MinimumRingSize) const
     874{
     875  struct BFSAccounting BFS;
     876  atom *Walker = NULL;
     877  atom *OtherAtom = NULL;
     878  bond *BackEdge = NULL;
     879  int NumCycles = 0;
     880  int MinRingSize = -1;
     881
     882  InitializeBFSAccounting(out, BFS, AtomCount);
     883
     884  //*out << Verbose(1) << "Back edge list - ";
     885  //BackEdgeStack->Output(out);
    548886
    549887  *out << Verbose(1) << "Analysing cycles ... " << endl;
     
    552890    BackEdge = BackEdgeStack->PopFirst();
    553891    // this is the target
    554     Root = BackEdge->leftatom;
     892    BFS.Root = BackEdge->leftatom;
    555893    // this is the source point
    556894    Walker = BackEdge->rightatom;
    557     ShortestPathList[Walker->nr] = 0;
    558     BFSStack->ClearStack();  // start with empty BFS stack
    559     BFSStack->Push(Walker);
    560     TouchedStack->Push(Walker);
     895
     896    ResetBFSAccounting(out, Walker, BFS);
     897
    561898    *out << Verbose(1) << "---------------------------------------------------------------------------------------------------------" << endl;
    562899    OtherAtom = NULL;
    563     do {  // look for Root
    564       Walker = BFSStack->PopFirst();
    565       *out << Verbose(2) << "Current Walker is " << *Walker << ", we look for SP to Root " << *Root << "." << endl;
    566       for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {
    567         Binder = ListOfBondsPerAtom[Walker->nr][i];
    568         if (Binder != BackEdge) { // only walk along DFS spanning tree (otherwise we always find SP of one being backedge Binder)
    569           OtherAtom = Binder->GetOtherAtom(Walker);
    570 #ifdef ADDHYDROGEN
    571           if (OtherAtom->type->Z != 1) {
    572 #endif
    573             *out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl;
    574             if (ColorList[OtherAtom->nr] == white) {
    575               TouchedStack->Push(OtherAtom);
    576               ColorList[OtherAtom->nr] = lightgray;
    577               PredecessorList[OtherAtom->nr] = Walker;  // Walker is the predecessor
    578               ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1;
    579               *out << Verbose(2) << "Coloring OtherAtom " << OtherAtom->Name << " lightgray, its predecessor is " << Walker->Name << " and its Shortest Path is " << ShortestPathList[OtherAtom->nr] << " egde(s) long." << endl;
    580               //if (ShortestPathList[OtherAtom->nr] < MinimumRingSize[Walker->GetTrueFather()->nr]) { // Check for maximum distance
    581                 *out << Verbose(3) << "Putting OtherAtom into queue." << endl;
    582                 BFSStack->Push(OtherAtom);
    583               //}
    584             } else {
    585               *out << Verbose(3) << "Not Adding, has already been visited." << endl;
    586             }
    587             if (OtherAtom == Root)
    588               break;
    589 #ifdef ADDHYDROGEN
    590           } else {
    591             *out << Verbose(2) << "Skipping hydrogen atom " << *OtherAtom << "." << endl;
    592             ColorList[OtherAtom->nr] = black;
    593           }
    594 #endif
    595         } else {
    596           *out << Verbose(2) << "Bond " << *Binder << " not Visiting, is the back edge." << endl;
    597         }
    598       }
    599       ColorList[Walker->nr] = black;
    600       *out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl;
    601       if (OtherAtom == Root) { // if we have found the root, check whether this cycle wasn't already found beforehand
    602         // step through predecessor list
    603         while (OtherAtom != BackEdge->rightatom) {
    604           if (!OtherAtom->GetTrueFather()->IsCyclic)  // if one bond in the loop is not marked as cyclic, we haven't found this cycle yet
    605             break;
    606           else
    607             OtherAtom = PredecessorList[OtherAtom->nr];
    608         }
    609         if (OtherAtom == BackEdge->rightatom) { // if each atom in found cycle is cyclic, loop's been found before already
    610           *out << Verbose(3) << "This cycle was already found before, skipping and removing seeker from search." << endl;\
    611           do {
    612             OtherAtom = TouchedStack->PopLast();
    613             if (PredecessorList[OtherAtom->nr] == Walker) {
    614               *out << Verbose(4) << "Removing " << *OtherAtom << " from lists and stacks." << endl;
    615               PredecessorList[OtherAtom->nr] = NULL;
    616               ShortestPathList[OtherAtom->nr] = -1;
    617               ColorList[OtherAtom->nr] = white;
    618               BFSStack->RemoveItem(OtherAtom);
    619             }
    620           } while ((!TouchedStack->IsEmpty()) && (PredecessorList[OtherAtom->nr] == NULL));
    621           TouchedStack->Push(OtherAtom);  // last was wrongly popped
    622           OtherAtom = BackEdge->rightatom; // set to not Root
    623         } else
    624           OtherAtom = Root;
    625       }
    626     } while ((!BFSStack->IsEmpty()) && (OtherAtom != Root) && (OtherAtom != NULL)); // || (ShortestPathList[OtherAtom->nr] < MinimumRingSize[Walker->GetTrueFather()->nr])));
    627 
    628     if (OtherAtom == Root) {
    629       // now climb back the predecessor list and thus find the cycle members
    630       NumCycles++;
    631       RingSize = 1;
    632       Root->GetTrueFather()->IsCyclic = true;
    633       *out << Verbose(1) << "Found ring contains: ";
    634       Walker = Root;
    635       while (Walker != BackEdge->rightatom) {
    636         *out << Walker->Name << " <-> ";
    637         Walker = PredecessorList[Walker->nr];
    638         Walker->GetTrueFather()->IsCyclic = true;
    639         RingSize++;
    640       }
    641       *out << Walker->Name << "  with a length of " << RingSize << "." << endl << endl;
    642       // walk through all and set MinimumRingSize
    643       Walker = Root;
    644       MinimumRingSize[Walker->GetTrueFather()->nr] = RingSize;
    645       while (Walker != BackEdge->rightatom) {
    646         Walker = PredecessorList[Walker->nr];
    647         if (RingSize < MinimumRingSize[Walker->GetTrueFather()->nr])
    648           MinimumRingSize[Walker->GetTrueFather()->nr] = RingSize;
    649       }
    650       if ((RingSize < MinRingSize) || (MinRingSize == -1))
    651         MinRingSize = RingSize;
    652     } else {
    653       *out << Verbose(1) << "No ring containing " << *Root << " with length equal to or smaller than " << MinimumRingSize[Walker->GetTrueFather()->nr] << " found." << endl;
    654     }
    655 
    656     // now clean the lists
    657     while (!TouchedStack->IsEmpty()){
    658       Walker = TouchedStack->PopFirst();
    659       PredecessorList[Walker->nr] = NULL;
    660       ShortestPathList[Walker->nr] = -1;
    661       ColorList[Walker->nr] = white;
    662     }
    663   }
    664   if (MinRingSize != -1) {
    665     // go over all atoms
    666     Root = start;
    667     while(Root->next != end) {
    668       Root = Root->next;
    669 
    670       if (MinimumRingSize[Root->GetTrueFather()->nr] == AtomCount) { // check whether MinimumRingSize is set, if not BFS to next where it is
    671         Walker = Root;
    672         ShortestPathList[Walker->nr] = 0;
    673         BFSStack->ClearStack();  // start with empty BFS stack
    674         BFSStack->Push(Walker);
    675         TouchedStack->Push(Walker);
    676         //*out << Verbose(1) << "---------------------------------------------------------------------------------------------------------" << endl;
    677         OtherAtom = Walker;
    678         while (OtherAtom != NULL) {  // look for Root
    679           Walker = BFSStack->PopFirst();
    680           //*out << Verbose(2) << "Current Walker is " << *Walker << ", we look for SP to Root " << *Root << "." << endl;
    681           for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {
    682             Binder = ListOfBondsPerAtom[Walker->nr][i];
    683             if ((Binder != BackEdge) || (NumberOfBondsPerAtom[Walker->nr] == 1)) { // only walk along DFS spanning tree (otherwise we always find SP of 1 being backedge Binder), but terminal hydrogens may be connected via backedge, hence extra check
    684               OtherAtom = Binder->GetOtherAtom(Walker);
    685               //*out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl;
    686               if (ColorList[OtherAtom->nr] == white) {
    687                 TouchedStack->Push(OtherAtom);
    688                 ColorList[OtherAtom->nr] = lightgray;
    689                 PredecessorList[OtherAtom->nr] = Walker;  // Walker is the predecessor
    690                 ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1;
    691                 //*out << Verbose(2) << "Coloring OtherAtom " << OtherAtom->Name << " lightgray, its predecessor is " << Walker->Name << " and its Shortest Path is " << ShortestPathList[OtherAtom->nr] << " egde(s) long." << endl;
    692                 if (OtherAtom->GetTrueFather()->IsCyclic) { // if the other atom is connected to a ring
    693                   MinimumRingSize[Root->GetTrueFather()->nr] = ShortestPathList[OtherAtom->nr]+MinimumRingSize[OtherAtom->GetTrueFather()->nr];
    694                   OtherAtom = NULL; //break;
    695                   break;
    696                 } else
    697                   BFSStack->Push(OtherAtom);
    698               } else {
    699                 //*out << Verbose(3) << "Not Adding, has already been visited." << endl;
    700               }
    701             } else {
    702               //*out << Verbose(3) << "Not Visiting, is a back edge." << endl;
    703             }
    704           }
    705           ColorList[Walker->nr] = black;
    706           //*out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl;
    707         }
    708 
    709         // now clean the lists
    710         while (!TouchedStack->IsEmpty()){
    711           Walker = TouchedStack->PopFirst();
    712           PredecessorList[Walker->nr] = NULL;
    713           ShortestPathList[Walker->nr] = -1;
    714           ColorList[Walker->nr] = white;
    715         }
    716       }
    717       *out << Verbose(1) << "Minimum ring size of " << *Root << " is " << MinimumRingSize[Root->GetTrueFather()->nr] << "." << endl;
    718     }
    719     *out << Verbose(1) << "Minimum ring size is " << MinRingSize << ", over " << NumCycles << " cycles total." << endl;
    720   } else
    721     *out << Verbose(1) << "No rings were detected in the molecular structure." << endl;
    722 
    723   Free(&PredecessorList);
    724   Free(&ShortestPathList);
    725   Free(&ColorList);
    726   delete(BFSStack);
     900    CyclicStructureAnalysis_CyclicBFSFromRootToRoot(out, BackEdge, BFS);
     901
     902    CyclicStructureAnalysis_RetrieveCycleMembers(out, OtherAtom, BackEdge, BFS, MinimumRingSize, MinRingSize);
     903
     904    CleanBFSAccounting(out, BFS);
     905  }
     906  FinalizeBFSAccounting(out, BFS);
     907
     908  CyclicStructureAnalysis_AssignRingSizetoNonCycleMembers(out, MinimumRingSize, MinRingSize, NumCycles, this);
    727909};
    728910
     
    732914 * \param nr number to use
    733915 */
    734 void molecule::SetNextComponentNumber(atom *vertex, int nr)
    735 {
    736   int i=0;
     916void molecule::SetNextComponentNumber(atom *vertex, int nr) const
     917{
     918  size_t i = 0;
    737919  if (vertex != NULL) {
    738     for(;i<NumberOfBondsPerAtom[vertex->nr];i++) {
    739       if (vertex->ComponentNr[i] == -1) {   // check if not yet used
     920    for (; i < vertex->ListOfBonds.size(); i++) {
     921      if (vertex->ComponentNr[i] == -1) { // check if not yet used
    740922        vertex->ComponentNr[i] = nr;
    741923        break;
    742       }
    743       else if (vertex->ComponentNr[i] == nr) // if number is already present, don't add another time
    744         break;  // breaking here will not cause error!
    745     }
    746     if (i == NumberOfBondsPerAtom[vertex->nr])
     924      } else if (vertex->ComponentNr[i] == nr) // if number is already present, don't add another time
     925        break; // breaking here will not cause error!
     926    }
     927    if (i == vertex->ListOfBonds.size())
    747928      cerr << "Error: All Component entries are already occupied!" << endl;
    748929  } else
    749       cerr << "Error: Given vertex is NULL!" << endl;
    750 };
    751 
    752 /** Output a list of flags, stating whether the bond was visited or not.
    753  * \param *out output stream for debugging
    754  */
    755 void molecule::OutputComponentNumber(ofstream *out, atom *vertex)
    756 {
    757   for(int i=0;i<NumberOfBondsPerAtom[vertex->nr];i++)
    758     *out << vertex->ComponentNr[i] << "  ";
    759 };
    760 
    761 /** Allocates memory for all atom::*ComponentNr in this molecule and sets each entry to -1.
    762  */
    763 void molecule::InitComponentNumbers()
    764 {
    765   atom *Walker = start;
    766   while(Walker->next != end) {
    767     Walker = Walker->next;
    768     if (Walker->ComponentNr != NULL)
    769       Free(&Walker->ComponentNr);
    770     Walker->ComponentNr = Malloc<int>(NumberOfBondsPerAtom[Walker->nr], "molecule::InitComponentNumbers: *Walker->ComponentNr");
    771     for (int i=NumberOfBondsPerAtom[Walker->nr];i--;)
    772       Walker->ComponentNr[i] = -1;
    773   }
    774 };
     930    cerr << "Error: Given vertex is NULL!" << endl;
     931}
     932;
    775933
    776934/** Returns next unused bond for this atom \a *vertex or NULL of none exists.
     
    778936 * \return bond class or NULL
    779937 */
    780 bond * molecule::FindNextUnused(atom *vertex)
    781 {
    782   for(int i=0;i<NumberOfBondsPerAtom[vertex->nr];i++)
    783     if (ListOfBondsPerAtom[vertex->nr][i]->IsUsed() == white)
    784       return(ListOfBondsPerAtom[vertex->nr][i]);
     938bond * molecule::FindNextUnused(atom *vertex) const
     939{
     940  for (BondList::const_iterator Runner = vertex->ListOfBonds.begin(); Runner != vertex->ListOfBonds.end(); (++Runner))
     941    if ((*Runner)->IsUsed() == white)
     942      return ((*Runner));
    785943  return NULL;
    786 };
     944}
     945;
    787946
    788947/** Resets bond::Used flag of all bonds in this molecule.
    789948 * \return true - success, false - -failure
    790949 */
    791 void molecule::ResetAllBondsToUnused()
     950void molecule::ResetAllBondsToUnused() const
    792951{
    793952  bond *Binder = first;
     
    796955    Binder->ResetUsed();
    797956  }
    798 };
    799 
    800 /** Resets atom::nr to -1 of all atoms in this molecule.
    801  */
    802 void molecule::ResetAllAtomNumbers()
    803 {
    804   atom *Walker = start;
    805   while (Walker->next != end) {
    806     Walker = Walker->next;
    807     Walker->GraphNr  = -1;
    808   }
    809 };
     957}
     958;
    810959
    811960/** Output a list of flags, stating whether the bond was visited or not.
     
    816965{
    817966  *out << Verbose(4) << "Already Visited Bonds:\t";
    818   for(int i=1;i<=list[0];i++) *out << Verbose(0) << list[i] << "  ";
     967  for (int i = 1; i <= list[0]; i++)
     968    *out << Verbose(0) << list[i] << "  ";
    819969  *out << endl;
    820 };
    821 
     970}
     971;
    822972
    823973/** Storing the bond structure of a molecule to file.
     
    830980{
    831981  ofstream AdjacencyFile;
    832   atom *Walker = NULL;
    833982  stringstream line;
    834983  bool status = true;
     
    838987  *out << Verbose(1) << "Saving adjacency list ... ";
    839988  if (AdjacencyFile != NULL) {
    840     Walker = start;
    841     while(Walker->next != end) {
    842       Walker = Walker->next;
    843       AdjacencyFile << Walker->nr << "\t";
    844       for (int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++)
    845         AdjacencyFile << ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker)->nr << "\t";
    846       AdjacencyFile << endl;
    847     }
     989    ActOnAllAtoms(&atom::OutputAdjacency, &AdjacencyFile);
    848990    AdjacencyFile.close();
    849991    *out << Verbose(1) << "done." << endl;
     
    854996
    855997  return status;
    856 };
     998}
     999;
     1000
     1001bool CheckAdjacencyFileAgainstMolecule_Init(ofstream *out, char *path, ifstream &File, int *&CurrentBonds)
     1002{
     1003  stringstream filename;
     1004  filename << path << "/" << FRAGMENTPREFIX << ADJACENCYFILE;
     1005  File.open(filename.str().c_str(), ios::out);
     1006  *out << Verbose(1) << "Looking at bond structure stored in adjacency file and comparing to present one ... ";
     1007  if (File == NULL)
     1008    return false;
     1009
     1010  // allocate storage structure
     1011  CurrentBonds = Calloc<int> (8, "molecule::CheckAdjacencyFileAgainstMolecule - CurrentBonds"); // contains parsed bonds of current atom
     1012  return true;
     1013}
     1014;
     1015
     1016void CheckAdjacencyFileAgainstMolecule_Finalize(ofstream *out, ifstream &File, int *&CurrentBonds)
     1017{
     1018  File.close();
     1019  File.clear();
     1020  Free(&CurrentBonds);
     1021}
     1022;
     1023
     1024void CheckAdjacencyFileAgainstMolecule_CompareBonds(ofstream *out, bool &status, int &NonMatchNumber, atom *&Walker, size_t &CurrentBondsOfAtom, int AtomNr, int *&CurrentBonds, atom **ListOfAtoms)
     1025{
     1026  size_t j = 0;
     1027  int id = -1;
     1028
     1029  //*out << Verbose(2) << "Walker is " << *Walker << ", bond partners: ";
     1030  if (CurrentBondsOfAtom == Walker->ListOfBonds.size()) {
     1031    for (BondList::const_iterator Runner = Walker->ListOfBonds.begin(); Runner != Walker->ListOfBonds.end(); (++Runner)) {
     1032      id = (*Runner)->GetOtherAtom(Walker)->nr;
     1033      j = 0;
     1034      for (; (j < CurrentBondsOfAtom) && (CurrentBonds[j++] != id);)
     1035        ; // check against all parsed bonds
     1036      if (CurrentBonds[j - 1] != id) { // no match ? Then mark in ListOfAtoms
     1037        ListOfAtoms[AtomNr] = NULL;
     1038        NonMatchNumber++;
     1039        status = false;
     1040        //*out << "[" << id << "]\t";
     1041      } else {
     1042        //*out << id << "\t";
     1043      }
     1044    }
     1045    //*out << endl;
     1046  } else {
     1047    *out << "Number of bonds for Atom " << *Walker << " does not match, parsed " << CurrentBondsOfAtom << " against " << Walker->ListOfBonds.size() << "." << endl;
     1048    status = false;
     1049  }
     1050}
     1051;
    8571052
    8581053/** Checks contents of adjacency file against bond structure in structure molecule.
     
    8651060{
    8661061  ifstream File;
    867   stringstream filename;
    8681062  bool status = true;
    869   char *buffer = Malloc<char>(MAXSTRINGSIZE, "molecule::CheckAdjacencyFileAgainstMolecule: *buffer");
    870 
    871   filename << path << "/" << FRAGMENTPREFIX << ADJACENCYFILE;
    872   File.open(filename.str().c_str(), ios::out);
    873   *out << Verbose(1) << "Looking at bond structure stored in adjacency file and comparing to present one ... ";
    874   if (File != NULL) {
    875     // allocate storage structure
    876     int NonMatchNumber = 0;   // will number of atoms with differing bond structure
    877     int *CurrentBonds = Malloc<int>(8, "molecule::CheckAdjacencyFileAgainstMolecule - CurrentBonds"); // contains parsed bonds of current atom
    878     int CurrentBondsOfAtom;
    879 
    880     // Parse the file line by line and count the bonds
    881     while (!File.eof()) {
    882       File.getline(buffer, MAXSTRINGSIZE);
    883       stringstream line;
    884       line.str(buffer);
    885       int AtomNr = -1;
    886       line >> AtomNr;
    887       CurrentBondsOfAtom = -1; // we count one too far due to line end
    888       // parse into structure
    889       if ((AtomNr >= 0) && (AtomNr < AtomCount)) {
    890         while (!line.eof())
    891           line >> CurrentBonds[ ++CurrentBondsOfAtom ];
    892         // compare against present bonds
    893         //cout << Verbose(2) << "Walker is " << *Walker << ", bond partners: ";
    894         if (CurrentBondsOfAtom == NumberOfBondsPerAtom[AtomNr]) {
    895           for(int i=0;i<NumberOfBondsPerAtom[AtomNr];i++) {
    896             int id = ListOfBondsPerAtom[AtomNr][i]->GetOtherAtom(ListOfAtoms[AtomNr])->nr;
    897             int j = 0;
    898             for (;(j<CurrentBondsOfAtom) && (CurrentBonds[j++] != id);); // check against all parsed bonds
    899             if (CurrentBonds[j-1] != id) { // no match ? Then mark in ListOfAtoms
    900               ListOfAtoms[AtomNr] = NULL;
    901               NonMatchNumber++;
    902               status = false;
    903               //out << "[" << id << "]\t";
    904             } else {
    905               //out << id << "\t";
    906             }
    907           }
    908           //out << endl;
    909         } else {
    910           *out << "Number of bonds for Atom " << *ListOfAtoms[AtomNr] << " does not match, parsed " << CurrentBondsOfAtom << " against " << NumberOfBondsPerAtom[AtomNr] << "." << endl;
    911           status = false;
    912         }
    913       }
    914     }
    915     File.close();
    916     File.clear();
    917     if (status) { // if equal we parse the KeySetFile
    918       *out << Verbose(1) << "done: Equal." << endl;
    919       status = true;
    920     } else
    921       *out << Verbose(1) << "done: Not equal by " << NonMatchNumber << " atoms." << endl;
    922     Free(&CurrentBonds);
    923   } else {
     1063  atom *Walker = NULL;
     1064  char *buffer = NULL;
     1065  int *CurrentBonds = NULL;
     1066  int NonMatchNumber = 0; // will number of atoms with differing bond structure
     1067  size_t CurrentBondsOfAtom = -1;
     1068
     1069  if (!CheckAdjacencyFileAgainstMolecule_Init(out, path, File, CurrentBonds)) {
    9241070    *out << Verbose(1) << "Adjacency file not found." << endl;
    925     status = false;
    926   }
    927   *out << endl;
     1071    return true;
     1072  }
     1073
     1074  buffer = Malloc<char> (MAXSTRINGSIZE, "molecule::CheckAdjacencyFileAgainstMolecule: *buffer");
     1075  // Parse the file line by line and count the bonds
     1076  while (!File.eof()) {
     1077    File.getline(buffer, MAXSTRINGSIZE);
     1078    stringstream line;
     1079    line.str(buffer);
     1080    int AtomNr = -1;
     1081    line >> AtomNr;
     1082    CurrentBondsOfAtom = -1; // we count one too far due to line end
     1083    // parse into structure
     1084    if ((AtomNr >= 0) && (AtomNr < AtomCount)) {
     1085      Walker = ListOfAtoms[AtomNr];
     1086      while (!line.eof())
     1087        line >> CurrentBonds[++CurrentBondsOfAtom];
     1088      // compare against present bonds
     1089      CheckAdjacencyFileAgainstMolecule_CompareBonds(out, status, NonMatchNumber, Walker, CurrentBondsOfAtom, AtomNr, CurrentBonds, ListOfAtoms);
     1090    }
     1091  }
    9281092  Free(&buffer);
    929 
     1093  CheckAdjacencyFileAgainstMolecule_Finalize(out, File, CurrentBonds);
     1094
     1095  if (status) { // if equal we parse the KeySetFile
     1096    *out << Verbose(1) << "done: Equal." << endl;
     1097  } else
     1098    *out << Verbose(1) << "done: Not equal by " << NonMatchNumber << " atoms." << endl;
    9301099  return status;
    931 };
    932 
     1100}
     1101;
    9331102
    9341103/** Picks from a global stack with all back edges the ones in the fragment.
     
    9391108 * \return true - everything ok, false - ReferenceStack was empty
    9401109 */
    941 bool molecule::PickLocalBackEdges(ofstream *out, atom **ListOfLocalAtoms, class StackClass<bond *> *&ReferenceStack, class StackClass<bond *> *&LocalStack)
     1110bool molecule::PickLocalBackEdges(ofstream *out, atom **ListOfLocalAtoms, class StackClass<bond *> *&ReferenceStack, class StackClass<bond *> *&LocalStack) const
    9421111{
    9431112  bool status = true;
     
    9471116  }
    9481117  bond *Binder = ReferenceStack->PopFirst();
    949   bond *FirstBond = Binder;   // mark the first bond, so that we don't loop through the stack indefinitely
     1118  bond *FirstBond = Binder; // mark the first bond, so that we don't loop through the stack indefinitely
    9501119  atom *Walker = NULL, *OtherAtom = NULL;
    9511120  ReferenceStack->Push(Binder);
    9521121
    953   do {  // go through all bonds and push local ones
    954     Walker = ListOfLocalAtoms[Binder->leftatom->nr];  // get one atom in the reference molecule
     1122  do { // go through all bonds and push local ones
     1123    Walker = ListOfLocalAtoms[Binder->leftatom->nr]; // get one atom in the reference molecule
    9551124    if (Walker != NULL) // if this Walker exists in the subgraph ...
    956       for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {    // go through the local list of bonds
    957         OtherAtom = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker);
    958         if (OtherAtom == ListOfLocalAtoms[Binder->rightatom->nr]) { // found the bond
    959           LocalStack->Push(ListOfBondsPerAtom[Walker->nr][i]);
    960           *out << Verbose(3) << "Found local edge " << *(ListOfBondsPerAtom[Walker->nr][i]) << "." << endl;
     1125      for (BondList::const_iterator Runner = Walker->ListOfBonds.begin(); Runner != Walker->ListOfBonds.end(); (++Runner)) {
     1126        OtherAtom = (*Runner)->GetOtherAtom(Walker);
     1127        if (OtherAtom == ListOfLocalAtoms[(*Runner)->rightatom->nr]) { // found the bond
     1128          LocalStack->Push((*Runner));
     1129          *out << Verbose(3) << "Found local edge " << *(*Runner) << "." << endl;
    9611130          break;
    9621131        }
    9631132      }
    964     Binder = ReferenceStack->PopFirst();  // loop the stack for next item
     1133    Binder = ReferenceStack->PopFirst(); // loop the stack for next item
    9651134    *out << Verbose(3) << "Current candidate edge " << Binder << "." << endl;
    9661135    ReferenceStack->Push(Binder);
     
    9681137
    9691138  return status;
    970 };
    971 
     1139}
     1140;
     1141
     1142void BreadthFirstSearchAdd_Init(struct BFSAccounting &BFS, atom *&Root, int AtomCount, int BondOrder, atom **AddedAtomList = NULL)
     1143{
     1144  BFS.AtomCount = AtomCount;
     1145  BFS.BondOrder = BondOrder;
     1146  BFS.PredecessorList = Calloc<atom*> (AtomCount, "molecule::BreadthFirstSearchAdd_Init: **PredecessorList");
     1147  BFS.ShortestPathList = Calloc<int> (AtomCount, "molecule::BreadthFirstSearchAdd_Init: *ShortestPathList");
     1148  BFS.ColorList = Malloc<enum Shading> (AtomCount, "molecule::BreadthFirstSearchAdd_Init: *ColorList");
     1149  BFS.BFSStack = new StackClass<atom *> (AtomCount);
     1150
     1151  BFS.Root = Root;
     1152  BFS.BFSStack->ClearStack();
     1153  BFS.BFSStack->Push(Root);
     1154
     1155  // initialise each vertex as white with no predecessor, empty queue, color Root lightgray
     1156  for (int i = AtomCount; i--;) {
     1157    BFS.ShortestPathList[i] = -1;
     1158    if ((AddedAtomList != NULL) && (AddedAtomList[i] != NULL)) // mark already present atoms (i.e. Root and maybe others) as visited
     1159      BFS.ColorList[i] = lightgray;
     1160    else
     1161      BFS.ColorList[i] = white;
     1162  }
     1163  //BFS.ShortestPathList[Root->nr] = 0; //is set due to Calloc()
     1164}
     1165;
     1166
     1167void BreadthFirstSearchAdd_Free(struct BFSAccounting &BFS)
     1168{
     1169  Free(&BFS.PredecessorList);
     1170  Free(&BFS.ShortestPathList);
     1171  Free(&BFS.ColorList);
     1172  delete (BFS.BFSStack);
     1173  BFS.AtomCount = 0;
     1174}
     1175;
     1176
     1177void BreadthFirstSearchAdd_UnvisitedNode(ofstream *out, molecule *Mol, struct BFSAccounting &BFS, atom *&Walker, atom *&OtherAtom, bond *&Binder, bond *&Bond, atom **&AddedAtomList, bond **&AddedBondList, bool IsAngstroem)
     1178{
     1179  if (Binder != Bond) // let other atom white if it's via Root bond. In case it's cyclic it has to be reached again (yet Root is from OtherAtom already black, thus no problem)
     1180    BFS.ColorList[OtherAtom->nr] = lightgray;
     1181  BFS.PredecessorList[OtherAtom->nr] = Walker; // Walker is the predecessor
     1182  BFS.ShortestPathList[OtherAtom->nr] = BFS.ShortestPathList[Walker->nr] + 1;
     1183  *out << Verbose(2) << "Coloring OtherAtom " << OtherAtom->Name << " " << ((BFS.ColorList[OtherAtom->nr] == white) ? "white" : "lightgray") << ", its predecessor is " << Walker->Name << " and its Shortest Path is " << BFS.ShortestPathList[OtherAtom->nr] << " egde(s) long." << endl;
     1184  if ((((BFS.ShortestPathList[OtherAtom->nr] < BFS.BondOrder) && (Binder != Bond)))) { // Check for maximum distance
     1185    *out << Verbose(3);
     1186    if (AddedAtomList[OtherAtom->nr] == NULL) { // add if it's not been so far
     1187      AddedAtomList[OtherAtom->nr] = Mol->AddCopyAtom(OtherAtom);
     1188      *out << "Added OtherAtom " << OtherAtom->Name;
     1189      AddedBondList[Binder->nr] = Mol->CopyBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder);
     1190      *out << " and bond " << *(AddedBondList[Binder->nr]) << ", ";
     1191    } else { // this code should actually never come into play (all white atoms are not yet present in BondMolecule, that's why they are white in the first place)
     1192      *out << "Not adding OtherAtom " << OtherAtom->Name;
     1193      if (AddedBondList[Binder->nr] == NULL) {
     1194        AddedBondList[Binder->nr] = Mol->CopyBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder);
     1195        *out << ", added Bond " << *(AddedBondList[Binder->nr]);
     1196      } else
     1197        *out << ", not added Bond ";
     1198    }
     1199    *out << ", putting OtherAtom into queue." << endl;
     1200    BFS.BFSStack->Push(OtherAtom);
     1201  } else { // out of bond order, then replace
     1202    if ((AddedAtomList[OtherAtom->nr] == NULL) && (Binder->Cyclic))
     1203      BFS.ColorList[OtherAtom->nr] = white; // unmark if it has not been queued/added, to make it available via its other bonds (cyclic)
     1204    if (Binder == Bond)
     1205      *out << Verbose(3) << "Not Queueing, is the Root bond";
     1206    else if (BFS.ShortestPathList[OtherAtom->nr] >= BFS.BondOrder)
     1207      *out << Verbose(3) << "Not Queueing, is out of Bond Count of " << BFS.BondOrder;
     1208    if (!Binder->Cyclic)
     1209      *out << ", is not part of a cyclic bond, saturating bond with Hydrogen." << endl;
     1210    if (AddedBondList[Binder->nr] == NULL) {
     1211      if ((AddedAtomList[OtherAtom->nr] != NULL)) { // .. whether we add or saturate
     1212        AddedBondList[Binder->nr] = Mol->CopyBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder);
     1213      } else {
     1214#ifdef ADDHYDROGEN
     1215        if (!Mol->AddHydrogenReplacementAtom(out, Binder, AddedAtomList[Walker->nr], Walker, OtherAtom, IsAngstroem))
     1216        exit(1);
     1217#endif
     1218      }
     1219    }
     1220  }
     1221}
     1222;
     1223
     1224void BreadthFirstSearchAdd_VisitedNode(ofstream *out, molecule *Mol, struct BFSAccounting &BFS, atom *&Walker, atom *&OtherAtom, bond *&Binder, bond *&Bond, atom **&AddedAtomList, bond **&AddedBondList, bool IsAngstroem)
     1225{
     1226  *out << Verbose(3) << "Not Adding, has already been visited." << endl;
     1227  // This has to be a cyclic bond, check whether it's present ...
     1228  if (AddedBondList[Binder->nr] == NULL) {
     1229    if ((Binder != Bond) && (Binder->Cyclic) && (((BFS.ShortestPathList[Walker->nr] + 1) < BFS.BondOrder))) {
     1230      AddedBondList[Binder->nr] = Mol->CopyBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder);
     1231    } else { // if it's root bond it has to broken (otherwise we would not create the fragments)
     1232#ifdef ADDHYDROGEN
     1233      if(!Mol->AddHydrogenReplacementAtom(out, Binder, AddedAtomList[Walker->nr], Walker, OtherAtom, IsAngstroem))
     1234      exit(1);
     1235#endif
     1236    }
     1237  }
     1238}
     1239;
    9721240
    9731241/** Adds atoms up to \a BondCount distance from \a *Root and notes them down in \a **AddedAtomList.
     
    9851253void molecule::BreadthFirstSearchAdd(ofstream *out, molecule *Mol, atom **&AddedAtomList, bond **&AddedBondList, atom *Root, bond *Bond, int BondOrder, bool IsAngstroem)
    9861254{
    987   atom **PredecessorList = Malloc<atom*>(AtomCount, "molecule::BreadthFirstSearchAdd: **PredecessorList");
    988   int *ShortestPathList = Malloc<int>(AtomCount, "molecule::BreadthFirstSearchAdd: *ShortestPathList");
    989   enum Shading *ColorList = Malloc<enum Shading>(AtomCount, "molecule::BreadthFirstSearchAdd: *ColorList");
    990   class StackClass<atom *> *AtomStack = new StackClass<atom *>(AtomCount);
     1255  struct BFSAccounting BFS;
    9911256  atom *Walker = NULL, *OtherAtom = NULL;
    9921257  bond *Binder = NULL;
    9931258
    9941259  // add Root if not done yet
    995   AtomStack->ClearStack();
    996   if (AddedAtomList[Root->nr] == NULL)  // add Root if not yet present
     1260  if (AddedAtomList[Root->nr] == NULL) // add Root if not yet present
    9971261    AddedAtomList[Root->nr] = Mol->AddCopyAtom(Root);
    998   AtomStack->Push(Root);
    999 
    1000   // initialise each vertex as white with no predecessor, empty queue, color Root lightgray
    1001   for (int i=AtomCount;i--;) {
    1002     PredecessorList[i] = NULL;
    1003     ShortestPathList[i] = -1;
    1004     if (AddedAtomList[i] != NULL) // mark already present atoms (i.e. Root and maybe others) as visited
    1005       ColorList[i] = lightgray;
    1006     else
    1007       ColorList[i] = white;
    1008   }
    1009   ShortestPathList[Root->nr] = 0;
     1262
     1263  BreadthFirstSearchAdd_Init(BFS, Root, BondOrder, AtomCount, AddedAtomList);
    10101264
    10111265  // and go on ... Queue always contains all lightgray vertices
    1012   while (!AtomStack->IsEmpty()) {
     1266  while (!BFS.BFSStack->IsEmpty()) {
    10131267    // we have to pop the oldest atom from stack. This keeps the atoms on the stack always of the same ShortestPath distance.
    10141268    // e.g. if current atom is 2, push to end of stack are of length 3, but first all of length 2 would be popped. They again
    10151269    // append length of 3 (their neighbours). Thus on stack we have always atoms of a certain length n at bottom of stack and
    10161270    // followed by n+1 till top of stack.
    1017     Walker = AtomStack->PopFirst(); // pop oldest added
    1018     *out << Verbose(1) << "Current Walker is: " << Walker->Name << ", and has " << NumberOfBondsPerAtom[Walker->nr] << " bonds." << endl;
    1019     for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {
    1020       Binder = ListOfBondsPerAtom[Walker->nr][i];
    1021       if (Binder != NULL) { // don't look at bond equal NULL
    1022         OtherAtom = Binder->GetOtherAtom(Walker);
    1023         *out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl;
    1024         if (ColorList[OtherAtom->nr] == white) {
    1025           if (Binder != Bond) // let other atom white if it's via Root bond. In case it's cyclic it has to be reached again (yet Root is from OtherAtom already black, thus no problem)
    1026             ColorList[OtherAtom->nr] = lightgray;
    1027           PredecessorList[OtherAtom->nr] = Walker;  // Walker is the predecessor
    1028           ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1;
    1029           *out << Verbose(2) << "Coloring OtherAtom " << OtherAtom->Name << " " << ((ColorList[OtherAtom->nr] == white) ? "white" : "lightgray") << ", its predecessor is " << Walker->Name << " and its Shortest Path is " << ShortestPathList[OtherAtom->nr] << " egde(s) long." << endl;
    1030           if ((((ShortestPathList[OtherAtom->nr] < BondOrder) && (Binder != Bond))) ) { // Check for maximum distance
    1031             *out << Verbose(3);
    1032             if (AddedAtomList[OtherAtom->nr] == NULL) { // add if it's not been so far
    1033               AddedAtomList[OtherAtom->nr] = Mol->AddCopyAtom(OtherAtom);
    1034               *out << "Added OtherAtom " << OtherAtom->Name;
    1035               AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree);
    1036               AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic;
    1037               AddedBondList[Binder->nr]->Type = Binder->Type;
    1038               *out << " and bond " << *(AddedBondList[Binder->nr]) << ", ";
    1039             } else {  // this code should actually never come into play (all white atoms are not yet present in BondMolecule, that's why they are white in the first place)
    1040               *out << "Not adding OtherAtom " << OtherAtom->Name;
    1041               if (AddedBondList[Binder->nr] == NULL) {
    1042                 AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree);
    1043                 AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic;
    1044                 AddedBondList[Binder->nr]->Type = Binder->Type;
    1045                 *out << ", added Bond " << *(AddedBondList[Binder->nr]);
    1046               } else
    1047                 *out << ", not added Bond ";
    1048             }
    1049             *out << ", putting OtherAtom into queue." << endl;
    1050             AtomStack->Push(OtherAtom);
    1051           } else { // out of bond order, then replace
    1052             if ((AddedAtomList[OtherAtom->nr] == NULL) && (Binder->Cyclic))
    1053               ColorList[OtherAtom->nr] = white; // unmark if it has not been queued/added, to make it available via its other bonds (cyclic)
    1054             if (Binder == Bond)
    1055               *out << Verbose(3) << "Not Queueing, is the Root bond";
    1056             else if (ShortestPathList[OtherAtom->nr] >= BondOrder)
    1057               *out << Verbose(3) << "Not Queueing, is out of Bond Count of " << BondOrder;
    1058             if (!Binder->Cyclic)
    1059               *out << ", is not part of a cyclic bond, saturating bond with Hydrogen." << endl;
    1060             if (AddedBondList[Binder->nr] == NULL) {
    1061               if ((AddedAtomList[OtherAtom->nr] != NULL)) { // .. whether we add or saturate
    1062                 AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree);
    1063                 AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic;
    1064                 AddedBondList[Binder->nr]->Type = Binder->Type;
    1065               } else {
    1066 #ifdef ADDHYDROGEN
    1067                 if (!Mol->AddHydrogenReplacementAtom(out, Binder, AddedAtomList[Walker->nr], Walker, OtherAtom, ListOfBondsPerAtom[Walker->nr], NumberOfBondsPerAtom[Walker->nr], IsAngstroem))
    1068                   exit(1);
    1069 #endif
    1070               }
    1071             }
    1072           }
     1271    Walker = BFS.BFSStack->PopFirst(); // pop oldest added
     1272    *out << Verbose(1) << "Current Walker is: " << Walker->Name << ", and has " << Walker->ListOfBonds.size() << " bonds." << endl;
     1273    for (BondList::const_iterator Runner = Walker->ListOfBonds.begin(); Runner != Walker->ListOfBonds.end(); (++Runner)) {
     1274      if ((*Runner) != NULL) { // don't look at bond equal NULL
     1275        Binder = (*Runner);
     1276        OtherAtom = (*Runner)->GetOtherAtom(Walker);
     1277        *out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *(*Runner) << "." << endl;
     1278        if (BFS.ColorList[OtherAtom->nr] == white) {
     1279          BreadthFirstSearchAdd_UnvisitedNode(out, Mol, BFS, Walker, OtherAtom, Binder, Bond, AddedAtomList, AddedBondList, IsAngstroem);
    10731280        } else {
    1074           *out << Verbose(3) << "Not Adding, has already been visited." << endl;
    1075           // This has to be a cyclic bond, check whether it's present ...
    1076           if (AddedBondList[Binder->nr] == NULL) {
    1077             if ((Binder != Bond) && (Binder->Cyclic) && (((ShortestPathList[Walker->nr]+1) < BondOrder))) {
    1078               AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree);
    1079               AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic;
    1080               AddedBondList[Binder->nr]->Type = Binder->Type;
    1081             } else { // if it's root bond it has to broken (otherwise we would not create the fragments)
    1082 #ifdef ADDHYDROGEN
    1083               if(!Mol->AddHydrogenReplacementAtom(out, Binder, AddedAtomList[Walker->nr], Walker, OtherAtom, ListOfBondsPerAtom[Walker->nr], NumberOfBondsPerAtom[Walker->nr], IsAngstroem))
    1084                 exit(1);
    1085 #endif
    1086             }
    1087           }
     1281          BreadthFirstSearchAdd_VisitedNode(out, Mol, BFS, Walker, OtherAtom, Binder, Bond, AddedAtomList, AddedBondList, IsAngstroem);
    10881282        }
    10891283      }
    10901284    }
    1091     ColorList[Walker->nr] = black;
     1285    BFS.ColorList[Walker->nr] = black;
    10921286    *out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl;
    10931287  }
    1094   Free(&PredecessorList);
    1095   Free(&ShortestPathList);
    1096   Free(&ColorList);
    1097   delete(AtomStack);
    1098 };
    1099 
    1100 /** Adds bond structure to this molecule from \a Father molecule.
    1101  * This basically causes this molecule to become an induced subgraph of the \a Father, i.e. for every bond in Father
    1102  * with end points present in this molecule, bond is created in this molecule.
    1103  * Special care was taken to ensure that this is of complexity O(N), where N is the \a Father's molecule::AtomCount.
    1104  * \param *out output stream for debugging
    1105  * \param *Father father molecule
    1106  * \return true - is induced subgraph, false - there are atoms with fathers not in \a Father
    1107  * \todo not checked, not fully working probably
    1108  */
    1109 bool molecule::BuildInducedSubgraph(ofstream *out, const molecule *Father)
    1110 {
    1111   atom *Walker = NULL, *OtherAtom = NULL;
    1112   bool status = true;
    1113   atom **ParentList = Malloc<atom*>(Father->AtomCount, "molecule::BuildInducedSubgraph: **ParentList");
    1114 
    1115   *out << Verbose(2) << "Begin of BuildInducedSubgraph." << endl;
    1116 
     1288  BreadthFirstSearchAdd_Free(BFS);
     1289}
     1290;
     1291
     1292/** Adds a bond as a copy to a given one
     1293 * \param *left leftatom of new bond
     1294 * \param *right rightatom of new bond
     1295 * \param *CopyBond rest of fields in bond are copied from this
     1296 * \return pointer to new bond
     1297 */
     1298bond * molecule::CopyBond(atom *left, atom *right, bond *CopyBond)
     1299{
     1300  bond *Binder = AddBond(left, right, CopyBond->BondDegree);
     1301  Binder->Cyclic = CopyBond->Cyclic;
     1302  Binder->Type = CopyBond->Type;
     1303  return Binder;
     1304}
     1305;
     1306
     1307void BuildInducedSubgraph_Init(ofstream *out, atom **&ParentList, int AtomCount)
     1308{
    11171309  // reset parent list
     1310  ParentList = Calloc<atom*> (AtomCount, "molecule::BuildInducedSubgraph_Init: **ParentList");
    11181311  *out << Verbose(3) << "Resetting ParentList." << endl;
    1119   for (int i=Father->AtomCount;i--;)
    1120     ParentList[i] = NULL;
    1121 
     1312}
     1313;
     1314
     1315void BuildInducedSubgraph_FillParentList(ofstream *out, const molecule *mol, const molecule *Father, atom **&ParentList)
     1316{
    11221317  // fill parent list with sons
    11231318  *out << Verbose(3) << "Filling Parent List." << endl;
    1124   Walker = start;
    1125   while (Walker->next != end) {
     1319  atom *Walker = mol->start;
     1320  while (Walker->next != mol->end) {
    11261321    Walker = Walker->next;
    11271322    ParentList[Walker->father->nr] = Walker;
    11281323    // Outputting List for debugging
    1129     *out << Verbose(4) << "Son["<< Walker->father->nr <<"] of " << Walker->father <<  " is " << ParentList[Walker->father->nr] << "." << endl;
    1130   }
    1131 
     1324    *out << Verbose(4) << "Son[" << Walker->father->nr << "] of " << Walker->father << " is " << ParentList[Walker->father->nr] << "." << endl;
     1325  }
     1326
     1327}
     1328;
     1329
     1330void BuildInducedSubgraph_Finalize(ofstream *out, atom **&ParentList)
     1331{
     1332  Free(&ParentList);
     1333}
     1334;
     1335
     1336bool BuildInducedSubgraph_CreateBondsFromParent(ofstream *out, molecule *mol, const molecule *Father, atom **&ParentList)
     1337{
     1338  bool status = true;
     1339  atom *Walker = NULL;
     1340  atom *OtherAtom = NULL;
    11321341  // check each entry of parent list and if ok (one-to-and-onto matching) create bonds
    11331342  *out << Verbose(3) << "Creating bonds." << endl;
     
    11391348        status = false;
    11401349      } else {
    1141         for (int i=0;i<Father->NumberOfBondsPerAtom[Walker->nr];i++) {
    1142           OtherAtom = Father->ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker);
     1350        for (BondList::const_iterator Runner = Walker->ListOfBonds.begin(); Runner != Walker->ListOfBonds.end(); (++Runner)) {
     1351          OtherAtom = (*Runner)->GetOtherAtom(Walker);
    11431352          if (ParentList[OtherAtom->nr] != NULL) { // if otheratom is also a father of an atom on this molecule, create the bond
    1144             *out << Verbose(4) << "Endpoints of Bond " << Father->ListOfBondsPerAtom[Walker->nr][i] << " are both present: " << ParentList[Walker->nr]->Name << " and " << ParentList[OtherAtom->nr]->Name << "." << endl;
    1145             AddBond(ParentList[Walker->nr], ParentList[OtherAtom->nr], Father->ListOfBondsPerAtom[Walker->nr][i]->BondDegree);
     1353            *out << Verbose(4) << "Endpoints of Bond " << (*Runner) << " are both present: " << ParentList[Walker->nr]->Name << " and " << ParentList[OtherAtom->nr]->Name << "." << endl;
     1354            mol->AddBond(ParentList[Walker->nr], ParentList[OtherAtom->nr], (*Runner)->BondDegree);
    11461355          }
    11471356        }
     
    11491358    }
    11501359  }
    1151 
    1152   Free(&ParentList);
     1360  return status;
     1361}
     1362;
     1363
     1364/** Adds bond structure to this molecule from \a Father molecule.
     1365 * This basically causes this molecule to become an induced subgraph of the \a Father, i.e. for every bond in Father
     1366 * with end points present in this molecule, bond is created in this molecule.
     1367 * Special care was taken to ensure that this is of complexity O(N), where N is the \a Father's molecule::AtomCount.
     1368 * \param *out output stream for debugging
     1369 * \param *Father father molecule
     1370 * \return true - is induced subgraph, false - there are atoms with fathers not in \a Father
     1371 * \todo not checked, not fully working probably
     1372 */
     1373bool molecule::BuildInducedSubgraph(ofstream *out, const molecule *Father)
     1374{
     1375  bool status = true;
     1376  atom **ParentList = NULL;
     1377
     1378  *out << Verbose(2) << "Begin of BuildInducedSubgraph." << endl;
     1379  BuildInducedSubgraph_Init(out, ParentList, Father->AtomCount);
     1380  BuildInducedSubgraph_FillParentList(out, this, Father, ParentList);
     1381  status = BuildInducedSubgraph_CreateBondsFromParent(out, this, Father, ParentList);
     1382  BuildInducedSubgraph_Finalize(out, ParentList);
    11531383  *out << Verbose(2) << "End of BuildInducedSubgraph." << endl;
    11541384  return status;
    1155 };
    1156 
     1385}
     1386;
    11571387
    11581388/** For a given keyset \a *Fragment, checks whether it is connected in the current molecule.
     
    11731403  // count number of atoms in graph
    11741404  size = 0;
    1175   for(KeySet::iterator runner = Fragment->begin(); runner != Fragment->end(); runner++)
     1405  for (KeySet::iterator runner = Fragment->begin(); runner != Fragment->end(); runner++)
    11761406    size++;
    11771407  if (size > 1)
    1178     for(KeySet::iterator runner = Fragment->begin(); runner != Fragment->end(); runner++) {
     1408    for (KeySet::iterator runner = Fragment->begin(); runner != Fragment->end(); runner++) {
    11791409      Walker = FindAtom(*runner);
    11801410      BondStatus = false;
    1181       for(KeySet::iterator runners = Fragment->begin(); runners != Fragment->end(); runners++) {
     1411      for (KeySet::iterator runners = Fragment->begin(); runners != Fragment->end(); runners++) {
    11821412        Walker2 = FindAtom(*runners);
    1183         for (int i=0;i<NumberOfBondsPerAtom[Walker->nr]; i++) {
    1184           if (ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker) == Walker2) {
     1413        for (BondList::const_iterator Runner = Walker->ListOfBonds.begin(); Runner != Walker->ListOfBonds.end(); (++Runner)) {
     1414          if ((*Runner)->GetOtherAtom(Walker) == Walker2) {
    11851415            BondStatus = true;
    11861416            break;
Note: See TracChangeset for help on using the changeset viewer.