- Timestamp:
- Mar 2, 2011, 9:53:08 PM (14 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:
- 1a4d4fe
- Parents:
- 2e4105
- git-author:
- Frederik Heber <heber@…> (02/25/11 20:52:50)
- git-committer:
- Frederik Heber <heber@…> (03/02/11 21:53:08)
- Location:
- src
- Files:
-
- 2 added
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Actions/FragmentationAction/DepthFirstSearchAction.cpp
r2e4105 re73ad9a 25 25 #include "CodePatterns/Log.hpp" 26 26 #include "CodePatterns/Verbose.hpp" 27 #include "Graph/CyclicStructureAnalysis.hpp" 27 28 #include "molecule.hpp" 28 29 #include "Descriptors/MoleculeDescriptor.hpp" … … 48 49 molecule * const mol = World::getInstance().getMolecule(MoleculeById(0)); 49 50 MoleculeLeafClass *Subgraphs = NULL; // list of subgraphs from DFS analysis 50 int *MinimumRingSize = new int[mol->getAtomCount()];51 51 atom **ListOfAtoms = NULL; 52 52 std::deque<bond *> *BackEdgeStack = NULL; … … 61 61 LocalBackEdgeStack = new std::deque<bond *>; // no need to have it Subgraphs->Leaf->BondCount size 62 62 Subgraphs->Leaf->PickLocalBackEdges(ListOfAtoms, BackEdgeStack, LocalBackEdgeStack); 63 Subgraphs->Leaf->CyclicStructureAnalysis(LocalBackEdgeStack, MinimumRingSize); 63 CyclicStructureAnalysis CycleAnalysis; 64 CycleAnalysis(LocalBackEdgeStack); 64 65 delete(LocalBackEdgeStack); 65 66 delete(Subgraphs->previous); … … 70 71 } 71 72 delete(BackEdgeStack); 72 delete[](MinimumRingSize);73 73 return Action::success; 74 74 } -
src/Actions/Makefile.am
r2e4105 re73ad9a 242 242 ../Parser/libMolecuilderParser.la \ 243 243 ../Shapes/libMolecuilderShapes.la \ 244 ../Graph/libMolecuilderGraph.la \ 244 245 ${CodePatterns_LIBS} 245 246 # ../UIElements/libMolecuilderUI.la -
src/Graph/Makefile.am
r2e4105 re73ad9a 9 9 GRAPHSOURCE = \ 10 10 BreadthFirstSearchAdd.cpp \ 11 ConnectedSubgraph.cpp 11 ConnectedSubgraph.cpp \ 12 CyclicStructureAnalysis.cpp 12 13 13 14 GRAPHHEADER = \ 14 15 BreadthFirstSearchAdd.hpp \ 15 ConnectedSubgraph.hpp 16 ConnectedSubgraph.hpp \ 17 CyclicStructureAnalysis.hpp 16 18 17 19 -
src/Makefile.am
r2e4105 re73ad9a 256 256 libMolecuilder_la_LIBADD = \ 257 257 LinearAlgebra/libMolecuilderLinearAlgebra.la \ 258 Graph/libMolecuilderGraph.la \ 258 259 ${CodePatterns_LIBS} \ 259 260 ${BOOST_PROGRAM_OPTIONS_LIB} -
src/molecule.hpp
r2e4105 re73ad9a 210 210 // Graph analysis 211 211 MoleculeLeafClass * DepthFirstSearchAnalysis(std::deque<bond *> *&BackEdgeStack) const; 212 void CyclicStructureAnalysis(std::deque<bond *> *BackEdgeStack, int *&MinimumRingSize) const;213 212 bool PickLocalBackEdges(atom **ListOfLocalAtoms, std::deque<bond *> *&ReferenceStack, std::deque<bond *> *&LocalStack) const; 214 213 bond * FindNextUnused(atom *vertex) const; … … 224 223 /// Fragment molecule by two different approaches: 225 224 int FragmentMolecule(int Order, std::string &prefix); 226 bool CheckOrderAtSite(bool *AtomMask, Graph *GlobalKeySetList, int Order, int *MinimumRingSize,std::string path = "");225 bool CheckOrderAtSite(bool *AtomMask, Graph *GlobalKeySetList, int Order, std::string path = ""); 227 226 bool StoreBondsToFile(std::string filename, std::string path = ""); 228 227 bool StoreAdjacencyToFile(std::string filename, std::string path = ""); … … 235 234 236 235 /// -# BOSSANOVA 237 void FragmentBOSSANOVA(Graph *&FragmentList, KeyStack &RootStack , int *MinimumRingSize);236 void FragmentBOSSANOVA(Graph *&FragmentList, KeyStack &RootStack); 238 237 int PowerSetGenerator(int Order, struct UniqueFragments &FragmentSearch, KeySet RestrictedKeySet); 239 238 bool BuildInducedSubgraph(const molecule *Father); -
src/molecule_fragmentation.cpp
r2e4105 re73ad9a 29 29 #include "config.hpp" 30 30 #include "element.hpp" 31 #include "Graph/BondGraph.hpp" 32 #include "Graph/CyclicStructureAnalysis.hpp" 31 33 #include "Helpers/helpers.hpp" 32 #include "Graph/BondGraph.hpp"33 34 #include "LinearAlgebra/RealSpaceMatrix.hpp" 34 35 #include "molecule.hpp" … … 456 457 * \param *GlobalKeySetList list of keysets with global ids (valid in "this" molecule) needed for adaptive increase 457 458 * \param Order desired Order if positive, desired exponent in threshold criteria if negative (0 is single-step) 458 * \param *MinimumRingSize array of max. possible order to avoid loops459 459 * \param path path to ENERGYPERFRAGMENT file (may be NULL if Order is non-negative) 460 460 * \return true - needs further fragmentation, false - does not need fragmentation 461 461 */ 462 bool molecule::CheckOrderAtSite(bool *AtomMask, Graph *GlobalKeySetList, int Order, int *MinimumRingSize,std::string path)462 bool molecule::CheckOrderAtSite(bool *AtomMask, Graph *GlobalKeySetList, int Order, std::string path) 463 463 { 464 464 bool status = false; … … 628 628 { 629 629 MoleculeListClass *BondFragments = NULL; 630 int *MinimumRingSize = new int[getAtomCount()];631 630 int FragmentCounter; 632 631 MoleculeLeafClass *MolecularWalker = NULL; … … 675 674 676 675 // analysis of the cycles (print rings, get minimum cycle length) for each subgraph 677 for(int i=getAtomCount();i--;)678 MinimumRingSize[i] = getAtomCount();679 676 MolecularWalker = Subgraphs; 680 677 const int LeafCount = Subgraphs->next->Count(); … … 697 694 MolecularWalker->Leaf->PickLocalBackEdges(ListOfAtoms, BackEdgeStack, LocalBackEdgeStack); 698 695 DoLog(0) && (Log() << Verbose(0) << "Analysing the cycles of subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl); 699 MolecularWalker->Leaf->CyclicStructureAnalysis(LocalBackEdgeStack, MinimumRingSize); 696 CyclicStructureAnalysis CycleAnalysis; 697 CycleAnalysis(LocalBackEdgeStack); 698 CycleAnalysis.getMinimumRingSize(); 700 699 DoLog(0) && (Log() << Verbose(0) << "Done with Analysing the cycles of subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl); 701 700 delete(LocalBackEdgeStack); … … 725 724 AtomMask[getAtomCount()] = false; 726 725 FragmentationToDo = false; // if CheckOrderAtSite just ones recommends fragmentation, we will save fragments afterwards 727 while ((CheckOrder = CheckOrderAtSite(AtomMask, ParsedFragmentList, Order, MinimumRingSize,prefix))) {726 while ((CheckOrder = CheckOrderAtSite(AtomMask, ParsedFragmentList, Order, prefix))) { 728 727 FragmentationToDo = FragmentationToDo || CheckOrder; 729 728 AtomMask[getAtomCount()] = true; // last plus one entry is used as marker that we have been through this loop once already in CheckOrderAtSite() … … 740 739 // call BOSSANOVA method 741 740 DoLog(0) && (Log() << Verbose(0) << endl << " ========== BOND ENERGY of subgraph " << FragmentCounter << " ========================= " << endl); 742 MolecularWalker->Leaf->FragmentBOSSANOVA(FragmentList[FragmentCounter], RootStack[FragmentCounter] , MinimumRingSize);741 MolecularWalker->Leaf->FragmentBOSSANOVA(FragmentList[FragmentCounter], RootStack[FragmentCounter]); 743 742 } else { 744 743 DoeLog(1) && (eLog()<< Verbose(1) << "Subgraph " << MolecularWalker << " has no atoms!" << endl); … … 751 750 delete[](AtomMask); 752 751 delete(ParsedFragmentList); 753 delete[](MinimumRingSize);754 752 755 753 // ==================================== End of FRAGMENTATION ============================================ … … 1646 1644 * \param Fragment&*List list of already present keystacks (adaptive scheme) or empty list 1647 1645 * \param &RootStack stack with all root candidates (unequal to each atom in complete molecule if adaptive scheme is applied) 1648 * \param *MinimumRingSize minimum ring size for each atom (molecule::Atomcount)1649 1646 * \return pointer to Graph list 1650 1647 */ 1651 void molecule::FragmentBOSSANOVA(Graph *&FragmentList, KeyStack &RootStack , int *MinimumRingSize)1648 void molecule::FragmentBOSSANOVA(Graph *&FragmentList, KeyStack &RootStack) 1652 1649 { 1653 1650 Graph ***FragmentLowerOrdersList = NULL; -
src/molecule_graph.cpp
r2e4105 re73ad9a 44 44 #define MAXBONDS 8 45 45 46 struct BFSAccounting47 {48 atom **PredecessorList;49 int *ShortestPathList;50 enum GraphEdge::Shading *ColorList;51 std::deque<atom *> *BFSStack;52 std::deque<atom *> *TouchedStack;53 int AtomCount;54 int BondOrder;55 atom *Root;56 bool BackStepping;57 int CurrentGraphNr;58 int ComponentNr;59 };60 46 61 47 /** Accounting data for Depth First Search. … … 200 186 201 187 202 /** Sets atom::GraphNr and atom::LowpointNr to BFSAccounting::CurrentGraphNr.188 /** Sets atom::GraphNr and atom::LowpointNr to DFSAccounting::CurrentGraphNr. 203 189 * \param *Walker current node 204 190 * \param &BFS structure with accounting data for BFS … … 518 504 } 519 505 ; 520 521 /** Initialise each vertex as white with no predecessor, empty queue, color Root lightgray.522 * \param &BFS accounting structure523 * \param AtomCount number of entries in the array to allocate524 */525 void InitializeBFSAccounting(struct BFSAccounting &BFS, int AtomCount)526 {527 BFS.AtomCount = AtomCount;528 BFS.PredecessorList = new atom*[AtomCount];529 BFS.ShortestPathList = new int[AtomCount];530 BFS.ColorList = new enum GraphEdge::Shading[AtomCount];531 BFS.BFSStack = new std::deque<atom *> (AtomCount);532 BFS.TouchedStack = new std::deque<atom *> (AtomCount);533 534 for (int i = AtomCount; i--;) {535 BFS.ShortestPathList[i] = -1;536 BFS.PredecessorList[i] = 0;537 BFS.ColorList[i] = GraphEdge::white;538 }539 };540 541 /** Free's accounting structure.542 * \param &BFS accounting structure543 */544 void FinalizeBFSAccounting(struct BFSAccounting &BFS)545 {546 delete[](BFS.PredecessorList);547 delete[](BFS.ShortestPathList);548 delete[](BFS.ColorList);549 delete (BFS.BFSStack);550 delete (BFS.TouchedStack);551 BFS.AtomCount = 0;552 };553 554 /** Clean the accounting structure.555 * \param &BFS accounting structure556 */557 void CleanBFSAccounting(struct BFSAccounting &BFS)558 {559 atom *Walker = NULL;560 while (!BFS.TouchedStack->empty()) {561 Walker = BFS.TouchedStack->front();562 BFS.TouchedStack->pop_front();563 BFS.PredecessorList[Walker->getNr()] = NULL;564 BFS.ShortestPathList[Walker->getNr()] = -1;565 BFS.ColorList[Walker->getNr()] = GraphEdge::white;566 }567 };568 569 /** Resets shortest path list and BFSStack.570 * \param *&Walker current node, pushed onto BFSAccounting::BFSStack and BFSAccounting::TouchedStack571 * \param &BFS accounting structure572 */573 void ResetBFSAccounting(atom *&Walker, struct BFSAccounting &BFS)574 {575 BFS.ShortestPathList[Walker->getNr()] = 0;576 BFS.BFSStack->clear(); // start with empty BFS stack577 BFS.BFSStack->push_front(Walker);578 BFS.TouchedStack->push_front(Walker);579 };580 581 /** Performs a BFS from \a *Root, trying to find the same node and hence a cycle.582 * \param *&BackEdge the edge from root that we don't want to move along583 * \param &BFS accounting structure584 */585 void CyclicStructureAnalysis_CyclicBFSFromRootToRoot(bond *&BackEdge, struct BFSAccounting &BFS)586 {587 atom *Walker = NULL;588 atom *OtherAtom = NULL;589 do { // look for Root590 ASSERT(!BFS.BFSStack->empty(), "CyclicStructureAnalysis_CyclicBFSFromRootToRoot() - BFS.BFSStack is empty!");591 Walker = BFS.BFSStack->front();592 BFS.BFSStack->pop_front();593 DoLog(2) && (Log() << Verbose(2) << "Current Walker is " << *Walker << ", we look for SP to Root " << *BFS.Root << "." << endl);594 const BondList& ListOfBonds = Walker->getListOfBonds();595 for (BondList::const_iterator Runner = ListOfBonds.begin();596 Runner != ListOfBonds.end();597 ++Runner) {598 if ((*Runner) != BackEdge) { // only walk along DFS spanning tree (otherwise we always find SP of one being backedge Binder)599 OtherAtom = (*Runner)->GetOtherAtom(Walker);600 #ifdef ADDHYDROGEN601 if (OtherAtom->getType()->getAtomicNumber() != 1) {602 #endif603 DoLog(2) && (Log() << Verbose(2) << "Current OtherAtom is: " << OtherAtom->getName() << " for bond " << *(*Runner) << "." << endl);604 if (BFS.ColorList[OtherAtom->getNr()] == GraphEdge::white) {605 BFS.TouchedStack->push_front(OtherAtom);606 BFS.ColorList[OtherAtom->getNr()] = GraphEdge::lightgray;607 BFS.PredecessorList[OtherAtom->getNr()] = Walker; // Walker is the predecessor608 BFS.ShortestPathList[OtherAtom->getNr()] = BFS.ShortestPathList[Walker->getNr()] + 1;609 DoLog(2) && (Log() << Verbose(2) << "Coloring OtherAtom " << OtherAtom->getName() << " lightgray, its predecessor is " << Walker->getName() << " and its Shortest Path is " << BFS.ShortestPathList[OtherAtom->getNr()] << " egde(s) long." << endl);610 //if (BFS.ShortestPathList[OtherAtom->getNr()] < MinimumRingSize[Walker->GetTrueFather()->nr]) { // Check for maximum distance611 DoLog(3) && (Log() << Verbose(3) << "Putting OtherAtom into queue." << endl);612 BFS.BFSStack->push_front(OtherAtom);613 //}614 } else {615 DoLog(3) && (Log() << Verbose(3) << "Not Adding, has already been visited." << endl);616 }617 if (OtherAtom == BFS.Root)618 break;619 #ifdef ADDHYDROGEN620 } else {621 DoLog(2) && (Log() << Verbose(2) << "Skipping hydrogen atom " << *OtherAtom << "." << endl);622 BFS.ColorList[OtherAtom->getNr()] = GraphEdge::black;623 }624 #endif625 } else {626 DoLog(2) && (Log() << Verbose(2) << "Bond " << *(*Runner) << " not Visiting, is the back edge." << endl);627 }628 }629 BFS.ColorList[Walker->getNr()] = GraphEdge::black;630 DoLog(1) && (Log() << Verbose(1) << "Coloring Walker " << Walker->getName() << " black." << endl);631 if (OtherAtom == BFS.Root) { // if we have found the root, check whether this cycle wasn't already found beforehand632 // step through predecessor list633 while (OtherAtom != BackEdge->rightatom) {634 if (!OtherAtom->GetTrueFather()->IsCyclic) // if one bond in the loop is not marked as cyclic, we haven't found this cycle yet635 break;636 else637 OtherAtom = BFS.PredecessorList[OtherAtom->getNr()];638 }639 if (OtherAtom == BackEdge->rightatom) { // if each atom in found cycle is cyclic, loop's been found before already640 DoLog(3) && (Log() << Verbose(3) << "This cycle was already found before, skipping and removing seeker from search." << endl);641 do {642 ASSERT(!BFS.TouchedStack->empty(), "CyclicStructureAnalysis_CyclicBFSFromRootToRoot() - BFS.TouchedStack is empty!");643 OtherAtom = BFS.TouchedStack->front();644 BFS.TouchedStack->pop_front();645 if (BFS.PredecessorList[OtherAtom->getNr()] == Walker) {646 DoLog(4) && (Log() << Verbose(4) << "Removing " << *OtherAtom << " from lists and stacks." << endl);647 BFS.PredecessorList[OtherAtom->getNr()] = NULL;648 BFS.ShortestPathList[OtherAtom->getNr()] = -1;649 BFS.ColorList[OtherAtom->getNr()] = GraphEdge::white;650 // rats ... deque has no find()651 std::deque<atom *>::iterator iter = find(652 BFS.BFSStack->begin(),653 BFS.BFSStack->end(),654 OtherAtom);655 ASSERT(iter != BFS.BFSStack->end(),656 "CyclicStructureAnalysis_CyclicBFSFromRootToRoot() - can't find "+toString(*OtherAtom)+" on stack!");657 BFS.BFSStack->erase(iter);658 }659 } while ((!BFS.TouchedStack->empty()) && (BFS.PredecessorList[OtherAtom->getNr()] == NULL));660 BFS.TouchedStack->push_front(OtherAtom); // last was wrongly popped661 OtherAtom = BackEdge->rightatom; // set to not Root662 } else663 OtherAtom = BFS.Root;664 }665 } while ((!BFS.BFSStack->empty()) && (OtherAtom != BFS.Root) && (OtherAtom != NULL)); // || (ShortestPathList[OtherAtom->getNr()] < MinimumRingSize[Walker->GetTrueFather()->getNr()])));666 };667 668 /** Climb back the BFSAccounting::PredecessorList and find cycle members.669 * \param *&OtherAtom670 * \param *&BackEdge denotes the edge we did not want to travel along when doing CyclicBFSFromRootToRoot()671 * \param &BFS accounting structure672 * \param *&MinimumRingSize minimum distance from this node possible without encountering oneself, set on return for each atom673 * \param &MinRingSize global minimum distance from one node without encountering oneself, set on return674 */675 void CyclicStructureAnalysis_RetrieveCycleMembers(atom *&OtherAtom, bond *&BackEdge, struct BFSAccounting &BFS, int *&MinimumRingSize, int &MinRingSize)676 {677 atom *Walker = NULL;678 int NumCycles = 0;679 int RingSize = -1;680 681 if (OtherAtom == BFS.Root) {682 // now climb back the predecessor list and thus find the cycle members683 NumCycles++;684 RingSize = 1;685 BFS.Root->GetTrueFather()->IsCyclic = true;686 DoLog(1) && (Log() << Verbose(1) << "Found ring contains: ");687 Walker = BFS.Root;688 while (Walker != BackEdge->rightatom) {689 DoLog(0) && (Log() << Verbose(0) << Walker->getName() << " <-> ");690 Walker = BFS.PredecessorList[Walker->getNr()];691 Walker->GetTrueFather()->IsCyclic = true;692 RingSize++;693 }694 DoLog(0) && (Log() << Verbose(0) << Walker->getName() << " with a length of " << RingSize << "." << endl << endl);695 // walk through all and set MinimumRingSize696 Walker = BFS.Root;697 MinimumRingSize[Walker->GetTrueFather()->getNr()] = RingSize;698 while (Walker != BackEdge->rightatom) {699 Walker = BFS.PredecessorList[Walker->getNr()];700 if (RingSize < MinimumRingSize[Walker->GetTrueFather()->getNr()])701 MinimumRingSize[Walker->GetTrueFather()->getNr()] = RingSize;702 }703 if ((RingSize < MinRingSize) || (MinRingSize == -1))704 MinRingSize = RingSize;705 } else {706 DoLog(1) && (Log() << Verbose(1) << "No ring containing " << *BFS.Root << " with length equal to or smaller than " << MinimumRingSize[BFS.Root->GetTrueFather()->getNr()] << " found." << endl);707 }708 };709 710 /** From a given node performs a BFS to touch the next cycle, for whose nodes \a *&MinimumRingSize is set and set it accordingly.711 * \param *&Root node to look for closest cycle from, i.e. \a *&MinimumRingSize is set for this node712 * \param *&MinimumRingSize minimum distance from this node possible without encountering oneself, set on return for each atom713 * \param AtomCount number of nodes in graph714 */715 void CyclicStructureAnalysis_BFSToNextCycle(atom *&Root, atom *&Walker, int *&MinimumRingSize, int AtomCount)716 {717 struct BFSAccounting BFS;718 atom *OtherAtom = Walker;719 720 InitializeBFSAccounting(BFS, AtomCount);721 722 ResetBFSAccounting(Walker, BFS);723 while (OtherAtom != NULL) { // look for Root724 ASSERT(!BFS.BFSStack->empty(), "CyclicStructureAnalysis_BFSToNextCycle() - BFS.BFSStack is empty!");725 Walker = BFS.BFSStack->front();726 BFS.BFSStack->pop_front();727 //Log() << Verbose(2) << "Current Walker is " << *Walker << ", we look for SP to Root " << *Root << "." << endl;728 const BondList& ListOfBonds = Walker->getListOfBonds();729 for (BondList::const_iterator Runner = ListOfBonds.begin();730 Runner != ListOfBonds.end();731 ++Runner) {732 // "removed (*Runner) != BackEdge) || " from next if, is u733 if ((ListOfBonds.size() == 1)) { // only walk along DFS spanning tree (otherwise we always find SP of 1 being backedge Binder), but terminal hydrogens may be connected via backedge, hence extra check734 OtherAtom = (*Runner)->GetOtherAtom(Walker);735 //Log() << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl;736 if (BFS.ColorList[OtherAtom->getNr()] == GraphEdge::white) {737 BFS.TouchedStack->push_front(OtherAtom);738 BFS.ColorList[OtherAtom->getNr()] = GraphEdge::lightgray;739 BFS.PredecessorList[OtherAtom->getNr()] = Walker; // Walker is the predecessor740 BFS.ShortestPathList[OtherAtom->getNr()] = BFS.ShortestPathList[Walker->getNr()] + 1;741 //Log() << Verbose(2) << "Coloring OtherAtom " << OtherAtom->Name << " lightgray, its predecessor is " << Walker->Name << " and its Shortest Path is " << ShortestPathList[OtherAtom->getNr()] << " egde(s) long." << endl;742 if (OtherAtom->GetTrueFather()->IsCyclic) { // if the other atom is connected to a ring743 MinimumRingSize[Root->GetTrueFather()->getNr()] = BFS.ShortestPathList[OtherAtom->getNr()] + MinimumRingSize[OtherAtom->GetTrueFather()->getNr()];744 OtherAtom = NULL; //break;745 break;746 } else747 BFS.BFSStack->push_front(OtherAtom);748 } else {749 //Log() << Verbose(3) << "Not Adding, has already been visited." << endl;750 }751 } else {752 //Log() << Verbose(3) << "Not Visiting, is a back edge." << endl;753 }754 }755 BFS.ColorList[Walker->getNr()] = GraphEdge::black;756 //Log() << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl;757 }758 //CleanAccountingLists(TouchedStack, PredecessorList, ShortestPathList, ColorList);759 760 FinalizeBFSAccounting(BFS);761 }762 ;763 764 /** All nodes that are not in cycles get assigned a \a *&MinimumRingSizeby BFS to next cycle.765 * \param *&MinimumRingSize array with minimum distance without encountering onself for each atom766 * \param &MinRingSize global minium distance767 * \param &NumCyles number of cycles in graph768 * \param *mol molecule with atoms769 */770 void CyclicStructureAnalysis_AssignRingSizetoNonCycleMembers(int *&MinimumRingSize, int &MinRingSize, int &NumCycles, const molecule * const mol)771 {772 atom *Root = NULL;773 atom *Walker = NULL;774 if (MinRingSize != -1) { // if rings are present775 // go over all atoms776 for (molecule::const_iterator iter = mol->begin(); iter != mol->end(); ++iter) {777 Root = *iter;778 779 if (MinimumRingSize[Root->GetTrueFather()->getNr()] == mol->getAtomCount()) { // check whether MinimumRingSize is set, if not BFS to next where it is780 Walker = Root;781 782 //Log() << Verbose(1) << "---------------------------------------------------------------------------------------------------------" << endl;783 CyclicStructureAnalysis_BFSToNextCycle(Root, Walker, MinimumRingSize, mol->getAtomCount());784 785 }786 DoLog(1) && (Log() << Verbose(1) << "Minimum ring size of " << *Root << " is " << MinimumRingSize[Root->GetTrueFather()->getNr()] << "." << endl);787 }788 DoLog(1) && (Log() << Verbose(1) << "Minimum ring size is " << MinRingSize << ", over " << NumCycles << " cycles total." << endl);789 } else790 DoLog(1) && (Log() << Verbose(1) << "No rings were detected in the molecular structure." << endl);791 }792 ;793 794 /** Analyses the cycles found and returns minimum of all cycle lengths.795 * We begin with a list of Back edges found during DepthFirstSearchAnalysis(). We go through this list - one end is the Root,796 * the other our initial Walker - and do a Breadth First Search for the Root. We mark down each Predecessor and as soon as797 * we have found the Root via BFS, we may climb back the closed cycle via the Predecessors. Thereby we mark atoms and bonds798 * as cyclic and print out the cycles.799 * \param *BackEdgeStack stack with all back edges found during DFS scan. Beware: This stack contains the bonds from the total molecule, not from the subgraph!800 * \param *&MinimumRingSize contains smallest ring size in molecular structure on return or -1 if no rings were found, if set is maximum search distance801 * \todo BFS from the not-same-LP to find back to starting point of tributary cycle over more than one bond802 */803 void molecule::CyclicStructureAnalysis(804 std::deque<bond *> * BackEdgeStack,805 int *&MinimumRingSize806 ) const807 {808 struct BFSAccounting BFS;809 atom *Walker = NULL;810 atom *OtherAtom = NULL;811 bond *BackEdge = NULL;812 int NumCycles = 0;813 int MinRingSize = -1;814 815 InitializeBFSAccounting(BFS, getAtomCount());816 817 //Log() << Verbose(1) << "Back edge list - ";818 //BackEdgeStack->Output(out);819 820 DoLog(1) && (Log() << Verbose(1) << "Analysing cycles ... " << endl);821 NumCycles = 0;822 while (!BackEdgeStack->empty()) {823 BackEdge = BackEdgeStack->front();824 BackEdgeStack->pop_front();825 // this is the target826 BFS.Root = BackEdge->leftatom;827 // this is the source point828 Walker = BackEdge->rightatom;829 830 ResetBFSAccounting(Walker, BFS);831 832 DoLog(1) && (Log() << Verbose(1) << "---------------------------------------------------------------------------------------------------------" << endl);833 OtherAtom = NULL;834 CyclicStructureAnalysis_CyclicBFSFromRootToRoot(BackEdge, BFS);835 836 CyclicStructureAnalysis_RetrieveCycleMembers(OtherAtom, BackEdge, BFS, MinimumRingSize, MinRingSize);837 838 CleanBFSAccounting(BFS);839 }840 FinalizeBFSAccounting(BFS);841 842 CyclicStructureAnalysis_AssignRingSizetoNonCycleMembers(MinimumRingSize, MinRingSize, NumCycles, this);843 };844 506 845 507 /** Sets the next component number.
Note:
See TracChangeset
for help on using the changeset viewer.