/// <summary> /// Recursively performs a depth first search in a molecular graphs contained in /// the AtomContainer molecule, starting at the root atom and returning when it /// hits the target atom. /// <para> /// CAUTION: This recursive method sets the VISITED flag of each atom /// does not reset it after finishing the search. If you want to do the /// operation on the same collection of atoms more than once, you have /// to set all the VISITED flags to false before each operation /// by looping of the atoms and doing a /// "atom.Flag = (CDKConstants.VISITED, false);" /// </para> /// <para> /// Note that the path generated by the search will not contain the root atom, /// but will contain the target atom /// </para> /// </summary> /// <param name="molecule">The AtomContainer to be searched</param> /// <param name="root">The root atom to start the search at</param> /// <param name="target">The target</param> /// <param name="path">An AtomContainer to be filled with the path</param> /// <returns><see langword="true"/> if the target atom was found during this function call</returns> public static bool DepthFirstTargetSearch(IAtomContainer molecule, IAtom root, IAtom target, IAtomContainer path) { var bonds = molecule.GetConnectedBonds(root); IAtom nextAtom; root.IsVisited = true; bool first = path.IsEmpty(); if (first) { path.Atoms.Add(root); } foreach (var bond in bonds) { nextAtom = bond.GetOther(root); if (!nextAtom.IsVisited) { path.Atoms.Add(nextAtom); path.Bonds.Add(bond); if (nextAtom.Equals(target)) { if (first) { path.Atoms.Remove(root); } return(true); } else { if (!DepthFirstTargetSearch(molecule, nextAtom, target, path)) { // we did not find the target path.Atoms.Remove(nextAtom); path.Bonds.Remove(bond); } else { if (first) { path.Atoms.Remove(root); } return(true); } } } } if (first) { path.Atoms.Remove(root); } return(false); }
private static int[] DetermineComponents(IAtomContainer target, bool auto) { int[] components = null; // no atoms -> no components if (target.IsEmpty()) { components = new int[0]; } // defined by reaction grouping if (components == null && target.Atoms[0].GetProperty <int?>(CDKPropertyName.ReactionGroup) != null) { int max = 0; components = new int[target.Atoms.Count + 1]; for (int i = 0; i < target.Atoms.Count; i++) { var grp = target.Atoms[i].GetProperty <int?>(CDKPropertyName.ReactionGroup); if (grp == null) { grp = 0; } components[i] = grp.Value; if (grp > max) { max = grp.Value; } } components[target.Atoms.Count] = max; } // calculate from connection table if (components == null && auto) { int max = 0; components = new int[target.Atoms.Count + 1]; int i = 0; foreach (int grp in new ConnectedComponents(GraphUtil.ToAdjList(target)).GetComponents()) { components[i++] = grp; if (grp > max) { max = grp; } } components[target.Atoms.Count] = max; } return(components); }