Changeset ba1823


Ignore:
Timestamp:
Oct 25, 2011, 12:08:02 PM (13 years ago)
Author:
Frederik Heber <heber@…>
Branches:
Action_Thermostats, Add_AtomRandomPerturbation, Add_FitFragmentPartialChargesAction, Add_RotateAroundBondAction, Add_SelectAtomByNameAction, Added_ParseSaveFragmentResults, AddingActions_SaveParseParticleParameters, Adding_Graph_to_ChangeBondActions, Adding_MD_integration_tests, Adding_ParticleName_to_Atom, Adding_StructOpt_integration_tests, AtomFragments, Automaking_mpqc_open, AutomationFragmentation_failures, Candidate_v1.5.4, Candidate_v1.6.0, Candidate_v1.6.1, ChangeBugEmailaddress, ChangingTestPorts, ChemicalSpaceEvaluator, CombiningParticlePotentialParsing, Combining_Subpackages, Debian_Package_split, Debian_package_split_molecuildergui_only, Disabling_MemDebug, Docu_Python_wait, EmpiricalPotential_contain_HomologyGraph, EmpiricalPotential_contain_HomologyGraph_documentation, Enable_parallel_make_install, Enhance_userguide, Enhanced_StructuralOptimization, Enhanced_StructuralOptimization_continued, Example_ManyWaysToTranslateAtom, Exclude_Hydrogens_annealWithBondGraph, FitPartialCharges_GlobalError, Fix_BoundInBox_CenterInBox_MoleculeActions, Fix_ChargeSampling_PBC, Fix_ChronosMutex, Fix_FitPartialCharges, Fix_FitPotential_needs_atomicnumbers, Fix_ForceAnnealing, Fix_IndependentFragmentGrids, Fix_ParseParticles, Fix_ParseParticles_split_forward_backward_Actions, Fix_PopActions, Fix_QtFragmentList_sorted_selection, Fix_Restrictedkeyset_FragmentMolecule, Fix_StatusMsg, Fix_StepWorldTime_single_argument, Fix_Verbose_Codepatterns, Fix_fitting_potentials, Fixes, ForceAnnealing_goodresults, ForceAnnealing_oldresults, ForceAnnealing_tocheck, ForceAnnealing_with_BondGraph, ForceAnnealing_with_BondGraph_continued, ForceAnnealing_with_BondGraph_continued_betteresults, ForceAnnealing_with_BondGraph_contraction-expansion, FragmentAction_writes_AtomFragments, FragmentMolecule_checks_bonddegrees, GeometryObjects, Gui_Fixes, Gui_displays_atomic_force_velocity, ImplicitCharges, IndependentFragmentGrids, IndependentFragmentGrids_IndividualZeroInstances, IndependentFragmentGrids_IntegrationTest, IndependentFragmentGrids_Sole_NN_Calculation, JobMarket_RobustOnKillsSegFaults, JobMarket_StableWorkerPool, JobMarket_unresolvable_hostname_fix, MoreRobust_FragmentAutomation, ODR_violation_mpqc_open, PartialCharges_OrthogonalSummation, PdbParser_setsAtomName, PythonUI_with_named_parameters, QtGui_reactivate_TimeChanged_changes, Recreated_GuiChecks, Rewrite_FitPartialCharges, RotateToPrincipalAxisSystem_UndoRedo, SaturateAtoms_findBestMatching, SaturateAtoms_singleDegree, StoppableMakroAction, Subpackage_CodePatterns, Subpackage_JobMarket, Subpackage_LinearAlgebra, Subpackage_levmar, Subpackage_mpqc_open, Subpackage_vmg, Switchable_LogView, ThirdParty_MPQC_rebuilt_buildsystem, TrajectoryDependenant_MaxOrder, TremoloParser_IncreasedPrecision, TremoloParser_MultipleTimesteps, TremoloParser_setsAtomName, Ubuntu_1604_changes, stable
Children:
d9a032
Parents:
708798
git-author:
Frederik Heber <heber@…> (10/18/11 09:12:25)
git-committer:
Frederik Heber <heber@…> (10/25/11 12:08:02)
Message:

Moved all helpers fragmentation functions into folder src/Fragmentation.

Location:
src
Files:
2 added
2 edited

Legend:

Unmodified
Added
Removed
  • src/Makefile.am

    r708798 rba1823  
    175175  moleculelist.cpp \
    176176  molecule.cpp \
     177  Fragmentation/fragmentation_helpers.cpp \
    177178  molecule_fragmentation.cpp \
    178179  molecule_geometry.cpp \
     
    198199  graph.hpp \
    199200  linkedcell.hpp \
     201  Fragmentation/fragmentation_helpers.hpp \
    200202  molecule.hpp \
    201203  ThermoStatContainer.hpp \
  • src/molecule_fragmentation.cpp

    r708798 rba1823  
    2929#include "config.hpp"
    3030#include "Element/element.hpp"
     31#include "Element/periodentafel.hpp"
     32#include "Fragmentation/fragmentation_helpers.hpp"
    3133#include "Graph/BondGraph.hpp"
    3234#include "Graph/CheckAgainstAdjacencyFile.hpp"
     
    3638#include "LinearAlgebra/RealSpaceMatrix.hpp"
    3739#include "molecule.hpp"
    38 #include "Element/periodentafel.hpp"
    3940#include "World.hpp"
    4041
     
    6465  DoLog(1) && (Log() << Verbose(1) << "Upper limit for this subgraph is " << FragmentCount << " for " << NoNonHydrogen << " non-H atoms with maximum bond degree of " << c << "." << endl);
    6566  return FragmentCount;
    66 };
    67 
    68 /** Scans a single line for number and puts them into \a KeySet.
    69  * \param *out output stream for debugging
    70  * \param *buffer buffer to scan
    71  * \param &CurrentSet filled KeySet on return
    72  * \return true - at least one valid atom id parsed, false - CurrentSet is empty
    73  */
    74 bool ScanBufferIntoKeySet(char *buffer, KeySet &CurrentSet)
    75 {
    76   stringstream line;
    77   int AtomNr;
    78   int status = 0;
    79 
    80   line.str(buffer);
    81   while (!line.eof()) {
    82     line >> AtomNr;
    83     if (AtomNr >= 0) {
    84       CurrentSet.insert(AtomNr);  // insert at end, hence in same order as in file!
    85       status++;
    86     } // else it's "-1" or else and thus must not be added
    87   }
    88   DoLog(1) && (Log() << Verbose(1) << "The scanned KeySet is ");
    89   for(KeySet::iterator runner = CurrentSet.begin(); runner != CurrentSet.end(); runner++) {
    90     DoLog(0) && (Log() << Verbose(0) << (*runner) << "\t");
    91   }
    92   DoLog(0) && (Log() << Verbose(0) << endl);
    93   return (status != 0);
    94 };
    95 
    96 /** Parses the KeySet file and fills \a *FragmentList from the known molecule structure.
    97  * Does two-pass scanning:
    98  * -# Scans the keyset file and initialises a temporary graph
    99  * -# Scans TEFactors file and sets the TEFactor of each key set in the temporary graph accordingly
    100  * Finally, the temporary graph is inserted into the given \a FragmentList for return.
    101  * \param &path path to file
    102  * \param *FragmentList empty, filled on return
    103  * \return true - parsing successfully, false - failure on parsing (FragmentList will be NULL)
    104  */
    105 bool ParseKeySetFile(std::string &path, Graph *&FragmentList)
    106 {
    107   bool status = true;
    108   ifstream InputFile;
    109   stringstream line;
    110   GraphTestPair testGraphInsert;
    111   int NumberOfFragments = 0;
    112   string filename;
    113 
    114   if (FragmentList == NULL) { // check list pointer
    115     FragmentList = new Graph;
    116   }
    117 
    118   // 1st pass: open file and read
    119   DoLog(1) && (Log() << Verbose(1) << "Parsing the KeySet file ... " << endl);
    120   filename = path + KEYSETFILE;
    121   InputFile.open(filename.c_str());
    122   if (InputFile.good()) {
    123     // each line represents a new fragment
    124     char buffer[MAXSTRINGSIZE];
    125     // 1. parse keysets and insert into temp. graph
    126     while (!InputFile.eof()) {
    127       InputFile.getline(buffer, MAXSTRINGSIZE);
    128       KeySet CurrentSet;
    129       if ((strlen(buffer) > 0) && (ScanBufferIntoKeySet(buffer, CurrentSet))) {  // if at least one valid atom was added, write config
    130         testGraphInsert = FragmentList->insert(GraphPair (CurrentSet,pair<int,double>(NumberOfFragments++,1)));  // store fragment number and current factor
    131         if (!testGraphInsert.second) {
    132           DoeLog(0) && (eLog()<< Verbose(0) << "KeySet file must be corrupt as there are two equal key sets therein!" << endl);
    133           performCriticalExit();
    134         }
    135       }
    136     }
    137     // 2. Free and done
    138     InputFile.close();
    139     InputFile.clear();
    140     DoLog(1) && (Log() << Verbose(1) << "\t ... done." << endl);
    141   } else {
    142     DoLog(1) && (Log() << Verbose(1) << "\t ... File " << filename << " not found." << endl);
    143     status = false;
    144   }
    145 
    146   return status;
    147 };
    148 
    149 /** Parses the TE factors file and fills \a *FragmentList from the known molecule structure.
    150  * -# Scans TEFactors file and sets the TEFactor of each key set in the temporary graph accordingly
    151  * \param *out output stream for debugging
    152  * \param *path path to file
    153  * \param *FragmentList graph whose nodes's TE factors are set on return
    154  * \return true - parsing successfully, false - failure on parsing
    155  */
    156 bool ParseTEFactorsFile(char *path, Graph *FragmentList)
    157 {
    158   bool status = true;
    159   ifstream InputFile;
    160   stringstream line;
    161   GraphTestPair testGraphInsert;
    162   int NumberOfFragments = 0;
    163   double TEFactor;
    164   char filename[MAXSTRINGSIZE];
    165 
    166   if (FragmentList == NULL) { // check list pointer
    167     FragmentList = new Graph;
    168   }
    169 
    170   // 2nd pass: open TEFactors file and read
    171   DoLog(1) && (Log() << Verbose(1) << "Parsing the TEFactors file ... " << endl);
    172   sprintf(filename, "%s/%s%s", path, FRAGMENTPREFIX, TEFACTORSFILE);
    173   InputFile.open(filename);
    174   if (InputFile != NULL) {
    175     // 3. add found TEFactors to each keyset
    176     NumberOfFragments = 0;
    177     for(Graph::iterator runner = FragmentList->begin();runner != FragmentList->end(); runner++) {
    178       if (!InputFile.eof()) {
    179         InputFile >> TEFactor;
    180         (*runner).second.second = TEFactor;
    181         DoLog(2) && (Log() << Verbose(2) << "Setting " << ++NumberOfFragments << " fragment's TEFactor to " << (*runner).second.second << "." << endl);
    182       } else {
    183         status = false;
    184         break;
    185       }
    186     }
    187     // 4. Free and done
    188     InputFile.close();
    189     DoLog(1) && (Log() << Verbose(1) << "done." << endl);
    190   } else {
    191     DoLog(1) && (Log() << Verbose(1) << "File " << filename << " not found." << endl);
    192     status = false;
    193   }
    194 
    195   return status;
    196 };
    197 
    198 /** Stores key sets to file.
    199  * \param KeySetList Graph with Keysets
    200  * \param &path path to file
    201  * \return true - file written successfully, false - writing failed
    202  */
    203 bool StoreKeySetFile(Graph &KeySetList, std::string &path)
    204 {
    205   bool status =  true;
    206   string line = path + KEYSETFILE;
    207   ofstream output(line.c_str());
    208 
    209   // open KeySet file
    210   DoLog(1) && (Log() << Verbose(1) << "Saving key sets of the total graph ... ");
    211   if(output.good()) {
    212     for(Graph::iterator runner = KeySetList.begin(); runner != KeySetList.end(); runner++) {
    213       for (KeySet::iterator sprinter = (*runner).first.begin();sprinter != (*runner).first.end(); sprinter++) {
    214         if (sprinter != (*runner).first.begin())
    215           output << "\t";
    216         output << *sprinter;
    217       }
    218       output << endl;
    219     }
    220     DoLog(0) && (Log() << Verbose(0) << "done." << endl);
    221   } else {
    222     DoeLog(0) && (eLog()<< Verbose(0) << "Unable to open " << line << " for writing keysets!" << endl);
    223     performCriticalExit();
    224     status = false;
    225   }
    226   output.close();
    227   output.clear();
    228 
    229   return status;
    230 };
    231 
    232 
    233 /** Stores TEFactors to file.
    234  * \param *out output stream for debugging
    235  * \param KeySetList Graph with factors
    236  * \param *path path to file
    237  * \return true - file written successfully, false - writing failed
    238  */
    239 bool StoreTEFactorsFile(Graph &KeySetList, char *path)
    240 {
    241   ofstream output;
    242   bool status =  true;
    243   string line;
    244 
    245   // open TEFactors file
    246   line = path;
    247   line.append("/");
    248   line += FRAGMENTPREFIX;
    249   line += TEFACTORSFILE;
    250   output.open(line.c_str(), ios::out);
    251   DoLog(1) && (Log() << Verbose(1) << "Saving TEFactors of the total graph ... ");
    252   if(output != NULL) {
    253     for(Graph::iterator runner = KeySetList.begin(); runner != KeySetList.end(); runner++)
    254       output << (*runner).second.second << endl;
    255     DoLog(1) && (Log() << Verbose(1) << "done." << endl);
    256   } else {
    257     DoLog(1) && (Log() << Verbose(1) << "failed to open " << line << "." << endl);
    258     status = false;
    259   }
    260   output.close();
    261 
    262   return status;
    263 };
    264 
    265 /** For a given graph, sorts KeySets into a (index, keyset) map.
    266  * \param *GlobalKeySetList list of keysets with global ids (valid in "this" molecule) needed for adaptive increase
    267  * \return map from index to keyset
    268  */
    269 map<int,KeySet> * GraphToIndexedKeySet(Graph *GlobalKeySetList)
    270 {
    271   map<int,KeySet> *IndexKeySetList = new map<int,KeySet>;
    272   for(Graph::iterator runner = GlobalKeySetList->begin(); runner != GlobalKeySetList->end(); runner++) {
    273     IndexKeySetList->insert( pair<int,KeySet>(runner->second.first,runner->first) );
    274   }
    275   return IndexKeySetList;
    276 };
    277 
    278 /** Inserts a (\a No, \a value) pair into the list, overwriting present one.
    279  * Note if values are equal, No will decided on which is first
    280  * \param *out output stream for debugging
    281  * \param &AdaptiveCriteriaList list to insert into
    282  * \param &IndexedKeySetList list to find key set for a given index \a No
    283  * \param FragOrder current bond order of fragment
    284  * \param No index of keyset
    285  * \param value energy value
    286  */
    287 void InsertIntoAdaptiveCriteriaList(map<int, pair<double,int> > *AdaptiveCriteriaList, map<int,KeySet> &IndexKeySetList, int FragOrder, int No, double Value)
    288 {
    289   map<int,KeySet>::iterator marker = IndexKeySetList.find(No);    // find keyset to Frag No.
    290   if (marker != IndexKeySetList.end()) {  // if found
    291     Value *= 1 + MYEPSILON*(*((*marker).second.begin()));     // in case of equal energies this makes them not equal without changing anything actually
    292     // as the smallest number in each set has always been the root (we use global id to keep the doubles away), seek smallest and insert into AtomMask
    293     pair <map<int, pair<double,int> >::iterator, bool> InsertedElement = AdaptiveCriteriaList->insert( make_pair(*((*marker).second.begin()), pair<double,int>( fabs(Value), FragOrder) ));
    294     map<int, pair<double,int> >::iterator PresentItem = InsertedElement.first;
    295     if (!InsertedElement.second) { // this root is already present
    296       if ((*PresentItem).second.second < FragOrder)  // if order there is lower, update entry with higher-order term
    297         //if ((*PresentItem).second.first < (*runner).first)    // as higher-order terms are not always better, we skip this part (which would always include this site into adaptive increase)
    298         {  // if value is smaller, update value and order
    299         (*PresentItem).second.first = fabs(Value);
    300         (*PresentItem).second.second = FragOrder;
    301         DoLog(2) && (Log() << Verbose(2) << "Updated element (" <<  (*PresentItem).first << ",[" << (*PresentItem).second.first << "," << (*PresentItem).second.second << "])." << endl);
    302       } else {
    303         DoLog(2) && (Log() << Verbose(2) << "Did not update element " <<  (*PresentItem).first << " as " << FragOrder << " is less than or equal to " << (*PresentItem).second.second << "." << endl);
    304       }
    305     } else {
    306       DoLog(2) && (Log() << Verbose(2) << "Inserted element (" <<  (*PresentItem).first << ",[" << (*PresentItem).second.first << "," << (*PresentItem).second.second << "])." << endl);
    307     }
    308   } else {
    309     DoLog(1) && (Log() << Verbose(1) << "No Fragment under No. " << No << "found." << endl);
    310   }
    311 };
    312 
    313 /** Counts lines in file.
    314  * Note we are scanning lines from current position, not from beginning.
    315  * \param InputFile file to be scanned.
    316  */
    317 int CountLinesinFile(ifstream &InputFile)
    318 {
    319   char *buffer = new char[MAXSTRINGSIZE];
    320   int lines=0;
    321 
    322   int PositionMarker = InputFile.tellg();  // not needed as Inputfile is copied, given by value, not by ref
    323   // count the number of lines, i.e. the number of fragments
    324   InputFile.getline(buffer, MAXSTRINGSIZE); // skip comment lines
    325   InputFile.getline(buffer, MAXSTRINGSIZE);
    326   while(!InputFile.eof()) {
    327     InputFile.getline(buffer, MAXSTRINGSIZE);
    328     lines++;
    329   }
    330   InputFile.seekg(PositionMarker, ios::beg);
    331   delete[](buffer);
    332   return lines;
    333 };
    334 
    335 
    336 /** Scans the adaptive order file and insert (index, value) into map.
    337  * \param &path path to ENERGYPERFRAGMENT file (may be NULL if Order is non-negative)
    338  * \param &IndexedKeySetList list to find key set for a given index \a No
    339  * \return adaptive criteria list from file
    340  */
    341 map<int, pair<double,int> > * ScanAdaptiveFileIntoMap(std::string &path, map<int,KeySet> &IndexKeySetList)
    342 {
    343   map<int, pair<double,int> > *AdaptiveCriteriaList = new map<int, pair<double,int> >;
    344   int No = 0, FragOrder = 0;
    345   double Value = 0.;
    346   char buffer[MAXSTRINGSIZE];
    347   string filename = path + ENERGYPERFRAGMENT;
    348   ifstream InputFile(filename.c_str());
    349 
    350   if (InputFile.fail()) {
    351     DoeLog(1) && (eLog() << Verbose(1) << "Cannot find file " << filename << "." << endl);
    352     return AdaptiveCriteriaList;
    353   }
    354 
    355   if (CountLinesinFile(InputFile) > 0) {
    356     // each line represents a fragment root (Atom::Nr) id and its energy contribution
    357     InputFile.getline(buffer, MAXSTRINGSIZE); // skip comment lines
    358     InputFile.getline(buffer, MAXSTRINGSIZE);
    359     while(!InputFile.eof()) {
    360       InputFile.getline(buffer, MAXSTRINGSIZE);
    361       if (strlen(buffer) > 2) {
    362         //Log() << Verbose(2) << "Scanning: " << buffer << endl;
    363         stringstream line(buffer);
    364         line >> FragOrder;
    365         line >> ws >> No;
    366         line >> ws >> Value; // skip time entry
    367         line >> ws >> Value;
    368         No -= 1;  // indices start at 1 in file, not 0
    369         //Log() << Verbose(2) << " - yields (" << No << "," << Value << ", " << FragOrder << ")" << endl;
    370 
    371         // clean the list of those entries that have been superceded by higher order terms already
    372         InsertIntoAdaptiveCriteriaList(AdaptiveCriteriaList, IndexKeySetList, FragOrder, No, Value);
    373       }
    374     }
    375     // close and done
    376     InputFile.close();
    377     InputFile.clear();
    378   }
    379 
    380   return AdaptiveCriteriaList;
    381 };
    382 
    383 /** Maps adaptive criteria list back onto (Value, (Root Nr., Order))
    384  * (i.e. sorted by value to pick the highest ones)
    385  * \param *out output stream for debugging
    386  * \param &AdaptiveCriteriaList list to insert into
    387  * \param *mol molecule with atoms
    388  * \return remapped list
    389  */
    390 map<double, pair<int,int> >  * ReMapAdaptiveCriteriaListToValue(map<int, pair<double,int> > *AdaptiveCriteriaList, molecule *mol)
    391 {
    392   atom *Walker = NULL;
    393   map<double, pair<int,int> > *FinalRootCandidates = new map<double, pair<int,int> > ;
    394   DoLog(1) && (Log() << Verbose(1) << "Root candidate list is: " << endl);
    395   for(map<int, pair<double,int> >::iterator runner = AdaptiveCriteriaList->begin(); runner != AdaptiveCriteriaList->end(); runner++) {
    396     Walker = mol->FindAtom((*runner).first);
    397     if (Walker != NULL) {
    398       //if ((*runner).second.second >= Walker->AdaptiveOrder) { // only insert if this is an "active" root site for the current order
    399       if (!Walker->MaxOrder) {
    400         DoLog(2) && (Log() << Verbose(2) << "(" << (*runner).first << ",[" << (*runner).second.first << "," << (*runner).second.second << "])" << endl);
    401         FinalRootCandidates->insert( make_pair( (*runner).second.first, pair<int,int>((*runner).first, (*runner).second.second) ) );
    402       } else {
    403         DoLog(2) && (Log() << Verbose(2) << "Excluding (" << *Walker << ", " << (*runner).first << ",[" << (*runner).second.first << "," << (*runner).second.second << "]), as it has reached its maximum order." << endl);
    404       }
    405     } else {
    406       DoeLog(0) && (eLog()<< Verbose(0) << "Atom No. " << (*runner).second.first << " was not found in this molecule." << endl);
    407       performCriticalExit();
    408     }
    409   }
    410   return FinalRootCandidates;
    411 };
    412 
    413 /** Marks all candidate sites for update if below adaptive threshold.
    414  * Picks a given number of highest values and set *AtomMask to true.
    415  * \param *out output stream for debugging
    416  * \param *AtomMask defines true/false per global Atom::Nr to mask in/out each nuclear site, used to activate given number of site to increment order adaptively
    417  * \param FinalRootCandidates list candidates to check
    418  * \param Order desired order
    419  * \param *mol molecule with atoms
    420  * \return true - if update is necessary, false - not
    421  */
    422 bool MarkUpdateCandidates(bool *AtomMask, map<double, pair<int,int> > &FinalRootCandidates, int Order, molecule *mol)
    423 {
    424   atom *Walker = NULL;
    425   int No = -1;
    426   bool status = false;
    427   for(map<double, pair<int,int> >::iterator runner = FinalRootCandidates.upper_bound(pow(10.,Order)); runner != FinalRootCandidates.end(); runner++) {
    428     No = (*runner).second.first;
    429     Walker = mol->FindAtom(No);
    430     //if (Walker->AdaptiveOrder < MinimumRingSize[Walker->getNr()]) {
    431       DoLog(2) && (Log() << Verbose(2) << "Root " << No << " is still above threshold (10^{" << Order <<"}: " << runner->first << ", setting entry " << No << " of Atom mask to true." << endl);
    432       AtomMask[No] = true;
    433       status = true;
    434     //} else
    435       //Log() << Verbose(2) << "Root " << No << " is still above threshold (10^{" << Order <<"}: " << runner->first << ", however MinimumRingSize of " << MinimumRingSize[Walker->getNr()] << " does not allow further adaptive increase." << endl;
    436   }
    437   return status;
    438 };
    439 
    440 /** print atom mask for debugging.
    441  * \param *out output stream for debugging
    442  * \param *AtomMask defines true/false per global Atom::Nr to mask in/out each nuclear site, used to activate given number of site to increment order adaptively
    443  * \param AtomCount number of entries in \a *AtomMask
    444  */
    445 void PrintAtomMask(bool *AtomMask, int AtomCount)
    446 {
    447   DoLog(2) && (Log() << Verbose(2) << "              ");
    448   for(int i=0;i<AtomCount;i++)
    449     DoLog(0) && (Log() << Verbose(0) << (i % 10));
    450   DoLog(0) && (Log() << Verbose(0) << endl);
    451   DoLog(2) && (Log() << Verbose(2) << "Atom mask is: ");
    452   for(int i=0;i<AtomCount;i++)
    453     DoLog(0) && (Log() << Verbose(0) << (AtomMask[i] ? "t" : "f"));
    454   DoLog(0) && (Log() << Verbose(0) << endl);
    45567};
    45668
     
    1045657};
    1046658
    1047 
    1048 /** Clears the touched list
    1049  * \param *out output stream for debugging
    1050  * \param verbosity verbosity level
    1051  * \param *&TouchedList touched list
    1052  * \param SubOrder current suborder
    1053  * \param TouchedIndex currently touched
    1054  */
    1055 void SPFragmentGenerator_ClearingTouched(int verbosity, int *&TouchedList, int SubOrder, int &TouchedIndex)
    1056 {
    1057   Log() << Verbose(1+verbosity) << "Clearing touched list." << endl;
    1058   for (TouchedIndex=SubOrder+1;TouchedIndex--;)  // empty touched list
    1059     TouchedList[TouchedIndex] = -1;
    1060   TouchedIndex = 0;
    1061 
    1062 }
    1063 
    1064 /** Adds the current combination of the power set to the snake stack.
    1065  * \param *out output stream for debugging
    1066  * \param verbosity verbosity level
    1067  * \param CurrentCombination
    1068  * \param SetDimension maximum number of bits in power set
    1069  * \param *FragmentSet snake stack to remove from
    1070  * \param &BondsSet set of bonds
    1071  * \param *&TouchedList touched list
    1072  * \param TouchedIndex currently touched
    1073  * \return number of set bits
    1074  */
    1075 int AddPowersetToSnakeStack(int verbosity, int CurrentCombination, int SetDimension, KeySet *FragmentSet, std::vector<bond *> &BondsSet, int *&TouchedList, int &TouchedIndex)
    1076 {
    1077   atom *OtherWalker = NULL;
    1078   bool bit = false;
    1079   KeySetTestPair TestKeySetInsert;
    1080 
    1081   int Added = 0;
    1082   for (int j=0;j<SetDimension;j++) {  // pull out every bit by shifting
    1083     bit = ((CurrentCombination & (1 << j)) != 0);  // mask the bit for the j-th bond
    1084     if (bit) {  // if bit is set, we add this bond partner
    1085       OtherWalker = BondsSet[j]->rightatom;  // rightatom is always the one more distant, i.e. the one to add
    1086       //Log() << Verbose(1+verbosity) << "Current Bond is " << BondsSet[j] << ", checking on " << *OtherWalker << "." << endl;
    1087       Log() << Verbose(2+verbosity) << "Adding " << *OtherWalker << " with nr " << OtherWalker->getNr() << "." << endl;
    1088       TestKeySetInsert = FragmentSet->insert(OtherWalker->getNr());
    1089       if (TestKeySetInsert.second) {
    1090         TouchedList[TouchedIndex++] = OtherWalker->getNr();  // note as added
    1091         Added++;
    1092       } else {
    1093         Log() << Verbose(2+verbosity) << "This was item was already present in the keyset." << endl;
    1094       }
    1095     } else {
    1096       Log() << Verbose(2+verbosity) << "Not adding." << endl;
    1097     }
    1098   }
    1099   return Added;
    1100 };
    1101 
    1102 /** Counts the number of elements in a power set.
    1103  * \param SetFirst begin iterator first bond
    1104  * \param SetLast end iterator
    1105  * \param *&TouchedList touched list
    1106  * \param TouchedIndex currently touched
    1107  * \return number of elements
    1108  */
    1109 int CountSetMembers(std::list<bond *>::const_iterator SetFirst, std::list<bond *>::const_iterator SetLast, int *&TouchedList, int TouchedIndex)
    1110 {
    1111   int SetDimension = 0;
    1112   for( std::list<bond *>::const_iterator Binder = SetFirst;
    1113       Binder != SetLast;
    1114       ++Binder) {
    1115     for (int k=TouchedIndex;k--;) {
    1116       if ((*Binder)->Contains(TouchedList[k]))   // if we added this very endpiece
    1117         SetDimension++;
    1118     }
    1119   }
    1120   return SetDimension;
    1121 };
    1122 
    1123 /** Fills a list of bonds from another
    1124  * \param *BondsList bonds array/vector to fill
    1125  * \param SetFirst begin iterator first bond
    1126  * \param SetLast end iterator
    1127  * \param *&TouchedList touched list
    1128  * \param TouchedIndex currently touched
    1129  * \return number of elements
    1130  */
    1131 int FillBondsList(std::vector<bond *> &BondsList, std::list<bond *>::const_iterator SetFirst, std::list<bond *>::const_iterator SetLast, int *&TouchedList, int TouchedIndex)
    1132 {
    1133   int SetDimension = 0;
    1134   for( std::list<bond *>::const_iterator Binder = SetFirst;
    1135       Binder != SetLast;
    1136       ++Binder) {
    1137     for (int k=0;k<TouchedIndex;k++) {
    1138       if ((*Binder)->leftatom->getNr() == TouchedList[k])   // leftatom is always the closer one
    1139         BondsList[SetDimension++] = (*Binder);
    1140     }
    1141   }
    1142   return SetDimension;
    1143 };
    1144 
    1145 /** Remove all items that were added on this SP level.
    1146  * \param *out output stream for debugging
    1147  * \param verbosity verbosity level
    1148  * \param *FragmentSet snake stack to remove from
    1149  * \param *&TouchedList touched list
    1150  * \param TouchedIndex currently touched
    1151  */
    1152 void RemoveAllTouchedFromSnakeStack(int verbosity, KeySet *FragmentSet, int *&TouchedList, int &TouchedIndex)
    1153 {
    1154   int Removal = 0;
    1155   for(int j=0;j<TouchedIndex;j++) {
    1156     Removal = TouchedList[j];
    1157     Log() << Verbose(2+verbosity) << "Removing item nr. " << Removal << " from snake stack." << endl;
    1158     FragmentSet->erase(Removal);
    1159     TouchedList[j] = -1;
    1160   }
    1161   DoLog(2) && (Log() << Verbose(2) << "Remaining local nr.s on snake stack are: ");
    1162   for(KeySet::iterator runner = FragmentSet->begin(); runner != FragmentSet->end(); runner++)
    1163     DoLog(0) && (Log() << Verbose(0) << (*runner) << " ");
    1164   DoLog(0) && (Log() << Verbose(0) << endl);
    1165   TouchedIndex = 0; // set Index to 0 for list of atoms added on this level
    1166 };
    1167 
    1168659/** From a given set of Bond sorted by Shortest Path distance, create all possible fragments of size \a SetDimension.
    1169660 * -# loops over every possible combination (2^dimension of edge set)
     
    1255746};
    1256747
    1257 /** Allocates memory for UniqueFragments::BondsPerSPList.
    1258  * \param *out output stream
    1259  * \param Order bond order (limits BFS exploration and "number of digits" in power set generation
    1260  * \param FragmentSearch UniqueFragments
    1261  * \sa FreeSPList()
    1262  */
    1263 void InitialiseSPList(int Order, struct UniqueFragments &FragmentSearch)
    1264 {
    1265   FragmentSearch.BondsPerSPList.resize(Order);
    1266   FragmentSearch.BondsPerSPCount = new int[Order];
    1267   for (int i=Order;i--;) {
    1268     FragmentSearch.BondsPerSPCount[i] = 0;
    1269   }
    1270 };
    1271 
    1272 /** Free's memory for for UniqueFragments::BondsPerSPList.
    1273  * \param *out output stream
    1274  * \param Order bond order (limits BFS exploration and "number of digits" in power set generation
    1275  * \param FragmentSearch UniqueFragments\
    1276  * \sa InitialiseSPList()
    1277  */
    1278 void FreeSPList(int Order, struct UniqueFragments &FragmentSearch)
    1279 {
    1280   delete[](FragmentSearch.BondsPerSPCount);
    1281 };
    1282 
    1283 /** Sets FragmenSearch to initial value.
    1284  * Sets UniqueFragments::ShortestPathList entries to zero, UniqueFragments::BondsPerSPCount to zero (except zero level to 1) and
    1285  * adds initial bond UniqueFragments::Root to UniqueFragments::Root to UniqueFragments::BondsPerSPList
    1286  * \param *out output stream
    1287  * \param Order bond order (limits BFS exploration and "number of digits" in power set generation
    1288  * \param FragmentSearch UniqueFragments
    1289  * \sa FreeSPList()
    1290  */
    1291 void SetSPList(int Order, struct UniqueFragments &FragmentSearch)
    1292 {
    1293   // prepare Label and SP arrays of the BFS search
    1294   FragmentSearch.ShortestPathList[FragmentSearch.Root->getNr()] = 0;
    1295 
    1296   // prepare root level (SP = 0) and a loop bond denoting Root
    1297   for (int i=Order;i--;)
    1298     FragmentSearch.BondsPerSPCount[i] = 0;
    1299   FragmentSearch.BondsPerSPCount[0] = 1;
    1300   bond *Binder = new bond(FragmentSearch.Root, FragmentSearch.Root);
    1301   FragmentSearch.BondsPerSPList[0].push_back(Binder);
    1302 };
    1303 
    1304 /** Resets UniqueFragments::ShortestPathList and cleans bonds from UniqueFragments::BondsPerSPList.
    1305  * \param *out output stream
    1306  * \param Order bond order (limits BFS exploration and "number of digits" in power set generation
    1307  * \param FragmentSearch UniqueFragments
    1308  * \sa InitialiseSPList()
    1309  */
    1310 void ResetSPList(int Order, struct UniqueFragments &FragmentSearch)
    1311 {
    1312   DoLog(0) && (Log() << Verbose(0) << "Free'ing all found lists. and resetting index lists" << endl);
    1313   for(int i=Order;i--;) {
    1314     DoLog(1) && (Log() << Verbose(1) << "Current SP level is " << i << ": ");
    1315     for (UniqueFragments::BondsPerSP::const_iterator iter = FragmentSearch.BondsPerSPList[i].begin();
    1316         iter != FragmentSearch.BondsPerSPList[i].end();
    1317         ++iter) {
    1318       // Log() << Verbose(0) << "Removing atom " << Binder->leftatom->getNr() << " and " << Binder->rightatom->getNr() << "." << endl; // make sure numbers are local
    1319       FragmentSearch.ShortestPathList[(*iter)->leftatom->getNr()] = -1;
    1320       FragmentSearch.ShortestPathList[(*iter)->rightatom->getNr()] = -1;
    1321     }
    1322     // delete added bonds
    1323     for (UniqueFragments::BondsPerSP::iterator iter = FragmentSearch.BondsPerSPList[i].begin();
    1324         iter != FragmentSearch.BondsPerSPList[i].end();
    1325         ++iter) {
    1326       delete(*iter);
    1327     }
    1328     FragmentSearch.BondsPerSPList[i].clear();
    1329     // also start and end node
    1330     DoLog(0) && (Log() << Verbose(0) << "cleaned." << endl);
    1331   }
    1332 };
    1333 
    1334 
    1335 /** Fills the Bonds per Shortest Path List and set the vertex labels.
    1336  * \param *out output stream
    1337  * \param Order bond order (limits BFS exploration and "number of digits" in power set generation
    1338  * \param FragmentSearch UniqueFragments
    1339  * \param *mol molecule with atoms and bonds
    1340  * \param RestrictedKeySet Restricted vertex set to use in context of molecule
    1341  */
    1342 void FillSPListandLabelVertices(int Order, struct UniqueFragments &FragmentSearch, molecule *mol, KeySet RestrictedKeySet)
    1343 {
    1344   // Actually, we should construct a spanning tree vom the root atom and select all edges therefrom and put them into
    1345   // according shortest path lists. However, we don't. Rather we fill these lists right away, as they do form a spanning
    1346   // tree already sorted into various SP levels. That's why we just do loops over the depth (CurrentSP) and breadth
    1347   // (EdgeinSPLevel) of this tree ...
    1348   // In another picture, the bonds always contain a direction by rightatom being the one more distant from root and hence
    1349   // naturally leftatom forming its predecessor, preventing the BFS"seeker" from continuing in the wrong direction.
    1350   int AtomKeyNr = -1;
    1351   atom *Walker = NULL;
    1352   atom *OtherWalker = NULL;
    1353   atom *Predecessor = NULL;
    1354   bond *Binder = NULL;
    1355   int RootKeyNr = FragmentSearch.Root->GetTrueFather()->getNr();
    1356   int RemainingWalkers = -1;
    1357   int SP = -1;
    1358 
    1359   DoLog(0) && (Log() << Verbose(0) << "Starting BFS analysis ..." << endl);
    1360   for (SP = 0; SP < (Order-1); SP++) {
    1361     DoLog(1) && (Log() << Verbose(1) << "New SP level reached: " << SP << ", creating new SP list with " << FragmentSearch.BondsPerSPCount[SP] << " item(s)");
    1362     if (SP > 0) {
    1363       DoLog(0) && (Log() << Verbose(0) << ", old level closed with " << FragmentSearch.BondsPerSPCount[SP-1] << " item(s)." << endl);
    1364       FragmentSearch.BondsPerSPCount[SP] = 0;
    1365     } else
    1366       DoLog(0) && (Log() << Verbose(0) << "." << endl);
    1367 
    1368     RemainingWalkers = FragmentSearch.BondsPerSPCount[SP];
    1369     for (UniqueFragments::BondsPerSP::const_iterator CurrentEdge = FragmentSearch.BondsPerSPList[SP].begin();
    1370         CurrentEdge != FragmentSearch.BondsPerSPList[SP].end();
    1371         ++CurrentEdge) { /// start till end of this SP level's list
    1372       RemainingWalkers--;
    1373       Walker = (*CurrentEdge)->rightatom;    // rightatom is always the one more distant
    1374       Predecessor = (*CurrentEdge)->leftatom;    // ... and leftatom is predecessor
    1375       AtomKeyNr = Walker->getNr();
    1376       DoLog(0) && (Log() << Verbose(0) << "Current Walker is: " << *Walker << " with nr " << Walker->getNr() << " and SP of " << SP << ", with " << RemainingWalkers << " remaining walkers on this level." << endl);
    1377       // check for new sp level
    1378       // go through all its bonds
    1379       DoLog(1) && (Log() << Verbose(1) << "Going through all bonds of Walker." << endl);
    1380       const BondList& ListOfBonds = Walker->getListOfBonds();
    1381       for (BondList::const_iterator Runner = ListOfBonds.begin();
    1382           Runner != ListOfBonds.end();
    1383           ++Runner) {
    1384         OtherWalker = (*Runner)->GetOtherAtom(Walker);
    1385         if ((RestrictedKeySet.find(OtherWalker->getNr()) != RestrictedKeySet.end())
    1386   #ifdef ADDHYDROGEN
    1387          && (OtherWalker->getType()->getAtomicNumber() != 1)
    1388   #endif
    1389                                                               ) {  // skip hydrogens and restrict to fragment
    1390           DoLog(2) && (Log() << Verbose(2) << "Current partner is " << *OtherWalker << " with nr " << OtherWalker->getNr() << " in bond " << *(*Runner) << "." << endl);
    1391           // set the label if not set (and push on root stack as well)
    1392           if ((OtherWalker != Predecessor) && (OtherWalker->GetTrueFather()->getNr() > RootKeyNr)) { // only pass through those with label bigger than Root's
    1393             FragmentSearch.ShortestPathList[OtherWalker->getNr()] = SP+1;
    1394             DoLog(3) && (Log() << Verbose(3) << "Set Shortest Path to " << FragmentSearch.ShortestPathList[OtherWalker->getNr()] << "." << endl);
    1395             // add the bond in between to the SP list
    1396             Binder = new bond(Walker, OtherWalker); // create a new bond in such a manner, that bond::rightatom is always the one more distant
    1397             FragmentSearch.BondsPerSPList[SP+1].push_back(Binder);
    1398             FragmentSearch.BondsPerSPCount[SP+1]++;
    1399             DoLog(3) && (Log() << Verbose(3) << "Added its bond to SP list, having now " << FragmentSearch.BondsPerSPCount[SP+1] << " item(s)." << endl);
    1400           } else {
    1401             if (OtherWalker != Predecessor)
    1402               DoLog(3) && (Log() << Verbose(3) << "Not passing on, as index of " << *OtherWalker << " " << OtherWalker->GetTrueFather()->getNr() << " is smaller than that of Root " << RootKeyNr << "." << endl);
    1403             else
    1404               DoLog(3) && (Log() << Verbose(3) << "This is my predecessor " << *Predecessor << "." << endl);
    1405           }
    1406         } else Log() << Verbose(2) << "Is not in the restricted keyset or skipping hydrogen " << *OtherWalker << "." << endl;
    1407       }
    1408     }
    1409   }
    1410 };
    1411 
    1412 /** prints the Bonds per Shortest Path list in UniqueFragments.
    1413  * \param *out output stream
    1414  * \param Order bond order (limits BFS exploration and "number of digits" in power set generation
    1415  * \param FragmentSearch UniqueFragments
    1416  */
    1417 void OutputSPList(int Order, struct UniqueFragments &FragmentSearch)
    1418 {
    1419   DoLog(0) && (Log() << Verbose(0) << "Printing all found lists." << endl);
    1420   for(int i=1;i<Order;i++) {    // skip the root edge in the printing
    1421     DoLog(1) && (Log() << Verbose(1) << "Current SP level is " << i << "." << endl);
    1422     for (UniqueFragments::BondsPerSP::const_iterator Binder = FragmentSearch.BondsPerSPList[i].begin();
    1423         Binder != FragmentSearch.BondsPerSPList[i].end();
    1424         ++Binder) {
    1425       DoLog(2) && (Log() << Verbose(2) << *Binder << endl);
    1426     }
    1427   }
    1428 };
    1429 
    1430 /** Simply counts all bonds in all UniqueFragments::BondsPerSPList lists.
    1431  * \param *out output stream
    1432  * \param Order bond order (limits BFS exploration and "number of digits" in power set generation
    1433  * \param FragmentSearch UniqueFragments
    1434  */
    1435 int CountNumbersInBondsList(int Order, struct UniqueFragments &FragmentSearch)
    1436 {
    1437   int SP = -1;  // the Root <-> Root edge must be subtracted!
    1438   for(int i=Order;i--;) { // sum up all found edges
    1439     for (UniqueFragments::BondsPerSP::const_iterator Binder = FragmentSearch.BondsPerSPList[i].begin();
    1440         Binder != FragmentSearch.BondsPerSPList[i].end();
    1441         ++Binder) {
    1442       SP++;
    1443     }
    1444   }
    1445   return SP;
    1446 };
    1447748
    1448749/** Creates a list of all unique fragments of certain vertex size from a given graph \a Fragment for a given root vertex in the context of \a this molecule.
     
    1510811};
    1511812
    1512 bool KeyCompare::operator() (const KeySet SubgraphA, const KeySet SubgraphB) const
    1513 {
    1514   //Log() << Verbose(0) << "my check is used." << endl;
    1515   if (SubgraphA.size() < SubgraphB.size()) {
    1516     return true;
    1517   } else {
    1518     if (SubgraphA.size() > SubgraphB.size()) {
    1519       return false;
    1520     } else {
    1521       KeySet::iterator IteratorA = SubgraphA.begin();
    1522       KeySet::iterator IteratorB = SubgraphB.begin();
    1523       while ((IteratorA != SubgraphA.end()) && (IteratorB != SubgraphB.end())) {
    1524         if ((*IteratorA) <  (*IteratorB))
    1525           return true;
    1526         else if ((*IteratorA) > (*IteratorB)) {
    1527             return false;
    1528           } // else, go on to next index
    1529         IteratorA++;
    1530         IteratorB++;
    1531       } // end of while loop
    1532     }// end of check in case of equal sizes
    1533   }
    1534   return false; // if we reach this point, they are equal
    1535 };
    1536 
    1537 
    1538 /** Combines all KeySets from all orders into single ones (with just unique entries).
    1539  * \param *out output stream for debugging
    1540  * \param *&FragmentList list to fill
    1541  * \param ***FragmentLowerOrdersList
    1542  * \param &RootStack stack with all root candidates (unequal to each atom in complete molecule if adaptive scheme is applied)
    1543  * \param *mol molecule with atoms and bonds
    1544  */
    1545 int CombineAllOrderListIntoOne(Graph *&FragmentList, Graph ***FragmentLowerOrdersList, KeyStack &RootStack, molecule *mol)
    1546 {
    1547   int RootNr = 0;
    1548   int RootKeyNr = 0;
    1549   int StartNr = 0;
    1550   int counter = 0;
    1551   int NumLevels = 0;
    1552   atom *Walker = NULL;
    1553 
    1554   DoLog(0) && (Log() << Verbose(0) << "Combining the lists of all orders per order and finally into a single one." << endl);
    1555   if (FragmentList == NULL) {
    1556     FragmentList = new Graph;
    1557     counter = 0;
    1558   } else {
    1559     counter = FragmentList->size();
    1560   }
    1561 
    1562   StartNr = RootStack.back();
    1563   do {
    1564     RootKeyNr = RootStack.front();
    1565     RootStack.pop_front();
    1566     Walker = mol->FindAtom(RootKeyNr);
    1567     NumLevels = 1 << (Walker->AdaptiveOrder - 1);
    1568     for(int i=0;i<NumLevels;i++) {
    1569       if (FragmentLowerOrdersList[RootNr][i] != NULL) {
    1570         InsertGraphIntoGraph(*FragmentList, (*FragmentLowerOrdersList[RootNr][i]), &counter);
    1571       }
    1572     }
    1573     RootStack.push_back(Walker->getNr());
    1574     RootNr++;
    1575   } while (RootKeyNr != StartNr);
    1576   return counter;
    1577 };
    1578 
    1579 /** Free's memory allocated for all KeySets from all orders.
    1580  * \param *out output stream for debugging
    1581  * \param ***FragmentLowerOrdersList
    1582  * \param &RootStack stack with all root candidates (unequal to each atom in complete molecule if adaptive scheme is applied)
    1583  * \param *mol molecule with atoms and bonds
    1584  */
    1585 void FreeAllOrdersList(Graph ***FragmentLowerOrdersList, KeyStack &RootStack, molecule *mol)
    1586 {
    1587   DoLog(1) && (Log() << Verbose(1) << "Free'ing the lists of all orders per order." << endl);
    1588   int RootNr = 0;
    1589   int RootKeyNr = 0;
    1590   int NumLevels = 0;
    1591   atom *Walker = NULL;
    1592   while (!RootStack.empty()) {
    1593     RootKeyNr = RootStack.front();
    1594     RootStack.pop_front();
    1595     Walker = mol->FindAtom(RootKeyNr);
    1596     NumLevels = 1 << (Walker->AdaptiveOrder - 1);
    1597     for(int i=0;i<NumLevels;i++) {
    1598       if (FragmentLowerOrdersList[RootNr][i] != NULL) {
    1599         delete(FragmentLowerOrdersList[RootNr][i]);
    1600       }
    1601     }
    1602     delete[](FragmentLowerOrdersList[RootNr]);
    1603     RootNr++;
    1604   }
    1605   delete[](FragmentLowerOrdersList);
    1606 };
     813
    1607814
    1608815
Note: See TracChangeset for help on using the changeset viewer.