- Timestamp:
- Aug 20, 2014, 12:59:22 PM (10 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:
- 2cb77c
- Parents:
- 4d6d6a
- git-author:
- Frederik Heber <heber@…> (08/20/14 11:47:12)
- git-committer:
- Frederik Heber <heber@…> (08/20/14 12:59:22)
- Location:
- src/Graph
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Graph/CyclicStructureAnalysis.cpp
r4d6d6a r83cc3e 103 103 } 104 104 105 /** Performs a BFS from \a *Root, trying to find the same node and hence a cycle. 105 /** Performs a BFS from \a *Root, trying to find the same node and hence all cycles. 106 * 107 * We exclude the back edge, hence the direct way is prohibited. But as it is a back edge, 108 * there must be at least one more way to \a *Root. This leads us to all cycles for this 109 * back edge. 110 * 106 111 * \param OtherAtom pointing to Root on return indicating found cycle 107 112 * \param *&BackEdge the edge from root that we don't want to move along 108 */ 109 void CyclicStructureAnalysis::CyclicBFSFromRootToRoot(atom *&OtherAtom, bond::ptr &BackEdge) 110 { 113 * \param MinRingSize set to minimum over all cycles encountered 114 */ 115 void CyclicStructureAnalysis::findAllCyclesforBackEdge( 116 atom *&OtherAtom, 117 bond::ptr &BackEdge, 118 int &MinRingSize) 119 { 120 size_t MaximumHorizon = (size_t)-1; // will overflow to largest number 111 121 atom *Walker = NULL; 112 122 do { // look for Root … … 115 125 BFSStack.pop_back(); 116 126 LOG(2, "INFO: Current Walker is " << *Walker << ", we look for SP to Root " << *Root << "."); 117 const BondList& ListOfBonds = Walker->getListOfBonds(); 118 for (BondList::const_iterator Runner = ListOfBonds.begin(); 119 Runner != ListOfBonds.end(); 120 ++Runner) { 121 if ((*Runner) != BackEdge) { // only walk along DFS spanning tree (otherwise we always find SP of one being backedge Binder) 122 OtherAtom = (*Runner)->GetOtherAtom(Walker); 123 if ((treatment == IncludeHydrogen) || (OtherAtom->getType()->getAtomicNumber() != 1)) { 124 LOG(2, "INFO: Current OtherAtom is: " << OtherAtom->getName() << " for bond " << *(*Runner) << "."); 125 if (ColorList[OtherAtom->getNr()] == GraphEdge::white) { 126 TouchedStack.push_front(OtherAtom); 127 ColorList[OtherAtom->getNr()] = GraphEdge::lightgray; 128 PredecessorList[OtherAtom->getNr()] = Walker; // Walker is the predecessor 129 ShortestPathList[OtherAtom->getNr()] = ShortestPathList[Walker->getNr()] + 1; 130 LOG(2, "INFO: Coloring OtherAtom " << OtherAtom->getName() << " lightgray, its predecessor is " << Walker->getName() << " and its Shortest Path is " << ShortestPathList[OtherAtom->getNr()] << " egde(s) long."); 131 //if (ShortestPathList[OtherAtom->getNr()] < MinimumRingSize[Walker->GetTrueFather()->getNr()]) { // Check for maximum distance 132 LOG(3, "ACCEPT: Putting OtherAtom " << OtherAtom->getName() << " into queue."); 133 BFSStack.push_front(OtherAtom); 134 //} 127 128 // check all edges/bonds from current Walker 129 if (MaximumHorizon >= (size_t)ShortestPathList[Walker->getNr()]) { 130 const BondList& ListOfBonds = Walker->getListOfBonds(); 131 for (BondList::const_iterator Runner = ListOfBonds.begin(); 132 Runner != ListOfBonds.end(); 133 ++Runner) { 134 if ((*Runner) != BackEdge) { // only walk along DFS spanning tree (otherwise we always find SP of one being backedge Binder) 135 OtherAtom = (*Runner)->GetOtherAtom(Walker); 136 if ((treatment == IncludeHydrogen) || (OtherAtom->getType()->getAtomicNumber() != 1)) { 137 LOG(2, "INFO: Current OtherAtom is: " << OtherAtom->getName() << " for bond " << *(*Runner) << "."); 138 if (ColorList[OtherAtom->getNr()] == GraphEdge::white) { 139 // we discovered a new node/atom 140 TouchedStack.push_front(OtherAtom); 141 ColorList[OtherAtom->getNr()] = GraphEdge::lightgray; 142 PredecessorList[OtherAtom->getNr()] = Walker; // Walker is the predecessor 143 ShortestPathList[OtherAtom->getNr()] = ShortestPathList[Walker->getNr()] + 1; 144 LOG(2, "INFO: Coloring OtherAtom " << OtherAtom->getName() << " lightgray, its predecessor is " << Walker->getName() << " and its Shortest Path is " << ShortestPathList[OtherAtom->getNr()] << " egde(s) long."); 145 //if (ShortestPathList[OtherAtom->getNr()] < MinimumRingSize[Walker->GetTrueFather()->getNr()]) { // Check for maximum distance 146 LOG(3, "ACCEPT: Putting OtherAtom " << OtherAtom->getName() << " into queue."); 147 BFSStack.push_front(OtherAtom); 148 //} 149 } else { 150 LOG(3, "REJECT: Not Adding, has already been visited."); 151 } 152 if (OtherAtom == Root) 153 break; 135 154 } else { 136 LOG(3, "REJECT: Not Adding, has already been visited."); 155 LOG(2, "INFO: Skipping hydrogen atom " << *OtherAtom << "."); 156 ColorList[OtherAtom->getNr()] = GraphEdge::black; 137 157 } 138 if (OtherAtom == Root)139 break;140 158 } else { 141 LOG(2, "INFO: Skipping hydrogen atom " << *OtherAtom << "."); 142 ColorList[OtherAtom->getNr()] = GraphEdge::black; 159 LOG(2, "REJECT: Bond " << *(*Runner) << " not Visiting, is the back edge."); 143 160 } 144 } else { 145 LOG(2, "REJECT: Bond " << *(*Runner) << " not Visiting, is the back edge."); 146 } 147 } 148 ColorList[Walker->getNr()] = GraphEdge::black; 149 LOG(1, "INFO: Coloring Walker " << Walker->getName() << " " << GraphEdge::getColorName(ColorList[Walker->getNr()]) << "."); 150 if (OtherAtom == Root) { // if we have found the root, check whether this cycle wasn't already found beforehand 151 // step through predecessor list 152 LOG(4, "DEBUG: Checking whether all predecessors are already marked cyclic ..."); 153 while (OtherAtom != BackEdge->rightatom) { // Note that leftatom is Root itself 154 if (!OtherAtom->GetTrueFather()->IsCyclic) { // if one bond in the loop is not marked as cyclic, we haven't found this cycle yet 155 LOG(4, "\tDEBUG: OtherAtom " << *OtherAtom << " is not cyclic, breaking."); 156 break; 157 } else 158 OtherAtom = PredecessorList[OtherAtom->getNr()]; 159 } 160 LOG(4, "DEBUG: Checking done."); 161 // if each atom in found cycle is cyclic, loop's been found before already 162 if (OtherAtom == BackEdge->rightatom) { // loop got round completely 163 LOG(3, "INFO: All bonds are marked cyclic already, checking allcycles whether cycle is already present."); 164 const cycle_t currentcycle = extractCurrentCycle(BackEdge); 165 const cycles_t::const_iterator iter = 166 std::find(allcycles.begin(), allcycles.end(), currentcycle); 167 if (iter == allcycles.end()) { // not found 168 OtherAtom = Root; 169 LOG(2, "INFO: Cycle is not present."); 170 LOG(2, "INFO: We have reached Root " << *OtherAtom << " and may extract the cycle."); 171 } else { 172 LOG(2, "INFO: Cycle is already present."); 173 do { 174 ASSERT(!TouchedStack.empty(), "CyclicStructureAnalysis_CyclicBFSFromRootToRoot() - TouchedStack is empty!"); 175 OtherAtom = TouchedStack.front(); 176 TouchedStack.pop_front(); 177 if (PredecessorList[OtherAtom->getNr()] == Walker) { 178 LOG(4, "INFO: Removing " << *OtherAtom << " from lists and stacks."); 179 PredecessorList[OtherAtom->getNr()] = NULL; 180 ShortestPathList[OtherAtom->getNr()] = -1; 181 ColorList[OtherAtom->getNr()] = GraphEdge::white; 182 // rats ... deque has no find() 183 std::deque<atom *>::iterator iter = find( 184 BFSStack.begin(), 185 BFSStack.end(), 186 OtherAtom); 187 ASSERT(iter != BFSStack.end(), 188 "CyclicStructureAnalysis_CyclicBFSFromRootToRoot() - can't find "+toString(*OtherAtom)+" on stack!"); 189 BFSStack.erase(iter); 190 } 191 } while ((!TouchedStack.empty()) && (PredecessorList[OtherAtom->getNr()] == NULL)); 192 TouchedStack.push_front(OtherAtom); // last was wrongly popped 193 OtherAtom = BackEdge->rightatom; // set to not Root 161 } 162 ColorList[Walker->getNr()] = GraphEdge::black; 163 LOG(1, "INFO: Coloring Walker " << Walker->getName() << " " << GraphEdge::getColorName(ColorList[Walker->getNr()]) << "."); 164 } else { 165 LOG(1, "INFO: Skipping bonds for " << Walker->getName() << " as it resides on the horizon."); 166 } 167 168 // have we closed the cycle, i.e. stumbled upon Root by another mean than 169 // the back edge? 170 if (OtherAtom == Root) { 171 // check whether this cycle wasn't already found beforehand by stepping 172 // through predecessor list 173 int RingSize = RetrieveCycleMembers(OtherAtom, BackEdge, MinRingSize); 174 MaximumHorizon = std::min( MaximumHorizon, (size_t)RingSize ); 175 LOG(2, "INFO: Maximum horizon is set to " << MaximumHorizon); 176 177 // remove last step and prepare for a possible yet another path to Root 178 do { 179 ASSERT(!TouchedStack.empty(), "CyclicStructureAnalysis_CyclicBFSFromRootToRoot() - TouchedStack is empty!"); 180 OtherAtom = TouchedStack.front(); 181 TouchedStack.pop_front(); 182 if (PredecessorList[OtherAtom->getNr()] == Walker) { 183 LOG(4, "INFO: Removing " << *OtherAtom << " from lists and stacks."); 184 PredecessorList[OtherAtom->getNr()] = NULL; 185 ShortestPathList[OtherAtom->getNr()] = -1; 186 ColorList[OtherAtom->getNr()] = GraphEdge::white; 187 // rats ... deque has no find() 188 std::deque<atom *>::iterator iter = find( 189 BFSStack.begin(), 190 BFSStack.end(), 191 OtherAtom); 192 ASSERT(iter != BFSStack.end(), 193 "CyclicStructureAnalysis_CyclicBFSFromRootToRoot() - can't find "+toString(*OtherAtom)+" on stack!"); 194 BFSStack.erase(iter); 194 195 } 195 } else { 196 OtherAtom = Root; 197 LOG(2, "INFO: We have reached Root " << *OtherAtom << " and may extract the cycle."); 198 } 196 } while ((!TouchedStack.empty()) && (PredecessorList[OtherAtom->getNr()] == NULL)); 197 TouchedStack.push_front(OtherAtom); // last was wrongly popped 198 OtherAtom = BackEdge->rightatom; // set to not Root 199 199 } 200 200 } while ((!BFSStack.empty()) && (OtherAtom != Root) && (OtherAtom != NULL)); // || (ShortestPathList[OtherAtom->getNr()] < MinimumRingSize[Walker->GetTrueFather()->getNr()]))); … … 233 233 * \param &BFS accounting structure 234 234 * \param &MinRingSize global minimum distance from one node without encountering oneself, set on return 235 * \ param &NumCyles number of cycles in graph236 */ 237 voidCyclicStructureAnalysis::RetrieveCycleMembers(235 * \return size of found cycle, -1 - nothing found, something went wrong 236 */ 237 int CyclicStructureAnalysis::RetrieveCycleMembers( 238 238 atom *&OtherAtom, 239 239 bond::ptr &BackEdge, 240 int &MinRingSize, 241 int &NumCycles) 242 { 243 atom *Walker = NULL; 240 int &MinRingSize) 241 { 244 242 int RingSize = -1; 243 bool newcycle = false; 245 244 246 245 if (OtherAtom == Root) { 247 246 // now climb back the predecessor list and thus find the cycle members 248 NumCycles++;249 247 Root->GetTrueFather()->IsCyclic = true; 250 248 251 // exctract cycle252 249 { 253 allcycles.push_back(extractCurrentCycle(BackEdge)); 254 CyclicStructureAnalysis::cycle_t &lastcycle = allcycles.back(); 255 RingSize = lastcycle.size(); 256 LOG(0, "INFO: " << "Found ring contains: " << lastcycle << " with a length of " << RingSize); 257 } 258 259 // walk through all and set MinimumRingSize 260 Walker = Root; 261 if ((MinimumRingSize.count(Walker->GetTrueFather()->getNr()) == 0) 262 || (RingSize < MinimumRingSize[Walker->GetTrueFather()->getNr()])) { 263 MinimumRingSize[Walker->GetTrueFather()->getNr()] = RingSize; 264 } else { 265 LOG(3, "INFO: Not setting MinimumRingSize of "<< *(Walker->GetTrueFather()) 266 << " to " << RingSize << " which is already set to " 267 << MinimumRingSize[Walker->GetTrueFather()->getNr()] << "."); 268 } 269 while (Walker != BackEdge->rightatom) { // note that Root is leftatom 270 Walker = PredecessorList[Walker->getNr()]; 250 // check whether cycle is present already 251 atom *Walker = Root; 252 LOG(4, "DEBUG: Checking whether all predecessors are already marked cyclic ..."); 253 while (Walker != BackEdge->rightatom) { // Note that leftatom is Root itself 254 if (!Walker->GetTrueFather()->IsCyclic) { // if one bond in the loop is not marked as cyclic, we haven't found this cycle yet 255 LOG(4, "\tDEBUG: Walker " << *Walker << " is not cyclic, breaking."); 256 break; 257 } else 258 Walker = PredecessorList[Walker->getNr()]; 259 } 260 LOG(4, "DEBUG: Checking done."); 261 262 // if each atom in found cycle is cyclic, loop's been found before already 263 264 // exctract cycle 265 { 266 const cycle_t currentcycle = extractCurrentCycle(BackEdge); 267 if (Walker != BackEdge->rightatom) { // loop got round completely 268 allcycles.push_back(currentcycle); 269 newcycle = true; 270 } else { 271 LOG(3, "INFO: All bonds are marked cyclic already, checking allcycles whether cycle is already present."); 272 const cycles_t::const_iterator iter = 273 std::find(allcycles.begin(), allcycles.end(), currentcycle); 274 if (iter == allcycles.end()) { // not found 275 allcycles.push_back(currentcycle); 276 newcycle = true; 277 } 278 } 279 RingSize = currentcycle.size(); 280 if (newcycle) { 281 LOG(0, "INFO: " << "Found ring contains: " << currentcycle << " with a length of " << RingSize); 282 } else { 283 LOG(1, "INFO: cycle " << currentcycle << " is already present."); 284 } 285 } 286 } 287 288 if (newcycle) { 289 // walk through all and set MinimumRingSize 290 atom *Walker = Root; 271 291 if ((MinimumRingSize.count(Walker->GetTrueFather()->getNr()) == 0) 272 || (RingSize < MinimumRingSize[Walker->GetTrueFather()->getNr()])) 292 || (RingSize < MinimumRingSize[Walker->GetTrueFather()->getNr()])) { 273 293 MinimumRingSize[Walker->GetTrueFather()->getNr()] = RingSize; 274 } 275 if ((RingSize < MinRingSize) || (MinRingSize == -1)) 276 MinRingSize = RingSize; 294 } else { 295 LOG(3, "INFO: Not setting MinimumRingSize of "<< *(Walker->GetTrueFather()) 296 << " to " << RingSize << " which is already set to " 297 << MinimumRingSize[Walker->GetTrueFather()->getNr()] << "."); 298 } 299 while (Walker != BackEdge->rightatom) { // note that Root is leftatom 300 Walker = PredecessorList[Walker->getNr()]; 301 if ((MinimumRingSize.count(Walker->GetTrueFather()->getNr()) == 0) 302 || (RingSize < MinimumRingSize[Walker->GetTrueFather()->getNr()])) 303 MinimumRingSize[Walker->GetTrueFather()->getNr()] = RingSize; 304 } 305 if ((RingSize < MinRingSize) || (MinRingSize == -1)) 306 MinRingSize = RingSize; 307 } 277 308 } else { 278 309 LOG(1, "INFO: No ring containing " << *Root << " with length equal to or smaller than " << MinimumRingSize[Root->GetTrueFather()->getNr()] << " found."); 279 310 } 311 return RingSize; 280 312 } 281 313 … … 358 390 * \param *&MinimumRingSize array with minimum distance without encountering oneself for each atom 359 391 * \param MinRingSize global minium distance 360 * \param NumCyles number of cycles in graph 361 */ 362 void CyclicStructureAnalysis::AssignRingSizetoNonCycleMembers(const int MinRingSize, const int NumCycles) 392 */ 393 void CyclicStructureAnalysis::AssignRingSizetoNonCycleMembers(const int MinRingSize) 363 394 { 364 395 atom *Walker = NULL; … … 380 411 LOG(1, "INFO: Minimum ring size of " << *Walker << " is " << MinimumRingSize[Walker->GetTrueFather()->getNr()] << "."); 381 412 } 382 LOG(1, "INFO: Minimum ring size is " << MinRingSize << ", over " << NumCycles<< " cycle(s) total.");413 LOG(1, "INFO: Minimum ring size is " << MinRingSize << ", over " << allcycles.size() << " cycle(s) total."); 383 414 } else 384 415 LOG(1, "INFO: No rings were detected in the molecular structure."); … … 399 430 atom *OtherAtom = NULL; 400 431 bond::ptr BackEdge; 401 int NumCycles = 0;402 432 int MinRingSize = -1; 403 433 … … 415 445 416 446 LOG(1, "STATUS: Analysing cycles ... "); 417 NumCycles = 0;418 447 while (!BackEdgeStack->empty()) { 419 448 BackEdge = BackEdgeStack->front(); … … 428 457 LOG(1, "---------------------------------------------------------------------------------------------------------"); 429 458 OtherAtom = NULL; 430 // go to next cycle via BFS 431 CyclicBFSFromRootToRoot(OtherAtom, BackEdge); 432 // get all member nodes of this cycle 433 RetrieveCycleMembers(OtherAtom, BackEdge, MinRingSize, NumCycles); 459 // find all cycles for current BackEdge 460 findAllCyclesforBackEdge(OtherAtom, BackEdge, MinRingSize); 434 461 435 462 CleanAllTouched(); 436 463 } 437 AssignRingSizetoNonCycleMembers(MinRingSize , NumCycles);464 AssignRingSizetoNonCycleMembers(MinRingSize); 438 465 } 439 466 -
src/Graph/CyclicStructureAnalysis.hpp
r4d6d6a r83cc3e 58 58 void InitializeToRoot(atom *&Walker); 59 59 // performing tasks 60 void CyclicBFSFromRootToRoot(atom *&OtherAtom, bond::ptr &BackEdge);61 void RetrieveCycleMembers(atom *&OtherAtom, bond::ptr &BackEdge, int &MinRingSize, int &NumCycles);60 void findAllCyclesforBackEdge(atom *&OtherAtom, bond::ptr &BackEdge, int &MinRingSize); 61 int RetrieveCycleMembers(atom *&OtherAtom, bond::ptr &BackEdge, int &MinRingSize); 62 62 cycle_t extractCurrentCycle(bond::ptr &BackEdge); 63 63 void BFSToNextCycle(atom *Walker); 64 void AssignRingSizetoNonCycleMembers(const int MinRingSize , const int NumCycles);64 void AssignRingSizetoNonCycleMembers(const int MinRingSize); 65 65 // output 66 66 void OutputAlreadyVisited(int *list);
Note:
See TracChangeset
for help on using the changeset viewer.