Changeset e73ad9a for src/molecule_graph.cpp
- 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)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
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.