Changeset 83cc3e for src


Ignore:
Timestamp:
Aug 20, 2014, 12:59:22 PM (10 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:
2cb77c
Parents:
4d6d6a
git-author:
Frederik Heber <heber@…> (08/20/14 11:47:12)
git-committer:
Frederik Heber <heber@…> (08/20/14 12:59:22)
Message:

FIX: CyclicStructureAnalysis did not robustly detect all cycles.

  • it depended on the sequence of the back edges. In Coronene most back edges lead to two cycles but at least one back edge is attached to only one cycle.
  • The change is that we now continue after having found a cycle - regardless of whether it is already present or not. This ensures that we find all cycles present.
  • finding a cycle sets however the size of the BFS horizon (we just look for the minimal cycles). This prevents the BFS from stepping through the whole graph.
  • rename CycleBFStoRoot() -> findAllCyclesforBackEdge(), calls RetrieveCycleMembers() on each found cycle (not in operator() anymore).
  • Modified RetrieveCycleMembers() to check whether cycle is present, using IsCyclic checking as a faster mean.
  • operator() dropped NumCycles, is redundantly contained in allcycles.size().
Location:
src/Graph
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • src/Graph/CyclicStructureAnalysis.cpp

    r4d6d6a r83cc3e  
    103103}
    104104
    105 /** Performs a BFS from \a *Root, trying to find the same node and hence a cycle.
     105/** Performs a BFS from \a *Root, trying to find the same node and hence all cycles.
     106 *
     107 * We exclude the back edge, hence the direct way is prohibited. But as it is a back edge,
     108 * there must be at least one more way to \a *Root. This leads us to all cycles for this
     109 * back edge.
     110 *
    106111 * \param OtherAtom pointing to Root on return indicating found cycle
    107112 * \param *&BackEdge the edge from root that we don't want to move along
    108  */
    109 void CyclicStructureAnalysis::CyclicBFSFromRootToRoot(atom *&OtherAtom, bond::ptr &BackEdge)
    110 {
     113 * \param MinRingSize set to minimum over all cycles encountered
     114 */
     115void CyclicStructureAnalysis::findAllCyclesforBackEdge(
     116    atom *&OtherAtom,
     117    bond::ptr &BackEdge,
     118    int &MinRingSize)
     119{
     120  size_t MaximumHorizon = (size_t)-1; // will overflow to largest number
    111121  atom *Walker = NULL;
    112122  do { // look for Root
     
    115125    BFSStack.pop_back();
    116126    LOG(2, "INFO: Current Walker is " << *Walker << ", we look for SP to Root " << *Root << ".");
    117     const BondList& ListOfBonds = Walker->getListOfBonds();
    118     for (BondList::const_iterator Runner = ListOfBonds.begin();
    119         Runner != ListOfBonds.end();
    120         ++Runner) {
    121       if ((*Runner) != BackEdge) { // only walk along DFS spanning tree (otherwise we always find SP of one being backedge Binder)
    122         OtherAtom = (*Runner)->GetOtherAtom(Walker);
    123         if ((treatment == IncludeHydrogen) || (OtherAtom->getType()->getAtomicNumber() != 1)) {
    124           LOG(2, "INFO: Current OtherAtom is: " << OtherAtom->getName() << " for bond " << *(*Runner) << ".");
    125           if (ColorList[OtherAtom->getNr()] == GraphEdge::white) {
    126             TouchedStack.push_front(OtherAtom);
    127             ColorList[OtherAtom->getNr()] = GraphEdge::lightgray;
    128             PredecessorList[OtherAtom->getNr()] = Walker; // Walker is the predecessor
    129             ShortestPathList[OtherAtom->getNr()] = ShortestPathList[Walker->getNr()] + 1;
    130             LOG(2, "INFO: Coloring OtherAtom " << OtherAtom->getName() << " lightgray, its predecessor is " << Walker->getName() << " and its Shortest Path is " << ShortestPathList[OtherAtom->getNr()] << " egde(s) long.");
    131             //if (ShortestPathList[OtherAtom->getNr()] < MinimumRingSize[Walker->GetTrueFather()->getNr()]) { // Check for maximum distance
    132             LOG(3, "ACCEPT: Putting OtherAtom " << OtherAtom->getName() << " into queue.");
    133             BFSStack.push_front(OtherAtom);
    134             //}
     127
     128    // check all edges/bonds from current Walker
     129    if (MaximumHorizon >=  (size_t)ShortestPathList[Walker->getNr()]) {
     130      const BondList& ListOfBonds = Walker->getListOfBonds();
     131      for (BondList::const_iterator Runner = ListOfBonds.begin();
     132          Runner != ListOfBonds.end();
     133          ++Runner) {
     134        if ((*Runner) != BackEdge) { // only walk along DFS spanning tree (otherwise we always find SP of one being backedge Binder)
     135          OtherAtom = (*Runner)->GetOtherAtom(Walker);
     136          if ((treatment == IncludeHydrogen) || (OtherAtom->getType()->getAtomicNumber() != 1)) {
     137            LOG(2, "INFO: Current OtherAtom is: " << OtherAtom->getName() << " for bond " << *(*Runner) << ".");
     138            if (ColorList[OtherAtom->getNr()] == GraphEdge::white) {
     139              // we discovered a new node/atom
     140              TouchedStack.push_front(OtherAtom);
     141              ColorList[OtherAtom->getNr()] = GraphEdge::lightgray;
     142              PredecessorList[OtherAtom->getNr()] = Walker; // Walker is the predecessor
     143              ShortestPathList[OtherAtom->getNr()] = ShortestPathList[Walker->getNr()] + 1;
     144              LOG(2, "INFO: Coloring OtherAtom " << OtherAtom->getName() << " lightgray, its predecessor is " << Walker->getName() << " and its Shortest Path is " << ShortestPathList[OtherAtom->getNr()] << " egde(s) long.");
     145              //if (ShortestPathList[OtherAtom->getNr()] < MinimumRingSize[Walker->GetTrueFather()->getNr()]) { // Check for maximum distance
     146              LOG(3, "ACCEPT: Putting OtherAtom " << OtherAtom->getName() << " into queue.");
     147              BFSStack.push_front(OtherAtom);
     148              //}
     149            } else {
     150              LOG(3, "REJECT: Not Adding, has already been visited.");
     151            }
     152            if (OtherAtom == Root)
     153              break;
    135154          } else {
    136             LOG(3, "REJECT: Not Adding, has already been visited.");
     155            LOG(2, "INFO: Skipping hydrogen atom " << *OtherAtom << ".");
     156            ColorList[OtherAtom->getNr()] = GraphEdge::black;
    137157          }
    138           if (OtherAtom == Root)
    139             break;
    140158        } else {
    141           LOG(2, "INFO: Skipping hydrogen atom " << *OtherAtom << ".");
    142           ColorList[OtherAtom->getNr()] = GraphEdge::black;
     159          LOG(2, "REJECT: Bond " << *(*Runner) << " not Visiting, is the back edge.");
    143160        }
    144       } else {
    145         LOG(2, "REJECT: Bond " << *(*Runner) << " not Visiting, is the back edge.");
    146       }
    147     }
    148     ColorList[Walker->getNr()] = GraphEdge::black;
    149     LOG(1, "INFO: Coloring Walker " << Walker->getName() << " " << GraphEdge::getColorName(ColorList[Walker->getNr()]) << ".");
    150     if (OtherAtom == Root) { // if we have found the root, check whether this cycle wasn't already found beforehand
    151       // step through predecessor list
    152       LOG(4, "DEBUG: Checking whether all predecessors are already marked cyclic ...");
    153       while (OtherAtom != BackEdge->rightatom) {  // Note that leftatom is Root itself
    154         if (!OtherAtom->GetTrueFather()->IsCyclic) { // if one bond in the loop is not marked as cyclic, we haven't found this cycle yet
    155           LOG(4, "\tDEBUG: OtherAtom " << *OtherAtom << " is not cyclic, breaking.");
    156           break;
    157         } else
    158           OtherAtom = PredecessorList[OtherAtom->getNr()];
    159       }
    160       LOG(4, "DEBUG: Checking done.");
    161       // if each atom in found cycle is cyclic, loop's been found before already
    162       if (OtherAtom == BackEdge->rightatom) { // loop got round completely
    163         LOG(3, "INFO: All bonds are marked cyclic already, checking allcycles whether cycle is already present.");
    164         const cycle_t currentcycle = extractCurrentCycle(BackEdge);
    165         const cycles_t::const_iterator iter =
    166             std::find(allcycles.begin(), allcycles.end(), currentcycle);
    167         if (iter == allcycles.end()) { // not found
    168           OtherAtom = Root;
    169           LOG(2, "INFO: Cycle is not present.");
    170           LOG(2, "INFO: We have reached Root " << *OtherAtom << " and may extract the cycle.");
    171         } else {
    172           LOG(2, "INFO: Cycle is already present.");
    173           do {
    174             ASSERT(!TouchedStack.empty(), "CyclicStructureAnalysis_CyclicBFSFromRootToRoot() - TouchedStack is empty!");
    175             OtherAtom = TouchedStack.front();
    176             TouchedStack.pop_front();
    177             if (PredecessorList[OtherAtom->getNr()] == Walker) {
    178               LOG(4, "INFO: Removing " << *OtherAtom << " from lists and stacks.");
    179               PredecessorList[OtherAtom->getNr()] = NULL;
    180               ShortestPathList[OtherAtom->getNr()] = -1;
    181               ColorList[OtherAtom->getNr()] = GraphEdge::white;
    182               // rats ... deque has no find()
    183               std::deque<atom *>::iterator iter = find(
    184                   BFSStack.begin(),
    185                   BFSStack.end(),
    186                   OtherAtom);
    187               ASSERT(iter != BFSStack.end(),
    188                   "CyclicStructureAnalysis_CyclicBFSFromRootToRoot() - can't find "+toString(*OtherAtom)+" on stack!");
    189               BFSStack.erase(iter);
    190             }
    191           } while ((!TouchedStack.empty()) && (PredecessorList[OtherAtom->getNr()] == NULL));
    192           TouchedStack.push_front(OtherAtom); // last was wrongly popped
    193           OtherAtom = BackEdge->rightatom; // set to not Root
     161      }
     162      ColorList[Walker->getNr()] = GraphEdge::black;
     163      LOG(1, "INFO: Coloring Walker " << Walker->getName() << " " << GraphEdge::getColorName(ColorList[Walker->getNr()]) << ".");
     164    } else {
     165      LOG(1, "INFO: Skipping bonds for " << Walker->getName() << " as it resides on the horizon.");
     166    }
     167
     168    // have we closed the cycle, i.e. stumbled upon Root by another mean than
     169    // the back edge?
     170    if (OtherAtom == Root) {
     171      // check whether this cycle wasn't already found beforehand by stepping
     172      // through predecessor list
     173      int RingSize = RetrieveCycleMembers(OtherAtom, BackEdge, MinRingSize);
     174      MaximumHorizon = std::min( MaximumHorizon, (size_t)RingSize );
     175      LOG(2, "INFO: Maximum horizon is set to " << MaximumHorizon);
     176
     177      // remove last step and prepare for a possible yet another path to Root
     178      do {
     179        ASSERT(!TouchedStack.empty(), "CyclicStructureAnalysis_CyclicBFSFromRootToRoot() - TouchedStack is empty!");
     180        OtherAtom = TouchedStack.front();
     181        TouchedStack.pop_front();
     182        if (PredecessorList[OtherAtom->getNr()] == Walker) {
     183          LOG(4, "INFO: Removing " << *OtherAtom << " from lists and stacks.");
     184          PredecessorList[OtherAtom->getNr()] = NULL;
     185          ShortestPathList[OtherAtom->getNr()] = -1;
     186          ColorList[OtherAtom->getNr()] = GraphEdge::white;
     187          // rats ... deque has no find()
     188          std::deque<atom *>::iterator iter = find(
     189              BFSStack.begin(),
     190              BFSStack.end(),
     191              OtherAtom);
     192          ASSERT(iter != BFSStack.end(),
     193              "CyclicStructureAnalysis_CyclicBFSFromRootToRoot() - can't find "+toString(*OtherAtom)+" on stack!");
     194          BFSStack.erase(iter);
    194195        }
    195       } else {
    196         OtherAtom = Root;
    197         LOG(2, "INFO: We have reached Root " << *OtherAtom << " and may extract the cycle.");
    198       }
     196      } while ((!TouchedStack.empty()) && (PredecessorList[OtherAtom->getNr()] == NULL));
     197      TouchedStack.push_front(OtherAtom); // last was wrongly popped
     198      OtherAtom = BackEdge->rightatom; // set to not Root
    199199    }
    200200  } while ((!BFSStack.empty()) && (OtherAtom != Root) && (OtherAtom != NULL)); // || (ShortestPathList[OtherAtom->getNr()] < MinimumRingSize[Walker->GetTrueFather()->getNr()])));
     
    233233 * \param &BFS accounting structure
    234234 * \param &MinRingSize global minimum distance from one node without encountering oneself, set on return
    235  * \param &NumCyles number of cycles in graph
    236  */
    237 void CyclicStructureAnalysis::RetrieveCycleMembers(
     235 * \return size of found cycle, -1 - nothing found, something went wrong
     236 */
     237int CyclicStructureAnalysis::RetrieveCycleMembers(
    238238    atom *&OtherAtom,
    239239    bond::ptr &BackEdge,
    240     int &MinRingSize,
    241     int &NumCycles)
    242 {
    243   atom *Walker = NULL;
     240    int &MinRingSize)
     241{
    244242  int RingSize = -1;
     243  bool newcycle = false;
    245244
    246245  if (OtherAtom == Root) {
    247246    // now climb back the predecessor list and thus find the cycle members
    248     NumCycles++;
    249247    Root->GetTrueFather()->IsCyclic = true;
    250248
    251     // exctract cycle
    252249    {
    253       allcycles.push_back(extractCurrentCycle(BackEdge));
    254       CyclicStructureAnalysis::cycle_t &lastcycle = allcycles.back();
    255       RingSize = lastcycle.size();
    256       LOG(0, "INFO: " << "Found ring contains: " << lastcycle << "  with a length of " << RingSize);
    257     }
    258 
    259     // walk through all and set MinimumRingSize
    260     Walker = Root;
    261     if ((MinimumRingSize.count(Walker->GetTrueFather()->getNr()) == 0)
    262         || (RingSize < MinimumRingSize[Walker->GetTrueFather()->getNr()])) {
    263       MinimumRingSize[Walker->GetTrueFather()->getNr()] = RingSize;
    264     } else {
    265       LOG(3, "INFO: Not setting MinimumRingSize of "<< *(Walker->GetTrueFather())
    266           << " to " << RingSize << " which is already set to "
    267           << MinimumRingSize[Walker->GetTrueFather()->getNr()] << ".");
    268     }
    269     while (Walker != BackEdge->rightatom) { // note that Root is leftatom
    270       Walker = PredecessorList[Walker->getNr()];
     250      // check whether cycle is present already
     251      atom *Walker = Root;
     252      LOG(4, "DEBUG: Checking whether all predecessors are already marked cyclic ...");
     253      while (Walker != BackEdge->rightatom) {  // Note that leftatom is Root itself
     254        if (!Walker->GetTrueFather()->IsCyclic) { // if one bond in the loop is not marked as cyclic, we haven't found this cycle yet
     255          LOG(4, "\tDEBUG: Walker " << *Walker << " is not cyclic, breaking.");
     256          break;
     257        } else
     258          Walker = PredecessorList[Walker->getNr()];
     259      }
     260      LOG(4, "DEBUG: Checking done.");
     261
     262      // if each atom in found cycle is cyclic, loop's been found before already
     263
     264      // exctract cycle
     265      {
     266        const cycle_t currentcycle = extractCurrentCycle(BackEdge);
     267        if (Walker != BackEdge->rightatom) { // loop got round completely
     268          allcycles.push_back(currentcycle);
     269          newcycle = true;
     270        } else {
     271          LOG(3, "INFO: All bonds are marked cyclic already, checking allcycles whether cycle is already present.");
     272          const cycles_t::const_iterator iter =
     273              std::find(allcycles.begin(), allcycles.end(), currentcycle);
     274          if (iter == allcycles.end()) { // not found
     275            allcycles.push_back(currentcycle);
     276            newcycle = true;
     277          }
     278        }
     279        RingSize = currentcycle.size();
     280        if (newcycle) {
     281          LOG(0, "INFO: " << "Found ring contains: " << currentcycle << "  with a length of " << RingSize);
     282        } else {
     283          LOG(1, "INFO: cycle " << currentcycle << " is already present.");
     284        }
     285      }
     286    }
     287
     288    if (newcycle) {
     289      // walk through all and set MinimumRingSize
     290      atom *Walker = Root;
    271291      if ((MinimumRingSize.count(Walker->GetTrueFather()->getNr()) == 0)
    272           || (RingSize < MinimumRingSize[Walker->GetTrueFather()->getNr()]))
     292          || (RingSize < MinimumRingSize[Walker->GetTrueFather()->getNr()])) {
    273293        MinimumRingSize[Walker->GetTrueFather()->getNr()] = RingSize;
    274     }
    275     if ((RingSize < MinRingSize) || (MinRingSize == -1))
    276       MinRingSize = RingSize;
     294      } else {
     295        LOG(3, "INFO: Not setting MinimumRingSize of "<< *(Walker->GetTrueFather())
     296            << " to " << RingSize << " which is already set to "
     297            << MinimumRingSize[Walker->GetTrueFather()->getNr()] << ".");
     298      }
     299      while (Walker != BackEdge->rightatom) { // note that Root is leftatom
     300        Walker = PredecessorList[Walker->getNr()];
     301        if ((MinimumRingSize.count(Walker->GetTrueFather()->getNr()) == 0)
     302            || (RingSize < MinimumRingSize[Walker->GetTrueFather()->getNr()]))
     303          MinimumRingSize[Walker->GetTrueFather()->getNr()] = RingSize;
     304      }
     305      if ((RingSize < MinRingSize) || (MinRingSize == -1))
     306        MinRingSize = RingSize;
     307    }
    277308  } else {
    278309    LOG(1, "INFO: No ring containing " << *Root << " with length equal to or smaller than " << MinimumRingSize[Root->GetTrueFather()->getNr()] << " found.");
    279310  }
     311  return RingSize;
    280312}
    281313
     
    358390 * \param *&MinimumRingSize array with minimum distance without encountering oneself for each atom
    359391 * \param MinRingSize global minium distance
    360  * \param NumCyles number of cycles in graph
    361  */
    362 void CyclicStructureAnalysis::AssignRingSizetoNonCycleMembers(const int MinRingSize, const int NumCycles)
     392 */
     393void CyclicStructureAnalysis::AssignRingSizetoNonCycleMembers(const int MinRingSize)
    363394{
    364395  atom *Walker = NULL;
     
    380411      LOG(1, "INFO: Minimum ring size of " << *Walker << " is " << MinimumRingSize[Walker->GetTrueFather()->getNr()] << ".");
    381412    }
    382     LOG(1, "INFO: Minimum ring size is " << MinRingSize << ", over " << NumCycles << " cycle(s) total.");
     413    LOG(1, "INFO: Minimum ring size is " << MinRingSize << ", over " << allcycles.size() << " cycle(s) total.");
    383414  } else
    384415    LOG(1, "INFO: No rings were detected in the molecular structure.");
     
    399430  atom *OtherAtom = NULL;
    400431  bond::ptr BackEdge;
    401   int NumCycles = 0;
    402432  int MinRingSize = -1;
    403433
     
    415445
    416446  LOG(1, "STATUS: Analysing cycles ... ");
    417   NumCycles = 0;
    418447  while (!BackEdgeStack->empty()) {
    419448    BackEdge = BackEdgeStack->front();
     
    428457    LOG(1, "---------------------------------------------------------------------------------------------------------");
    429458    OtherAtom = NULL;
    430     // go to next cycle via BFS
    431     CyclicBFSFromRootToRoot(OtherAtom, BackEdge);
    432     // get all member nodes of this cycle
    433     RetrieveCycleMembers(OtherAtom, BackEdge, MinRingSize, NumCycles);
     459    // find all cycles for current BackEdge
     460    findAllCyclesforBackEdge(OtherAtom, BackEdge, MinRingSize);
    434461
    435462    CleanAllTouched();
    436463  }
    437   AssignRingSizetoNonCycleMembers(MinRingSize, NumCycles);
     464  AssignRingSizetoNonCycleMembers(MinRingSize);
    438465}
    439466
  • src/Graph/CyclicStructureAnalysis.hpp

    r4d6d6a r83cc3e  
    5858  void InitializeToRoot(atom *&Walker);
    5959  // performing tasks
    60   void CyclicBFSFromRootToRoot(atom *&OtherAtom, bond::ptr &BackEdge);
    61   void RetrieveCycleMembers(atom *&OtherAtom, bond::ptr &BackEdge, int &MinRingSize, int &NumCycles);
     60  void findAllCyclesforBackEdge(atom *&OtherAtom, bond::ptr &BackEdge, int &MinRingSize);
     61  int RetrieveCycleMembers(atom *&OtherAtom, bond::ptr &BackEdge, int &MinRingSize);
    6262  cycle_t extractCurrentCycle(bond::ptr &BackEdge);
    6363  void BFSToNextCycle(atom *Walker);
    64   void AssignRingSizetoNonCycleMembers(const int MinRingSize, const int NumCycles);
     64  void AssignRingSizetoNonCycleMembers(const int MinRingSize);
    6565  // output
    6666  void OutputAlreadyVisited(int *list);
Note: See TracChangeset for help on using the changeset viewer.