Changeset ba1823
- Timestamp:
- Oct 25, 2011, 12:08:02 PM (13 years ago)
- 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)
- Location:
- src
- Files:
-
- 2 added
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Makefile.am
r708798 rba1823 175 175 moleculelist.cpp \ 176 176 molecule.cpp \ 177 Fragmentation/fragmentation_helpers.cpp \ 177 178 molecule_fragmentation.cpp \ 178 179 molecule_geometry.cpp \ … … 198 199 graph.hpp \ 199 200 linkedcell.hpp \ 201 Fragmentation/fragmentation_helpers.hpp \ 200 202 molecule.hpp \ 201 203 ThermoStatContainer.hpp \ -
src/molecule_fragmentation.cpp
r708798 rba1823 29 29 #include "config.hpp" 30 30 #include "Element/element.hpp" 31 #include "Element/periodentafel.hpp" 32 #include "Fragmentation/fragmentation_helpers.hpp" 31 33 #include "Graph/BondGraph.hpp" 32 34 #include "Graph/CheckAgainstAdjacencyFile.hpp" … … 36 38 #include "LinearAlgebra/RealSpaceMatrix.hpp" 37 39 #include "molecule.hpp" 38 #include "Element/periodentafel.hpp"39 40 #include "World.hpp" 40 41 … … 64 65 DoLog(1) && (Log() << Verbose(1) << "Upper limit for this subgraph is " << FragmentCount << " for " << NoNonHydrogen << " non-H atoms with maximum bond degree of " << c << "." << endl); 65 66 return FragmentCount; 66 };67 68 /** Scans a single line for number and puts them into \a KeySet.69 * \param *out output stream for debugging70 * \param *buffer buffer to scan71 * \param &CurrentSet filled KeySet on return72 * \return true - at least one valid atom id parsed, false - CurrentSet is empty73 */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 added87 }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 graph99 * -# Scans TEFactors file and sets the TEFactor of each key set in the temporary graph accordingly100 * Finally, the temporary graph is inserted into the given \a FragmentList for return.101 * \param &path path to file102 * \param *FragmentList empty, filled on return103 * \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 pointer115 FragmentList = new Graph;116 }117 118 // 1st pass: open file and read119 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 fragment124 char buffer[MAXSTRINGSIZE];125 // 1. parse keysets and insert into temp. graph126 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 config130 testGraphInsert = FragmentList->insert(GraphPair (CurrentSet,pair<int,double>(NumberOfFragments++,1))); // store fragment number and current factor131 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 done138 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 accordingly151 * \param *out output stream for debugging152 * \param *path path to file153 * \param *FragmentList graph whose nodes's TE factors are set on return154 * \return true - parsing successfully, false - failure on parsing155 */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 pointer167 FragmentList = new Graph;168 }169 170 // 2nd pass: open TEFactors file and read171 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 keyset176 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 done188 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 Keysets200 * \param &path path to file201 * \return true - file written successfully, false - writing failed202 */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 file210 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 debugging235 * \param KeySetList Graph with factors236 * \param *path path to file237 * \return true - file written successfully, false - writing failed238 */239 bool StoreTEFactorsFile(Graph &KeySetList, char *path)240 {241 ofstream output;242 bool status = true;243 string line;244 245 // open TEFactors file246 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 increase267 * \return map from index to keyset268 */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 first280 * \param *out output stream for debugging281 * \param &AdaptiveCriteriaList list to insert into282 * \param &IndexedKeySetList list to find key set for a given index \a No283 * \param FragOrder current bond order of fragment284 * \param No index of keyset285 * \param value energy value286 */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 found291 Value *= 1 + MYEPSILON*(*((*marker).second.begin())); // in case of equal energies this makes them not equal without changing anything actually292 // 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 AtomMask293 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 present296 if ((*PresentItem).second.second < FragOrder) // if order there is lower, update entry with higher-order term297 //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 order299 (*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 ref323 // count the number of lines, i.e. the number of fragments324 InputFile.getline(buffer, MAXSTRINGSIZE); // skip comment lines325 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 No339 * \return adaptive criteria list from file340 */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 contribution357 InputFile.getline(buffer, MAXSTRINGSIZE); // skip comment lines358 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 entry367 line >> ws >> Value;368 No -= 1; // indices start at 1 in file, not 0369 //Log() << Verbose(2) << " - yields (" << No << "," << Value << ", " << FragOrder << ")" << endl;370 371 // clean the list of those entries that have been superceded by higher order terms already372 InsertIntoAdaptiveCriteriaList(AdaptiveCriteriaList, IndexKeySetList, FragOrder, No, Value);373 }374 }375 // close and done376 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 debugging386 * \param &AdaptiveCriteriaList list to insert into387 * \param *mol molecule with atoms388 * \return remapped list389 */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 order399 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 debugging416 * \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 adaptively417 * \param FinalRootCandidates list candidates to check418 * \param Order desired order419 * \param *mol molecule with atoms420 * \return true - if update is necessary, false - not421 */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 //} else435 //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 debugging442 * \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 adaptively443 * \param AtomCount number of entries in \a *AtomMask444 */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);455 67 }; 456 68 … … 1045 657 }; 1046 658 1047 1048 /** Clears the touched list1049 * \param *out output stream for debugging1050 * \param verbosity verbosity level1051 * \param *&TouchedList touched list1052 * \param SubOrder current suborder1053 * \param TouchedIndex currently touched1054 */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 list1059 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 debugging1066 * \param verbosity verbosity level1067 * \param CurrentCombination1068 * \param SetDimension maximum number of bits in power set1069 * \param *FragmentSet snake stack to remove from1070 * \param &BondsSet set of bonds1071 * \param *&TouchedList touched list1072 * \param TouchedIndex currently touched1073 * \return number of set bits1074 */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 shifting1083 bit = ((CurrentCombination & (1 << j)) != 0); // mask the bit for the j-th bond1084 if (bit) { // if bit is set, we add this bond partner1085 OtherWalker = BondsSet[j]->rightatom; // rightatom is always the one more distant, i.e. the one to add1086 //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 added1091 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 bond1104 * \param SetLast end iterator1105 * \param *&TouchedList touched list1106 * \param TouchedIndex currently touched1107 * \return number of elements1108 */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 endpiece1117 SetDimension++;1118 }1119 }1120 return SetDimension;1121 };1122 1123 /** Fills a list of bonds from another1124 * \param *BondsList bonds array/vector to fill1125 * \param SetFirst begin iterator first bond1126 * \param SetLast end iterator1127 * \param *&TouchedList touched list1128 * \param TouchedIndex currently touched1129 * \return number of elements1130 */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 one1139 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 debugging1147 * \param verbosity verbosity level1148 * \param *FragmentSet snake stack to remove from1149 * \param *&TouchedList touched list1150 * \param TouchedIndex currently touched1151 */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 level1166 };1167 1168 659 /** From a given set of Bond sorted by Shortest Path distance, create all possible fragments of size \a SetDimension. 1169 660 * -# loops over every possible combination (2^dimension of edge set) … … 1255 746 }; 1256 747 1257 /** Allocates memory for UniqueFragments::BondsPerSPList.1258 * \param *out output stream1259 * \param Order bond order (limits BFS exploration and "number of digits" in power set generation1260 * \param FragmentSearch UniqueFragments1261 * \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 stream1274 * \param Order bond order (limits BFS exploration and "number of digits" in power set generation1275 * \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) and1285 * adds initial bond UniqueFragments::Root to UniqueFragments::Root to UniqueFragments::BondsPerSPList1286 * \param *out output stream1287 * \param Order bond order (limits BFS exploration and "number of digits" in power set generation1288 * \param FragmentSearch UniqueFragments1289 * \sa FreeSPList()1290 */1291 void SetSPList(int Order, struct UniqueFragments &FragmentSearch)1292 {1293 // prepare Label and SP arrays of the BFS search1294 FragmentSearch.ShortestPathList[FragmentSearch.Root->getNr()] = 0;1295 1296 // prepare root level (SP = 0) and a loop bond denoting Root1297 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 stream1306 * \param Order bond order (limits BFS exploration and "number of digits" in power set generation1307 * \param FragmentSearch UniqueFragments1308 * \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 local1319 FragmentSearch.ShortestPathList[(*iter)->leftatom->getNr()] = -1;1320 FragmentSearch.ShortestPathList[(*iter)->rightatom->getNr()] = -1;1321 }1322 // delete added bonds1323 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 node1330 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 stream1337 * \param Order bond order (limits BFS exploration and "number of digits" in power set generation1338 * \param FragmentSearch UniqueFragments1339 * \param *mol molecule with atoms and bonds1340 * \param RestrictedKeySet Restricted vertex set to use in context of molecule1341 */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 into1345 // according shortest path lists. However, we don't. Rather we fill these lists right away, as they do form a spanning1346 // tree already sorted into various SP levels. That's why we just do loops over the depth (CurrentSP) and breadth1347 // (EdgeinSPLevel) of this tree ...1348 // In another picture, the bonds always contain a direction by rightatom being the one more distant from root and hence1349 // 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 } else1366 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 list1372 RemainingWalkers--;1373 Walker = (*CurrentEdge)->rightatom; // rightatom is always the one more distant1374 Predecessor = (*CurrentEdge)->leftatom; // ... and leftatom is predecessor1375 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 level1378 // go through all its bonds1379 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 ADDHYDROGEN1387 && (OtherWalker->getType()->getAtomicNumber() != 1)1388 #endif1389 ) { // skip hydrogens and restrict to fragment1390 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's1393 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 list1396 Binder = new bond(Walker, OtherWalker); // create a new bond in such a manner, that bond::rightatom is always the one more distant1397 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 else1404 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 stream1414 * \param Order bond order (limits BFS exploration and "number of digits" in power set generation1415 * \param FragmentSearch UniqueFragments1416 */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 printing1421 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 stream1432 * \param Order bond order (limits BFS exploration and "number of digits" in power set generation1433 * \param FragmentSearch UniqueFragments1434 */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 edges1439 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 };1447 748 1448 749 /** 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. … … 1510 811 }; 1511 812 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 1607 814 1608 815
Note:
See TracChangeset
for help on using the changeset viewer.