- Timestamp:
- May 7, 2008, 2:46:33 PM (17 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:
- fe5589
- Parents:
- 6d35e4
- Location:
- src
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
src/molecules.cpp
r6d35e4 r8d9c38 1572 1572 1573 1573 // analysis of the cycles (print rings, get minimum cycle length) 1574 CyclicStructureAnalysis(out, MinimumRingSize);1574 CyclicStructureAnalysis(out, BackEdgeStack, MinimumRingSize); 1575 1575 1576 1576 *out << Verbose(1) << "Final graph info for each atom is:" << endl; … … 1606 1606 /** Analyses the cycles found and returns minimum of all cycle lengths. 1607 1607 * \param *out output stream for debugging 1608 * \param MinimumRingSize contains smallest ring size in molecular structure on return or -1 if no rings were found 1608 * \param *BackEdgeStack stack with all back edges found during DFS scan 1609 * \param MinimumRingSize contains smallest ring size in molecular structure on return or -1 if no rings were found, if set is maximum search distance 1609 1610 * \todo BFS from the not-same-LP to find back to starting point of tributary cycle over more than one bond 1610 1611 */ 1611 void molecule::CyclicStructureAnalysis(ofstream *out, int &MinimumRingSize) 1612 { 1613 class StackClass<atom *> *AtomStack = new StackClass<atom *>(AtomCount); 1614 int LP; 1615 atom *Walker = NULL, *OtherAtom = NULL, *Root = NULL, *Runner = NULL; 1616 bond *Binder = NULL; 1612 void molecule::CyclicStructureAnalysis(ofstream *out, class StackClass<bond *> * BackEdgeStack, int &MinimumRingSize) 1613 { 1614 atom **PredecessorList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::CyclicStructureAnalysis: **PredecessorList"); 1615 int *ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::CyclicStructureAnalysis: *ShortestPathList"); 1616 enum Shading *ColorList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::CyclicStructureAnalysis: *ColorList"); 1617 class StackClass<atom *> *BFSStack = new StackClass<atom *> (AtomCount); // will hold the current ring 1618 class StackClass<atom *> *TouchedStack = new StackClass<atom *> (AtomCount); // contains all "touched" atoms 1619 atom *Walker = NULL, *OtherAtom = NULL, *Root = NULL; 1620 bond *Binder = NULL, *BackEdge = NULL; 1617 1621 int RingSize, NumCycles; 1618 1622 1619 // count number of cyclic bonds per atom and push all with 3 cyclic bonds onto stack 1620 AtomStack->ClearStack(); 1621 int *NoCyclicBondsPerAtom = (int *) Malloc(sizeof(int)*AtomCount, "molecule::CyclicStructureAnalysis: *NoCyclicBondsPerAtom"); 1622 Walker = start; 1623 while (Walker->next != end) { 1624 Walker = Walker->next; 1625 NoCyclicBondsPerAtom[Walker->nr] = 0; 1626 // check whether it's connected to cyclic bonds and count per atom 1627 // 0 means not part of a cycle, 2 means in a cycle, 3 or more means interconnection site of cycles 1628 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr]; i++) { 1629 Binder = ListOfBondsPerAtom[Walker->nr][i]; 1630 NoCyclicBondsPerAtom[Walker->nr] += (int) Binder->Cyclic; 1631 if (NoCyclicBondsPerAtom[Walker->nr] == 3) //push all intersections 1632 AtomStack->Push(Walker); 1633 } 1634 } 1635 *out << Verbose(1) << "NoCyclicBondsPerAtom: "; 1636 for(int i=0;i<AtomCount;i++) { 1637 *out << NoCyclicBondsPerAtom[i] << " "; 1638 } 1639 *out << endl; 1623 // initialise each vertex as white with no predecessor, empty queue, color Root lightgray 1624 for (int i=0;i<AtomCount;i++) { 1625 PredecessorList[i] = NULL; 1626 ShortestPathList[i] = -1; 1627 ColorList[i] = white; 1628 } 1629 1630 *out << Verbose(1) << "Back edge list - "; 1631 BackEdgeStack->Output(out); 1632 1640 1633 *out << Verbose(1) << "Analysing cycles ... " << endl; 1641 MinimumRingSize = -1; 1634 if ((MinimumRingSize <= 2) || (MinimumRingSize > AtomCount)) 1635 MinimumRingSize = AtomCount; 1642 1636 NumCycles = 0; 1643 while (!AtomStack->IsEmpty()) { 1644 Walker = AtomStack->PopFirst(); 1645 if (NoCyclicBondsPerAtom[Walker->nr] > 1) { 1646 NoCyclicBondsPerAtom[Walker->nr]--; // remove one for being intersection 1647 RingSize = 0; 1648 *out << Verbose(2) << "Current intersection is " << *Walker << ", expect to find " << NoCyclicBondsPerAtom[Walker->nr] << " cycles." << endl; 1637 while (!BackEdgeStack->IsEmpty()) { 1638 BackEdge = BackEdgeStack->PopFirst(); 1639 // this is the target 1640 Root = BackEdge->leftatom; 1641 // this is the source point 1642 Walker = BackEdge->rightatom; 1643 ShortestPathList[Walker->nr] = 0; 1644 BFSStack->ClearStack(); // start with empty BFS stack 1645 BFSStack->Push(Walker); 1646 TouchedStack->Push(Walker); 1647 //*out << Verbose(1) << "---------------------------------------------------------------------------------------------------------" << endl; 1648 OtherAtom = NULL; 1649 while ((Walker != Root) && ((OtherAtom == NULL) || (ShortestPathList[OtherAtom->nr] < MinimumRingSize))) { // look for Root 1650 Walker = BFSStack->PopFirst(); 1651 //*out << Verbose(2) << "Current Walker is " << *Walker << ", we look for SP to Root " << *Root << "." << endl; 1649 1652 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { 1650 1653 Binder = ListOfBondsPerAtom[Walker->nr][i]; 1651 OtherAtom = Binder->GetOtherAtom(Walker); 1652 // note down the LowPoint number of this cycle 1653 if (NoCyclicBondsPerAtom[OtherAtom->nr] > 1) { 1654 LP = OtherAtom->LowpointNr; 1655 NoCyclicBondsPerAtom[Walker->nr]--; // walker is start of cycle 1656 if (LP != Walker->LowpointNr) 1657 *out << Verbose(2) << "Tributary cycle: ... <-> " << Walker->Name; 1658 else 1659 *out << Verbose(2) << "Main cycle: ... <-> " << Walker->Name; 1660 Root = Walker; // root acts as predecessor marker so that we don't step back accidentally 1661 RingSize = 1; 1662 do { 1663 for(int j=0;j<NumberOfBondsPerAtom[OtherAtom->nr];j++) { // search among its bonds for next in cycle (same lowpoint nr) 1664 Runner = ListOfBondsPerAtom[OtherAtom->nr][j]->GetOtherAtom(OtherAtom); 1665 if (((Runner->LowpointNr == LP) || (Runner->LowpointNr == Walker->LowpointNr)) && (Runner != Root)) { 1666 // first check is to stay in the cycle 1667 // middle check is allow for getting back into main cycle briefly from tributary cycle (just one step, then while further down stops) 1668 // last check is not step back 1669 *out << " <-> " << OtherAtom->Name; 1670 NoCyclicBondsPerAtom[OtherAtom->nr]--; 1671 Root = OtherAtom; 1672 OtherAtom = Runner; 1673 NoCyclicBondsPerAtom[Root->nr]--; 1674 RingSize++; 1675 break; 1676 } 1654 if (Binder != BackEdge) { // only walk along DFS spanning tree (otherwise we always find SP of one being backedge Binder) 1655 OtherAtom = Binder->GetOtherAtom(Walker); 1656 //*out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl; 1657 if (ColorList[OtherAtom->nr] == white) { 1658 TouchedStack->Push(OtherAtom); 1659 ColorList[OtherAtom->nr] = lightgray; 1660 PredecessorList[OtherAtom->nr] = Walker; // Walker is the predecessor 1661 ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1; 1662 //*out << Verbose(2) << "Coloring OtherAtom " << OtherAtom->Name << " lightgray, its predecessor is " << Walker->Name << " and its Shortest Path is " << ShortestPathList[OtherAtom->nr] << " egde(s) long." << endl; 1663 if (ShortestPathList[OtherAtom->nr] < MinimumRingSize) { // Check for maximum distance 1664 //*out << Verbose(3) << "Putting OtherAtom into queue." << endl; 1665 BFSStack->Push(OtherAtom); 1677 1666 } 1678 } while ((OtherAtom->LowpointNr == LP) && (Walker != OtherAtom) && (Root->LowpointNr == OtherAtom->LowpointNr));1679 // now check if the LP is different from Walker's, as then there is one more bond to follow1680 if (LP != Walker->LowpointNr) {1681 // find last bond to home base1682 for(int j=0;j<NumberOfBondsPerAtom[OtherAtom->nr];j++)1683 if (ListOfBondsPerAtom[OtherAtom->nr][j]->GetOtherAtom(OtherAtom) == Root) {1684 *out << " <-> " << OtherAtom->Name;1685 RingSize++;1686 NoCyclicBondsPerAtom[OtherAtom->nr]--;1687 }1688 1667 } else { 1689 // we have made the complete cycle1668 //*out << Verbose(3) << "Not Adding, has already been visited." << endl; 1690 1669 } 1691 *out << " <-> ... with cycle length of " << RingSize << "." << endl; 1692 NumCycles++; 1693 if ((RingSize < MinimumRingSize) || (MinimumRingSize == -1)) 1694 MinimumRingSize = RingSize; 1670 } else { 1671 //*out << Verbose(3) << "Not Visiting, is a back edge." << endl; 1695 1672 } 1696 1673 } 1697 } 1698 } 1699 1700 // print NoCyclicBondsPerAtom to visually check of all are zero 1701 *out << Verbose(1) << "NoCyclicBondsPerAtom: "; 1702 for(int i=0;i<AtomCount;i++) { 1703 if (NoCyclicBondsPerAtom[i] > 0) 1704 cerr << "There was an error in molecule::CyclicStructureAnalysis!" << endl; 1705 *out << NoCyclicBondsPerAtom[i] << " "; 1706 } 1707 *out << endl; 1674 ColorList[Walker->nr] = black; 1675 //*out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl; 1676 } 1677 1678 if (Walker == Root) { 1679 // now climb back the predecessor list and thus find the cycle members 1680 NumCycles++; 1681 RingSize = 1; 1682 Walker = Root; 1683 *out << Verbose(1) << "Found ring contains: "; 1684 while (Walker != BackEdge->rightatom) { 1685 *out << Walker->Name << " <-> "; 1686 Walker = PredecessorList[Walker->nr]; 1687 RingSize++; 1688 } 1689 *out << Walker->Name << " with a length of " << RingSize << "." << endl << endl; 1690 if (RingSize < MinimumRingSize) 1691 MinimumRingSize = RingSize; 1692 } else { 1693 *out << Verbose(1) << "No ring with length equal to or smaller than " << MinimumRingSize << " found." << endl; 1694 } 1695 1696 // now clean the lists 1697 while (!TouchedStack->IsEmpty()){ 1698 Walker = TouchedStack->PopFirst(); 1699 PredecessorList[Walker->nr] = NULL; 1700 ShortestPathList[Walker->nr] = -1; 1701 ColorList[Walker->nr] = white; 1702 } 1703 } 1704 1708 1705 1709 1706 if (MinimumRingSize != -1) … … 1712 1709 *out << Verbose(1) << "No rings were detected in the molecular structure." << endl; 1713 1710 1714 Free((void **)&NoCyclicBondsPerAtom, "molecule::CyclicStructureAnalysis: *NoCyclicBondsPerAtom"); 1715 delete(AtomStack); 1711 Free((void **)&PredecessorList, "molecule::CyclicStructureAnalysis: **PredecessorList"); 1712 Free((void **)&ShortestPathList, "molecule::CyclicStructureAnalysis: **ShortestPathList"); 1713 Free((void **)&ColorList, "molecule::CyclicStructureAnalysis: **ColorList"); 1714 delete(BFSStack); 1716 1715 }; 1717 1716 -
src/molecules.hpp
r6d35e4 r8d9c38 326 326 // Graph analysis 327 327 MoleculeLeafClass * DepthFirstSearchAnalysis(ofstream *out, bool ReturnStack, int &MinimumRingSize); 328 void CyclicStructureAnalysis(ofstream *out, int &MinimumRingSize);328 void CyclicStructureAnalysis(ofstream *out, class StackClass<bond *> *BackEdgeStack, int &MinimumRingSize); 329 329 bond * FindNextUnused(atom *vertex); 330 330 void SetNextComponentNumber(atom *vertex, int nr);
Note:
See TracChangeset
for help on using the changeset viewer.