Changeset 49c059 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:
- 2fa1dc
- Parents:
- 1a4d4fe
- git-author:
- Frederik Heber <heber@…> (02/25/11 22:15:31)
- git-committer:
- Frederik Heber <heber@…> (03/02/11 21:53:08)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/molecule_graph.cpp
r1a4d4fe r49c059 30 30 #include "CodePatterns/Verbose.hpp" 31 31 #include "config.hpp" 32 #include "Graph/DepthFirstSearchAnalysis.hpp" 32 33 #include "element.hpp" 33 34 #include "Graph/BondGraph.hpp" … … 44 45 #define MAXBONDS 8 45 46 46 47 /** Accounting data for Depth First Search.48 */49 struct DFSAccounting50 {51 std::deque<atom *> *AtomStack;52 std::deque<bond *> *BackEdgeStack;53 int CurrentGraphNr;54 int ComponentNumber;55 atom *Root;56 bool BackStepping;57 };58 59 /************************************* Functions for class molecule *********************************/60 47 61 48 /** Fills the bond structure of this chain list subgraphs that are derived from a complete \a *reference molecule. … … 146 133 ; 147 134 148 149 /** Counts all cyclic bonds and returns their number.150 * \note Hydrogen bonds can never by cyclic, thus no check for that151 * \return number of cyclic bonds152 */153 int molecule::CountCyclicBonds()154 {155 NoCyclicBonds = 0;156 int *MinimumRingSize = NULL;157 MoleculeLeafClass *Subgraphs = NULL;158 std::deque<bond *> *BackEdgeStack = NULL;159 for(molecule::iterator AtomRunner = begin(); AtomRunner != end(); ++AtomRunner) {160 const BondList& ListOfBonds = (*AtomRunner)->getListOfBonds();161 if ((!ListOfBonds.empty()) && ((*ListOfBonds.begin())->Type == GraphEdge::Undetermined)) {162 DoLog(0) && (Log() << Verbose(0) << "No Depth-First-Search analysis performed so far, calling ..." << endl);163 Subgraphs = DepthFirstSearchAnalysis(BackEdgeStack);164 while (Subgraphs->next != NULL) {165 Subgraphs = Subgraphs->next;166 delete (Subgraphs->previous);167 }168 delete (Subgraphs);169 delete[] (MinimumRingSize);170 break;171 }172 }173 for(molecule::iterator AtomRunner = begin(); AtomRunner != end(); ++AtomRunner) {174 const BondList& ListOfBonds = (*AtomRunner)->getListOfBonds();175 for(BondList::const_iterator BondRunner = ListOfBonds.begin();176 BondRunner != ListOfBonds.end();177 ++BondRunner)178 if ((*BondRunner)->leftatom == *AtomRunner)179 if ((*BondRunner)->Cyclic)180 NoCyclicBonds++;181 }182 delete (BackEdgeStack);183 return NoCyclicBonds;184 }185 ;186 187 188 /** Sets atom::GraphNr and atom::LowpointNr to DFSAccounting::CurrentGraphNr.189 * \param *Walker current node190 * \param &BFS structure with accounting data for BFS191 */192 void DepthFirstSearchAnalysis_SetWalkersGraphNr(atom *&Walker, struct DFSAccounting &DFS)193 {194 if (!DFS.BackStepping) { // if we don't just return from (8)195 Walker->GraphNr = DFS.CurrentGraphNr;196 Walker->LowpointNr = DFS.CurrentGraphNr;197 DoLog(1) && (Log() << Verbose(1) << "Setting Walker[" << Walker->getName() << "]'s number to " << Walker->GraphNr << " with Lowpoint " << Walker->LowpointNr << "." << endl);198 DFS.AtomStack->push_front(Walker);199 DFS.CurrentGraphNr++;200 }201 }202 ;203 204 /** During DFS goes along unvisited bond and touches other atom.205 * Sets bond::type, if206 * -# BackEdge: set atom::LowpointNr and push on \a BackEdgeStack207 * -# TreeEgde: set atom::Ancestor and continue with Walker along this edge208 * Continue until molecule::FindNextUnused() finds no more unused bonds.209 * \param *mol molecule with atoms and finding unused bonds210 * \param *&Binder current edge211 * \param &DFS DFS accounting data212 */213 void DepthFirstSearchAnalysis_ProbeAlongUnusedBond(const molecule * const mol, atom *&Walker, bond *&Binder, struct DFSAccounting &DFS)214 {215 atom *OtherAtom = NULL;216 217 do { // (3) if Walker has no unused egdes, go to (5)218 DFS.BackStepping = false; // reset backstepping flag for (8)219 if (Binder == NULL) // if we don't just return from (11), Binder is already set to next unused220 Binder = mol->FindNextUnused(Walker);221 if (Binder == NULL)222 break;223 DoLog(2) && (Log() << Verbose(2) << "Current Unused Bond is " << *Binder << "." << endl);224 // (4) Mark Binder used, ...225 Binder->MarkUsed(GraphEdge::black);226 OtherAtom = Binder->GetOtherAtom(Walker);227 DoLog(2) && (Log() << Verbose(2) << "(4) OtherAtom is " << OtherAtom->getName() << "." << endl);228 if (OtherAtom->GraphNr != -1) {229 // (4a) ... if "other" atom has been visited (GraphNr != 0), set lowpoint to minimum of both, go to (3)230 Binder->Type = GraphEdge::BackEdge;231 DFS.BackEdgeStack->push_front(Binder);232 Walker->LowpointNr = (Walker->LowpointNr < OtherAtom->GraphNr) ? Walker->LowpointNr : OtherAtom->GraphNr;233 DoLog(3) && (Log() << Verbose(3) << "(4a) Visited: Setting Lowpoint of Walker[" << Walker->getName() << "] to " << Walker->LowpointNr << "." << endl);234 } else {235 // (4b) ... otherwise set OtherAtom as Ancestor of Walker and Walker as OtherAtom, go to (2)236 Binder->Type = GraphEdge::TreeEdge;237 OtherAtom->Ancestor = Walker;238 Walker = OtherAtom;239 DoLog(3) && (Log() << Verbose(3) << "(4b) Not Visited: OtherAtom[" << OtherAtom->getName() << "]'s Ancestor is now " << OtherAtom->Ancestor->getName() << ", Walker is OtherAtom " << OtherAtom->getName() << "." << endl);240 break;241 }242 Binder = NULL;243 } while (1); // (3)244 }245 ;246 247 /** Checks whether we have a new component.248 * if atom::LowpointNr of \a *&Walker is greater than atom::GraphNr of its atom::Ancestor, we have a new component.249 * Meaning that if we touch upon a node who suddenly has a smaller atom::LowpointNr than its ancestor, then we250 * have a found a new branch in the graph tree.251 * \param *mol molecule with atoms and finding unused bonds252 * \param *&Walker current node253 * \param &DFS DFS accounting data254 */255 void DepthFirstSearchAnalysis_CheckForaNewComponent(const molecule * const mol, atom *&Walker, struct DFSAccounting &DFS, MoleculeLeafClass *&LeafWalker)256 {257 atom *OtherAtom = NULL;258 259 // (5) if Ancestor of Walker is ...260 DoLog(1) && (Log() << Verbose(1) << "(5) Number of Walker[" << Walker->getName() << "]'s Ancestor[" << Walker->Ancestor->getName() << "] is " << Walker->Ancestor->GraphNr << "." << endl);261 262 if (Walker->Ancestor->GraphNr != DFS.Root->GraphNr) {263 // (6) (Ancestor of Walker is not Root)264 if (Walker->LowpointNr < Walker->Ancestor->GraphNr) {265 // (6a) set Ancestor's Lowpoint number to minimum of of its Ancestor and itself, go to Step(8)266 Walker->Ancestor->LowpointNr = (Walker->Ancestor->LowpointNr < Walker->LowpointNr) ? Walker->Ancestor->LowpointNr : Walker->LowpointNr;267 DoLog(2) && (Log() << Verbose(2) << "(6) Setting Walker[" << Walker->getName() << "]'s Ancestor[" << Walker->Ancestor->getName() << "]'s Lowpoint to " << Walker->Ancestor->LowpointNr << "." << endl);268 } else {269 // (7) (Ancestor of Walker is a separating vertex, remove all from stack till Walker (including), these and Ancestor form a component270 Walker->Ancestor->SeparationVertex = true;271 DoLog(2) && (Log() << Verbose(2) << "(7) Walker[" << Walker->getName() << "]'s Ancestor[" << Walker->Ancestor->getName() << "]'s is a separating vertex, creating component." << endl);272 mol->SetNextComponentNumber(Walker->Ancestor, DFS.ComponentNumber);273 DoLog(3) && (Log() << Verbose(3) << "(7) Walker[" << Walker->getName() << "]'s Ancestor's Compont is " << DFS.ComponentNumber << "." << endl);274 mol->SetNextComponentNumber(Walker, DFS.ComponentNumber);275 DoLog(3) && (Log() << Verbose(3) << "(7) Walker[" << Walker->getName() << "]'s Compont is " << DFS.ComponentNumber << "." << endl);276 do {277 ASSERT(!DFS.AtomStack->empty(), "DepthFirstSearchAnalysis_CheckForaNewComponent() - DFS.AtomStack is empty!");278 OtherAtom = DFS.AtomStack->front();279 DFS.AtomStack->pop_front();280 LeafWalker->Leaf->AddCopyAtom(OtherAtom);281 mol->SetNextComponentNumber(OtherAtom, DFS.ComponentNumber);282 DoLog(3) && (Log() << Verbose(3) << "(7) Other[" << OtherAtom->getName() << "]'s Compont is " << DFS.ComponentNumber << "." << endl);283 } while (OtherAtom != Walker);284 DFS.ComponentNumber++;285 }286 // (8) Walker becomes its Ancestor, go to (3)287 DoLog(2) && (Log() << Verbose(2) << "(8) Walker[" << Walker->getName() << "] is now its Ancestor " << Walker->Ancestor->getName() << ", backstepping. " << endl);288 Walker = Walker->Ancestor;289 DFS.BackStepping = true;290 }291 }292 ;293 294 /** Cleans the root stack when we have found a component.295 * If we are not DFSAccounting::BackStepping, then we clear the root stack by putting everything into a296 * component down till we meet DFSAccounting::Root.297 * \param *mol molecule with atoms and finding unused bonds298 * \param *&Walker current node299 * \param *&Binder current edge300 * \param &DFS DFS accounting data301 */302 void DepthFirstSearchAnalysis_CleanRootStackDownTillWalker(const molecule * const mol, atom *&Walker, bond *&Binder, struct DFSAccounting &DFS, MoleculeLeafClass *&LeafWalker)303 {304 atom *OtherAtom = NULL;305 306 if (!DFS.BackStepping) { // coming from (8) want to go to (3)307 // (9) remove all from stack till Walker (including), these and Root form a component308 //DFS.AtomStack->Output(out);309 mol->SetNextComponentNumber(DFS.Root, DFS.ComponentNumber);310 DoLog(3) && (Log() << Verbose(3) << "(9) Root[" << DFS.Root->getName() << "]'s Component is " << DFS.ComponentNumber << "." << endl);311 mol->SetNextComponentNumber(Walker, DFS.ComponentNumber);312 DoLog(3) && (Log() << Verbose(3) << "(9) Walker[" << Walker->getName() << "]'s Component is " << DFS.ComponentNumber << "." << endl);313 do {314 ASSERT(!DFS.AtomStack->empty(), "DepthFirstSearchAnalysis_CleanRootStackDownTillWalker() - DFS.AtomStack is empty!");315 OtherAtom = DFS.AtomStack->front();316 DFS.AtomStack->pop_front();317 LeafWalker->Leaf->AddCopyAtom(OtherAtom);318 mol->SetNextComponentNumber(OtherAtom, DFS.ComponentNumber);319 DoLog(3) && (Log() << Verbose(3) << "(7) Other[" << OtherAtom->getName() << "]'s Component is " << DFS.ComponentNumber << "." << endl);320 } while (OtherAtom != Walker);321 DFS.ComponentNumber++;322 323 // (11) Root is separation vertex, set Walker to Root and go to (4)324 Walker = DFS.Root;325 Binder = mol->FindNextUnused(Walker);326 DoLog(1) && (Log() << Verbose(1) << "(10) Walker is Root[" << DFS.Root->getName() << "], next Unused Bond is " << Binder << "." << endl);327 if (Binder != NULL) { // Root is separation vertex328 DoLog(1) && (Log() << Verbose(1) << "(11) Root is a separation vertex." << endl);329 Walker->SeparationVertex = true;330 }331 }332 }333 ;334 335 /** Initializes DFSAccounting structure.336 * \param &DFS accounting structure to allocate337 * \param *mol molecule with AtomCount, BondCount and all atoms338 */339 void DepthFirstSearchAnalysis_Init(struct DFSAccounting &DFS, const molecule * const mol)340 {341 DFS.AtomStack = new std::deque<atom *> (mol->getAtomCount());342 DFS.CurrentGraphNr = 0;343 DFS.ComponentNumber = 0;344 DFS.BackStepping = false;345 mol->ResetAllBondsToUnused();346 DFS.BackEdgeStack->clear();347 }348 ;349 350 /** Free's DFSAccounting structure.351 * \param &DFS accounting structure to free352 */353 void DepthFirstSearchAnalysis_Finalize(struct DFSAccounting &DFS)354 {355 delete (DFS.AtomStack);356 // delete (DFS.BackEdgeStack); // DON'T free, see DepthFirstSearchAnalysis(), is returned as allocated357 }358 ;359 360 void molecule::init_DFS(struct DFSAccounting &DFS) const{361 DepthFirstSearchAnalysis_Init(DFS, this);362 for_each(atoms.begin(),atoms.end(),mem_fun(&atom::resetGraphNr));363 for_each(atoms.begin(),atoms.end(),mem_fun(&atom::InitComponentNr));364 }365 366 /** Performs a Depth-First search on this molecule.367 * Marks bonds in molecule as cyclic, bridge, ... and atoms as368 * articulations points, ...369 * We use the algorithm from [Even, Graph Algorithms, p.62].370 * \param *&BackEdgeStack NULL pointer to std::deque<bond *> with all the found back edges, allocated and filled on return371 * \return list of each disconnected subgraph as an individual molecule class structure372 */373 MoleculeLeafClass * molecule::DepthFirstSearchAnalysis(std::deque<bond *> *&BackEdgeStack) const374 {375 struct DFSAccounting DFS;376 BackEdgeStack = new std::deque<bond *> (getBondCount());377 DFS.BackEdgeStack = BackEdgeStack;378 MoleculeLeafClass *SubGraphs = new MoleculeLeafClass(NULL);379 MoleculeLeafClass *LeafWalker = SubGraphs;380 int OldGraphNr = 0;381 atom *Walker = NULL;382 bond *Binder = NULL;383 384 if (getAtomCount() == 0)385 return SubGraphs;386 DoLog(0) && (Log() << Verbose(0) << "Begin of DepthFirstSearchAnalysis" << endl);387 init_DFS(DFS);388 389 for (molecule::const_iterator iter = begin(); iter != end();) {390 DFS.Root = *iter;391 // (1) mark all edges unused, empty stack, set atom->GraphNr = -1 for all392 DFS.AtomStack->clear();393 394 // put into new subgraph molecule and add this to list of subgraphs395 LeafWalker = new MoleculeLeafClass(LeafWalker);396 LeafWalker->Leaf = World::getInstance().createMolecule();397 LeafWalker->Leaf->AddCopyAtom(DFS.Root);398 399 OldGraphNr = DFS.CurrentGraphNr;400 Walker = DFS.Root;401 do { // (10)402 do { // (2) set number and Lowpoint of Atom to i, increase i, push current atom403 DepthFirstSearchAnalysis_SetWalkersGraphNr(Walker, DFS);404 405 DepthFirstSearchAnalysis_ProbeAlongUnusedBond(this, Walker, Binder, DFS);406 407 if (Binder == NULL) {408 DoLog(2) && (Log() << Verbose(2) << "No more Unused Bonds." << endl);409 break;410 } else411 Binder = NULL;412 } while (1); // (2)413 414 // if we came from backstepping, yet there were no more unused bonds, we end up here with no Ancestor, because Walker is Root! Then we are finished!415 if ((Walker == DFS.Root) && (Binder == NULL))416 break;417 418 DepthFirstSearchAnalysis_CheckForaNewComponent(this, Walker, DFS, LeafWalker);419 420 DepthFirstSearchAnalysis_CleanRootStackDownTillWalker(this, Walker, Binder, DFS, LeafWalker);421 422 } while ((DFS.BackStepping) || (Binder != NULL)); // (10) halt only if Root has no unused edges423 424 // From OldGraphNr to CurrentGraphNr ranges an disconnected subgraph425 DoLog(0) && (Log() << Verbose(0) << "Disconnected subgraph ranges from " << OldGraphNr << " to " << DFS.CurrentGraphNr << "." << endl);426 LeafWalker->Leaf->Output((ofstream *)&(Log() << Verbose(0)));427 DoLog(0) && (Log() << Verbose(0) << endl);428 429 // step on to next root430 while ((iter != end()) && ((*iter)->GraphNr != -1)) {431 //Log() << Verbose(1) << "Current next subgraph root candidate is " << (*iter)->Name << "." << endl;432 if ((*iter)->GraphNr != -1) // if already discovered, step on433 iter++;434 }435 }436 // set cyclic bond criterium on "same LP" basis437 CyclicBondAnalysis();438 439 OutputGraphInfoPerAtom();440 441 OutputGraphInfoPerBond();442 443 // free all and exit444 DepthFirstSearchAnalysis_Finalize(DFS);445 DoLog(0) && (Log() << Verbose(0) << "End of DepthFirstSearchAnalysis" << endl);446 return SubGraphs;447 }448 ;449 450 /** Scans through all bonds and set bond::Cyclic to true where atom::LowpointNr of both ends is equal: LP criterion.451 */452 void molecule::CyclicBondAnalysis() const453 {454 NoCyclicBonds = 0;455 for(molecule::const_iterator AtomRunner = begin(); AtomRunner != end(); ++AtomRunner) {456 const BondList& ListOfBonds = (*AtomRunner)->getListOfBonds();457 for(BondList::const_iterator BondRunner = ListOfBonds.begin();458 BondRunner != ListOfBonds.end();459 ++BondRunner)460 if ((*BondRunner)->leftatom == *AtomRunner)461 if ((*BondRunner)->rightatom->LowpointNr == (*BondRunner)->leftatom->LowpointNr) { // cyclic ??462 (*BondRunner)->Cyclic = true;463 NoCyclicBonds++;464 }465 }466 }467 ;468 469 /** Output graph information per atom.470 */471 void molecule::OutputGraphInfoPerAtom() const472 {473 DoLog(1) && (Log() << Verbose(1) << "Final graph info for each atom is:" << endl);474 for_each(atoms.begin(),atoms.end(),mem_fun(&atom::OutputGraphInfo));475 }476 ;477 478 /** Output graph information per bond.479 */480 void molecule::OutputGraphInfoPerBond() const481 {482 DoLog(1) && (Log() << Verbose(1) << "Final graph info for each bond is:" << endl);483 for(molecule::const_iterator AtomRunner = begin(); AtomRunner != end(); ++AtomRunner) {484 const BondList& ListOfBonds = (*AtomRunner)->getListOfBonds();485 for(BondList::const_iterator BondRunner = ListOfBonds.begin();486 BondRunner != ListOfBonds.end();487 ++BondRunner)488 if ((*BondRunner)->leftatom == *AtomRunner) {489 const bond *Binder = *BondRunner;490 if (DoLog(2)) {491 ostream &out = (Log() << Verbose(2));492 out << ((Binder->Type == GraphEdge::TreeEdge) ? "TreeEdge " : "BackEdge ") << *Binder << ": <";493 out << ((Binder->leftatom->SeparationVertex) ? "SP," : "") << "L" << Binder->leftatom->LowpointNr << " G" << Binder->leftatom->GraphNr << " Comp.";494 Binder->leftatom->OutputComponentNumber(&out);495 out << " === ";496 out << ((Binder->rightatom->SeparationVertex) ? "SP," : "") << "L" << Binder->rightatom->LowpointNr << " G" << Binder->rightatom->GraphNr << " Comp.";497 Binder->rightatom->OutputComponentNumber(&out);498 out << ">." << endl;499 }500 if (Binder->Cyclic) // cyclic ??501 DoLog(3) && (Log() << Verbose(3) << "Lowpoint at each side are equal: CYCLIC!" << endl);502 }503 }504 }505 ;506 507 /** Sets the next component number.508 * This is O(N) as the number of bonds per atom is bound.509 * \param *vertex atom whose next atom::*ComponentNr is to be set510 * \param Nr number to use511 */512 void molecule::SetNextComponentNumber(atom *vertex, int nr) const513 {514 size_t i = 0;515 if (vertex != NULL) {516 const BondList& ListOfBonds = vertex->getListOfBonds();517 for (; i < ListOfBonds.size(); i++) {518 if (vertex->ComponentNr[i] == -1) { // check if not yet used519 vertex->ComponentNr[i] = nr;520 break;521 } else if (vertex->ComponentNr[i] == nr) // if number is already present, don't add another time522 break; // breaking here will not cause error!523 }524 if (i == ListOfBonds.size()) {525 DoeLog(0) && (eLog()<< Verbose(0) << "Error: All Component entries are already occupied!" << endl);526 performCriticalExit();527 }528 } else {529 DoeLog(0) && (eLog()<< Verbose(0) << "Error: Given vertex is NULL!" << endl);530 performCriticalExit();531 }532 }533 ;534 535 /** Returns next unused bond for this atom \a *vertex or NULL of none exists.536 * \param *vertex atom to regard537 * \return bond class or NULL538 */539 bond * molecule::FindNextUnused(atom *vertex) const540 {541 const BondList& ListOfBonds = vertex->getListOfBonds();542 for (BondList::const_iterator Runner = ListOfBonds.begin();543 Runner != ListOfBonds.end();544 ++Runner)545 if ((*Runner)->IsUsed() == GraphEdge::white)546 return ((*Runner));547 return NULL;548 }549 ;550 551 /** Resets bond::Used flag of all bonds in this molecule.552 * \return true - success, false - -failure553 */554 void molecule::ResetAllBondsToUnused() const555 {556 for(molecule::const_iterator AtomRunner = begin(); AtomRunner != end(); ++AtomRunner) {557 const BondList& ListOfBonds = (*AtomRunner)->getListOfBonds();558 for(BondList::const_iterator BondRunner = ListOfBonds.begin();559 BondRunner != ListOfBonds.end();560 ++BondRunner)561 if ((*BondRunner)->leftatom == *AtomRunner)562 (*BondRunner)->ResetUsed();563 }564 }565 ;566 567 /** Output a list of flags, stating whether the bond was visited or not.568 * \param *list list to print569 */570 void OutputAlreadyVisited(int *list)571 {572 DoLog(4) && (Log() << Verbose(4) << "Already Visited Bonds:\t");573 for (int i = 1; i <= list[0]; i++)574 DoLog(0) && (Log() << Verbose(0) << list[i] << " ");575 DoLog(0) && (Log() << Verbose(0) << endl);576 }577 ;578 135 579 136 /** Storing the bond structure of a molecule to file. … … 755 312 ; 756 313 757 /** Picks from a global stack with all back edges the ones in the fragment.758 * \param **ListOfLocalAtoms array of father atom::Nr to local atom::Nr (reverse of atom::father)759 * \param *ReferenceStack stack with all the back egdes760 * \param *LocalStack stack to be filled761 * \return true - everything ok, false - ReferenceStack was empty762 */763 bool molecule::PickLocalBackEdges(atom **ListOfLocalAtoms, std::deque<bond *> *&ReferenceStack, std::deque<bond *> *&LocalStack) const764 {765 bool status = true;766 if (ReferenceStack->empty()) {767 DoLog(1) && (Log() << Verbose(1) << "ReferenceStack is empty!" << endl);768 return false;769 }770 bond *Binder = ReferenceStack->front();771 ReferenceStack->pop_front();772 bond *FirstBond = Binder; // mark the first bond, so that we don't loop through the stack indefinitely773 atom *Walker = NULL, *OtherAtom = NULL;774 ReferenceStack->push_front(Binder);775 776 do { // go through all bonds and push local ones777 Walker = ListOfLocalAtoms[Binder->leftatom->getNr()]; // get one atom in the reference molecule778 if (Walker != NULL) { // if this Walker exists in the subgraph ...779 const BondList& ListOfBonds = Walker->getListOfBonds();780 for (BondList::const_iterator Runner = ListOfBonds.begin();781 Runner != ListOfBonds.end();782 ++Runner) {783 OtherAtom = (*Runner)->GetOtherAtom(Walker);784 if (OtherAtom == ListOfLocalAtoms[(*Runner)->rightatom->getNr()]) { // found the bond785 LocalStack->push_front((*Runner));786 DoLog(3) && (Log() << Verbose(3) << "Found local edge " << *(*Runner) << "." << endl);787 break;788 }789 }790 }791 ASSERT(!ReferenceStack->empty(), "molecule::PickLocalBackEdges() - ReferenceStack is empty!");792 Binder = ReferenceStack->front(); // loop the stack for next item793 ReferenceStack->pop_front();794 DoLog(3) && (Log() << Verbose(3) << "Current candidate edge " << Binder << "." << endl);795 ReferenceStack->push_front(Binder);796 } while (FirstBond != Binder);797 798 return status;799 }800 ;801 802 314 /** Adds a bond as a copy to a given one 803 315 * \param *left leftatom of new bond … … 891 403 ; 892 404 893 /** For a given keyset \a *Fragment, checks whether it is connected in the current molecule. 894 * \param *Fragment Keyset of fragment's vertices 895 * \return true - connected, false - disconnected 896 * \note this is O(n^2) for it's just a bug checker not meant for permanent use! 897 */ 898 bool molecule::CheckForConnectedSubgraph(KeySet *Fragment) 899 { 900 atom *Walker = NULL, *Walker2 = NULL; 901 bool BondStatus = false; 902 int size; 903 904 DoLog(1) && (Log() << Verbose(1) << "Begin of CheckForConnectedSubgraph" << endl); 905 DoLog(2) && (Log() << Verbose(2) << "Disconnected atom: "); 906 907 // count number of atoms in graph 908 size = 0; 909 for (KeySet::iterator runner = Fragment->begin(); runner != Fragment->end(); runner++) 910 size++; 911 if (size > 1) 912 for (KeySet::iterator runner = Fragment->begin(); runner != Fragment->end(); runner++) { 913 Walker = FindAtom(*runner); 914 BondStatus = false; 915 for (KeySet::iterator runners = Fragment->begin(); runners != Fragment->end(); runners++) { 916 Walker2 = FindAtom(*runners); 917 const BondList& ListOfBonds = Walker->getListOfBonds(); 918 for (BondList::const_iterator Runner = ListOfBonds.begin(); 919 Runner != ListOfBonds.end(); 920 ++Runner) { 921 if ((*Runner)->GetOtherAtom(Walker) == Walker2) { 922 BondStatus = true; 923 break; 924 } 925 if (BondStatus) 926 break; 927 } 928 } 929 if (!BondStatus) { 930 DoLog(0) && (Log() << Verbose(0) << (*Walker) << endl); 931 return false; 932 } 933 } 934 else { 935 DoLog(0) && (Log() << Verbose(0) << "none." << endl); 936 return true; 937 } 938 DoLog(0) && (Log() << Verbose(0) << "none." << endl); 939 940 DoLog(1) && (Log() << Verbose(1) << "End of CheckForConnectedSubgraph" << endl); 941 942 return true; 943 } 944 945 /** Fills a lookup list of father's Atom::Nr -> atom for each subgraph. 946 * \param *out output stream from debugging 405 /** Fills a lookup list of father's Atom::nr -> atom for each subgraph. 947 406 * \param **&ListOfLocalAtoms Lookup table for each subgraph and index of each atom in global molecule, may be NULL on start, then it is filled 948 407 * \param GlobalAtomCount number of atoms in the complete molecule
Note:
See TracChangeset
for help on using the changeset viewer.