Ignore:
Timestamp:
Oct 18, 2009, 5:52:47 PM (15 years ago)
Author:
Frederik Heber <heber@…>
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:
43587e
Parents:
ba4170
Message:

Refactored molecule::BreadthFirstSearchAdd()

  • new function: BreadthFirstSearchAdd_Init(), BreadthFirstSearchAdd_VisitedNode(), BreadthFirstSearchAdd_UnvisitedNode()
  • new structure BFSAccounting contains all of the accounting data needed for Breadth First Search.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/molecule_graph.cpp

    rba4170 rce7cc5  
    983983};
    984984
     985struct BFSAccounting {
     986  atom **PredecessorList;
     987  int *ShortestPathList;
     988  enum Shading *ColorList;
     989  class StackClass<atom *> *AtomStack;
     990  int AtomCount;
     991  int BondOrder;
     992  atom *Root;
     993};
     994
     995void BreadthFirstSearchAdd_Init(struct BFSAccounting &BFS, atom *&Root, int AtomCount, int BondOrder, atom **AddedAtomList = NULL)
     996{
     997  BFS.AtomCount = AtomCount;
     998  BFS.BondOrder = BondOrder;
     999  BFS.PredecessorList = Malloc<atom*>(AtomCount, "molecule::BreadthFirstSearchAdd_Init: **PredecessorList");
     1000  BFS.ShortestPathList = Malloc<int>(AtomCount, "molecule::BreadthFirstSearchAdd_Init: *ShortestPathList");
     1001  BFS.ColorList = Malloc<enum Shading>(AtomCount, "molecule::BreadthFirstSearchAdd_Init: *ColorList");
     1002  BFS.AtomStack = new StackClass<atom *>(AtomCount);
     1003
     1004  BFS.Root = Root;
     1005  BFS.AtomStack->ClearStack();
     1006  BFS.AtomStack->Push(Root);
     1007
     1008  // initialise each vertex as white with no predecessor, empty queue, color Root lightgray
     1009  for (int i=AtomCount;i--;) {
     1010    BFS.PredecessorList[i] = NULL;
     1011    BFS.ShortestPathList[i] = -1;
     1012    if ((AddedAtomList != NULL) && (AddedAtomList[i] != NULL)) // mark already present atoms (i.e. Root and maybe others) as visited
     1013      BFS.ColorList[i] = lightgray;
     1014    else
     1015      BFS.ColorList[i] = white;
     1016  }
     1017  BFS.ShortestPathList[Root->nr] = 0;
     1018};
     1019
     1020void BreadthFirstSearchAdd_Free(struct BFSAccounting &BFS)
     1021{
     1022  Free(&BFS.PredecessorList);
     1023  Free(&BFS.ShortestPathList);
     1024  Free(&BFS.ColorList);
     1025  delete(BFS.AtomStack);
     1026  BFS.AtomCount = 0;
     1027};
     1028
     1029
     1030void BreadthFirstSearchAdd_UnvisitedNode(ofstream *out, molecule *Mol, struct BFSAccounting &BFS, atom *&Walker, atom *&OtherAtom, bond *&Binder, bond *&Bond, atom **&AddedAtomList, bond **&AddedBondList, bool IsAngstroem)
     1031{
     1032  if (Binder != Bond) // let other atom white if it's via Root bond. In case it's cyclic it has to be reached again (yet Root is from OtherAtom already black, thus no problem)
     1033    BFS.ColorList[OtherAtom->nr] = lightgray;
     1034  BFS.PredecessorList[OtherAtom->nr] = Walker;  // Walker is the predecessor
     1035  BFS.ShortestPathList[OtherAtom->nr] = BFS.ShortestPathList[Walker->nr]+1;
     1036  *out << Verbose(2) << "Coloring OtherAtom " << OtherAtom->Name << " " << ((BFS.ColorList[OtherAtom->nr] == white) ? "white" : "lightgray") << ", its predecessor is " << Walker->Name << " and its Shortest Path is " << BFS.ShortestPathList[OtherAtom->nr] << " egde(s) long." << endl;
     1037  if ((((BFS.ShortestPathList[OtherAtom->nr] < BFS.BondOrder) && (Binder != Bond))) ) { // Check for maximum distance
     1038    *out << Verbose(3);
     1039    if (AddedAtomList[OtherAtom->nr] == NULL) { // add if it's not been so far
     1040      AddedAtomList[OtherAtom->nr] = Mol->AddCopyAtom(OtherAtom);
     1041      *out << "Added OtherAtom " << OtherAtom->Name;
     1042      AddedBondList[Binder->nr] = Mol->CopyBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder);
     1043      *out << " and bond " << *(AddedBondList[Binder->nr]) << ", ";
     1044    } else {  // this code should actually never come into play (all white atoms are not yet present in BondMolecule, that's why they are white in the first place)
     1045      *out << "Not adding OtherAtom " << OtherAtom->Name;
     1046      if (AddedBondList[Binder->nr] == NULL) {
     1047        AddedBondList[Binder->nr] = Mol->CopyBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder);
     1048        *out << ", added Bond " << *(AddedBondList[Binder->nr]);
     1049      } else
     1050        *out << ", not added Bond ";
     1051    }
     1052    *out << ", putting OtherAtom into queue." << endl;
     1053    BFS.AtomStack->Push(OtherAtom);
     1054  } else { // out of bond order, then replace
     1055    if ((AddedAtomList[OtherAtom->nr] == NULL) && (Binder->Cyclic))
     1056      BFS.ColorList[OtherAtom->nr] = white; // unmark if it has not been queued/added, to make it available via its other bonds (cyclic)
     1057    if (Binder == Bond)
     1058      *out << Verbose(3) << "Not Queueing, is the Root bond";
     1059    else if (BFS.ShortestPathList[OtherAtom->nr] >= BFS.BondOrder)
     1060      *out << Verbose(3) << "Not Queueing, is out of Bond Count of " << BFS.BondOrder;
     1061    if (!Binder->Cyclic)
     1062      *out << ", is not part of a cyclic bond, saturating bond with Hydrogen." << endl;
     1063    if (AddedBondList[Binder->nr] == NULL) {
     1064      if ((AddedAtomList[OtherAtom->nr] != NULL)) { // .. whether we add or saturate
     1065        AddedBondList[Binder->nr] = Mol->CopyBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder);
     1066      } else {
     1067  #ifdef ADDHYDROGEN
     1068        if (!Mol->AddHydrogenReplacementAtom(out, Binder, AddedAtomList[Walker->nr], Walker, OtherAtom, IsAngstroem))
     1069          exit(1);
     1070  #endif
     1071      }
     1072    }
     1073  }
     1074};
     1075
     1076void BreadthFirstSearchAdd_VisitedNode(ofstream *out, molecule *Mol, struct BFSAccounting &BFS, atom *&Walker, atom *&OtherAtom, bond *&Binder, bond *&Bond, atom **&AddedAtomList, bond **&AddedBondList, bool IsAngstroem)
     1077{
     1078  *out << Verbose(3) << "Not Adding, has already been visited." << endl;
     1079  // This has to be a cyclic bond, check whether it's present ...
     1080  if (AddedBondList[Binder->nr] == NULL) {
     1081    if ((Binder != Bond) && (Binder->Cyclic) && (((BFS.ShortestPathList[Walker->nr]+1) < BFS.BondOrder))) {
     1082      AddedBondList[Binder->nr] = Mol->CopyBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder);
     1083    } else { // if it's root bond it has to broken (otherwise we would not create the fragments)
     1084  #ifdef ADDHYDROGEN
     1085      if(!Mol->AddHydrogenReplacementAtom(out, Binder, AddedAtomList[Walker->nr], Walker, OtherAtom, IsAngstroem))
     1086        exit(1);
     1087  #endif
     1088    }
     1089  }
     1090};
    9851091
    9861092/** Adds atoms up to \a BondCount distance from \a *Root and notes them down in \a **AddedAtomList.
     
    9981104void molecule::BreadthFirstSearchAdd(ofstream *out, molecule *Mol, atom **&AddedAtomList, bond **&AddedBondList, atom *Root, bond *Bond, int BondOrder, bool IsAngstroem)
    9991105{
    1000   atom **PredecessorList = Malloc<atom*>(AtomCount, "molecule::BreadthFirstSearchAdd: **PredecessorList");
    1001   int *ShortestPathList = Malloc<int>(AtomCount, "molecule::BreadthFirstSearchAdd: *ShortestPathList");
    1002   enum Shading *ColorList = Malloc<enum Shading>(AtomCount, "molecule::BreadthFirstSearchAdd: *ColorList");
    1003   class StackClass<atom *> *AtomStack = new StackClass<atom *>(AtomCount);
     1106  struct BFSAccounting BFS;
    10041107  atom *Walker = NULL, *OtherAtom = NULL;
     1108  bond *Binder = NULL;
    10051109
    10061110  // add Root if not done yet
    1007   AtomStack->ClearStack();
    10081111  if (AddedAtomList[Root->nr] == NULL)  // add Root if not yet present
    10091112    AddedAtomList[Root->nr] = Mol->AddCopyAtom(Root);
    1010   AtomStack->Push(Root);
    1011 
    1012   // initialise each vertex as white with no predecessor, empty queue, color Root lightgray
    1013   for (int i=AtomCount;i--;) {
    1014     PredecessorList[i] = NULL;
    1015     ShortestPathList[i] = -1;
    1016     if (AddedAtomList[i] != NULL) // mark already present atoms (i.e. Root and maybe others) as visited
    1017       ColorList[i] = lightgray;
    1018     else
    1019       ColorList[i] = white;
    1020   }
    1021   ShortestPathList[Root->nr] = 0;
     1113
     1114  BreadthFirstSearchAdd_Init(BFS, Root, BondOrder, AtomCount, AddedAtomList);
    10221115
    10231116  // and go on ... Queue always contains all lightgray vertices
    1024   while (!AtomStack->IsEmpty()) {
     1117  while (!BFS.AtomStack->IsEmpty()) {
    10251118    // we have to pop the oldest atom from stack. This keeps the atoms on the stack always of the same ShortestPath distance.
    10261119    // e.g. if current atom is 2, push to end of stack are of length 3, but first all of length 2 would be popped. They again
    10271120    // append length of 3 (their neighbours). Thus on stack we have always atoms of a certain length n at bottom of stack and
    10281121    // followed by n+1 till top of stack.
    1029     Walker = AtomStack->PopFirst(); // pop oldest added
     1122    Walker = BFS.AtomStack->PopFirst(); // pop oldest added
    10301123    *out << Verbose(1) << "Current Walker is: " << Walker->Name << ", and has " << Walker->ListOfBonds.size() << " bonds." << endl;
    10311124    for (BondList::const_iterator Runner = Walker->ListOfBonds.begin(); Runner != Walker->ListOfBonds.end(); (++Runner)) {
    10321125      if ((*Runner) != NULL) { // don't look at bond equal NULL
     1126        Binder = (*Runner);
    10331127        OtherAtom = (*Runner)->GetOtherAtom(Walker);
    10341128        *out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *(*Runner) << "." << endl;
    1035         if (ColorList[OtherAtom->nr] == white) {
    1036           if ((*Runner) != Bond) // let other atom white if it's via Root bond. In case it's cyclic it has to be reached again (yet Root is from OtherAtom already black, thus no problem)
    1037             ColorList[OtherAtom->nr] = lightgray;
    1038           PredecessorList[OtherAtom->nr] = Walker;  // Walker is the predecessor
    1039           ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1;
    1040           *out << Verbose(2) << "Coloring OtherAtom " << OtherAtom->Name << " " << ((ColorList[OtherAtom->nr] == white) ? "white" : "lightgray") << ", its predecessor is " << Walker->Name << " and its Shortest Path is " << ShortestPathList[OtherAtom->nr] << " egde(s) long." << endl;
    1041           if ((((ShortestPathList[OtherAtom->nr] < BondOrder) && ((*Runner) != Bond))) ) { // Check for maximum distance
    1042             *out << Verbose(3);
    1043             if (AddedAtomList[OtherAtom->nr] == NULL) { // add if it's not been so far
    1044               AddedAtomList[OtherAtom->nr] = Mol->AddCopyAtom(OtherAtom);
    1045               *out << "Added OtherAtom " << OtherAtom->Name;
    1046               AddedBondList[(*Runner)->nr] = Mol->CopyBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], (*Runner));
    1047               *out << " and bond " << *(AddedBondList[(*Runner)->nr]) << ", ";
    1048             } else {  // this code should actually never come into play (all white atoms are not yet present in BondMolecule, that's why they are white in the first place)
    1049               *out << "Not adding OtherAtom " << OtherAtom->Name;
    1050               if (AddedBondList[(*Runner)->nr] == NULL) {
    1051                 AddedBondList[(*Runner)->nr] = Mol->CopyBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], (*Runner));
    1052                 *out << ", added Bond " << *(AddedBondList[(*Runner)->nr]);
    1053               } else
    1054                 *out << ", not added Bond ";
    1055             }
    1056             *out << ", putting OtherAtom into queue." << endl;
    1057             AtomStack->Push(OtherAtom);
    1058           } else { // out of bond order, then replace
    1059             if ((AddedAtomList[OtherAtom->nr] == NULL) && ((*Runner)->Cyclic))
    1060               ColorList[OtherAtom->nr] = white; // unmark if it has not been queued/added, to make it available via its other bonds (cyclic)
    1061             if ((*Runner) == Bond)
    1062               *out << Verbose(3) << "Not Queueing, is the Root bond";
    1063             else if (ShortestPathList[OtherAtom->nr] >= BondOrder)
    1064               *out << Verbose(3) << "Not Queueing, is out of Bond Count of " << BondOrder;
    1065             if (!(*Runner)->Cyclic)
    1066               *out << ", is not part of a cyclic bond, saturating bond with Hydrogen." << endl;
    1067             if (AddedBondList[(*Runner)->nr] == NULL) {
    1068               if ((AddedAtomList[OtherAtom->nr] != NULL)) { // .. whether we add or saturate
    1069                 AddedBondList[(*Runner)->nr] = Mol->CopyBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], (*Runner));
    1070               } else {
    1071 #ifdef ADDHYDROGEN
    1072                 if (!Mol->AddHydrogenReplacementAtom(out, (*Runner), AddedAtomList[Walker->nr], Walker, OtherAtom, IsAngstroem))
    1073                   exit(1);
    1074 #endif
    1075               }
    1076             }
    1077           }
     1129        if (BFS.ColorList[OtherAtom->nr] == white) {
     1130          BreadthFirstSearchAdd_UnvisitedNode(out, Mol, BFS, Walker, OtherAtom, Binder, Bond, AddedAtomList, AddedBondList, IsAngstroem);
    10781131        } else {
    1079           *out << Verbose(3) << "Not Adding, has already been visited." << endl;
    1080           // This has to be a cyclic bond, check whether it's present ...
    1081           if (AddedBondList[(*Runner)->nr] == NULL) {
    1082             if (((*Runner) != Bond) && ((*Runner)->Cyclic) && (((ShortestPathList[Walker->nr]+1) < BondOrder))) {
    1083               AddedBondList[(*Runner)->nr] = Mol->CopyBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], (*Runner));
    1084             } else { // if it's root bond it has to broken (otherwise we would not create the fragments)
    1085 #ifdef ADDHYDROGEN
    1086               if(!Mol->AddHydrogenReplacementAtom(out, (*Runner), AddedAtomList[Walker->nr], Walker, OtherAtom, IsAngstroem))
    1087                 exit(1);
    1088 #endif
    1089             }
    1090           }
     1132          BreadthFirstSearchAdd_VisitedNode(out, Mol, BFS, Walker, OtherAtom, Binder, Bond, AddedAtomList, AddedBondList, IsAngstroem);
    10911133        }
    10921134      }
    10931135    }
    1094     ColorList[Walker->nr] = black;
     1136    BFS.ColorList[Walker->nr] = black;
    10951137    *out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl;
    10961138  }
    1097   Free(&PredecessorList);
    1098   Free(&ShortestPathList);
    1099   Free(&ColorList);
    1100   delete(AtomStack);
     1139  BreadthFirstSearchAdd_Free(BFS);
    11011140};
    11021141
Note: See TracChangeset for help on using the changeset viewer.