private IEnumerable <int> RecursiveDFT(int atom) { if ((travIndex < NumAtoms) && (!visited[atom])) { travIndex++; visited[atom] = true; List <int> adjSet = new List <int>(); for (int nextAtom = 0; nextAtom < dim; nextAtom++) { if ((int)contab[atom][nextAtom] != 0) { adjSet.Add(nextAtom); } } while (adjSet.Count > 0) { int adjIndex = RandomNumbersTool.RandomInt(0, adjSet.Count - 1); foreach (int i in RecursiveDFT(adjSet[adjIndex])) { yield return(i); } adjSet.RemoveAt(adjIndex); } } yield break; }
public IEnumerable <int> PickBFGraph() { //breadth first search from a randomly selected atom travIndex = 0; visited = new bool[dim]; for (int atom = 0; atom < dim; atom++) { visited[atom] = false; } int seedAtom = RandomNumbersTool.RandomInt(0, dim - 1); var atomQueue = new List <int> { seedAtom }; visited[seedAtom] = true; int count = 0; while (atomQueue.Count != 0 && count < NumAtoms) { int foreAtom = atomQueue[0]; yield return(foreAtom); count++; atomQueue.RemoveAt(0); travIndex++; var adjSet = new List <int>(); for (int nextAtom = 0; nextAtom < dim; nextAtom++) { if (((int)contab[foreAtom][nextAtom] != 0) && (!visited[nextAtom])) { adjSet.Add(nextAtom); } } while (adjSet.Count > 0) { int adjIndex = RandomNumbersTool.RandomInt(0, adjSet.Count - 1); atomQueue.Add((int)adjSet[adjIndex]); visited[adjSet[adjIndex]] = true; adjSet.RemoveAt(adjIndex); } } yield break; }
public IEnumerable <int> PickDFGraph() { //depth first search from a randomly selected atom travIndex = 0; visited = new bool[dim]; for (int atom = 0; atom < dim; atom++) { visited[atom] = false; } int seedAtom = RandomNumbersTool.RandomInt(0, dim - 1); foreach (int atom in RecursiveDFT(seedAtom)) { yield return(atom); } yield break; }
/// <summary> /// Performs the n point crossover of two <see cref="IAtomContainer"/>. /// </summary> /// <remarks> /// Precondition: The atoms in the molecules are ordered by properties to /// preserve (e. g. atom symbol). Due to its randomized nature, this method /// fails in around 3% of all cases. A <see cref="CDKException"/> with message "Could not /// mate these properly" will then be thrown. /// </remarks> /// <returns>The children.</returns> /// <exception cref="CDKException">if it was not possible to form off springs.</exception> public IReadOnlyList <IAtomContainer> DoCrossover(IAtomContainer dad, IAtomContainer mom) { int tries = 0; while (true) { int dim = dad.Atoms.Count; var redChild = new IAtomContainer[2]; var blueChild = new IAtomContainer[2]; var redAtoms = new List <int>(); var blueAtoms = new List <int>(); // randomly divide atoms into two parts: redAtoms and blueAtoms. if (splitMode == SplitMode.Random) { // better way to randomly divide atoms into two parts: redAtoms // and blueAtoms. for (int i = 0; i < dim; i++) { redAtoms.Add(i); } for (int i = 0; i < (dim - numatoms); i++) { int ranInt = RandomNumbersTool.RandomInt(0, redAtoms.Count - 1); redAtoms.RemoveAt(ranInt); blueAtoms.Add(ranInt); } } else { // split graph using depth/breadth first traverse var graph = new ChemGraph(dad) { NumAtoms = numatoms }; if (splitMode == SplitMode.DepthFirst) { redAtoms = graph.PickDFGraph().ToList(); } else { //this is SPLIT_MODE_BREADTH_FIRST redAtoms = graph.PickBFGraph().ToList(); } for (int i = 0; i < dim; i++) { int element = i; if (!(redAtoms.Contains(element))) { blueAtoms.Add(element); } } } /* * dividing over ** */ redChild[0] = dad.Builder.NewAtomContainer(dad); blueChild[0] = dad.Builder.NewAtomContainer(dad); redChild[1] = dad.Builder.NewAtomContainer(mom); blueChild[1] = dad.Builder.NewAtomContainer(mom); var blueAtomsInRedChild0 = new List <IAtom>(); for (int j = 0; j < blueAtoms.Count; j++) { blueAtomsInRedChild0.Add(redChild[0].Atoms[(int)blueAtoms[j]]); } for (int j = 0; j < blueAtomsInRedChild0.Count; j++) { redChild[0].RemoveAtom(blueAtomsInRedChild0[j]); } var blueAtomsInRedChild1 = new List <IAtom>(); for (int j = 0; j < blueAtoms.Count; j++) { blueAtomsInRedChild1.Add(redChild[1].Atoms[(int)blueAtoms[j]]); } for (int j = 0; j < blueAtomsInRedChild1.Count; j++) { redChild[1].RemoveAtom(blueAtomsInRedChild1[j]); } var redAtomsInBlueChild0 = new List <IAtom>(); for (int j = 0; j < redAtoms.Count; j++) { redAtomsInBlueChild0.Add(blueChild[0].Atoms[(int)redAtoms[j]]); } for (int j = 0; j < redAtomsInBlueChild0.Count; j++) { blueChild[0].RemoveAtom(redAtomsInBlueChild0[j]); } var redAtomsInBlueChild1 = new List <IAtom>(); for (int j = 0; j < redAtoms.Count; j++) { redAtomsInBlueChild1.Add(blueChild[1].Atoms[(int)redAtoms[j]]); } for (int j = 0; j < redAtomsInBlueChild1.Count; j++) { blueChild[1].RemoveAtom(redAtomsInBlueChild1[j]); } //if the two fragments of one and only one parent have an uneven number //of attachment points, we need to rearrange them var satCheck = CDK.SaturationChecker; double red1attachpoints = 0; for (int i = 0; i < redChild[0].Atoms.Count; i++) { red1attachpoints += satCheck.GetCurrentMaxBondOrder(redChild[0].Atoms[i], redChild[0]); } double red2attachpoints = 0; for (int i = 0; i < redChild[1].Atoms.Count; i++) { red2attachpoints += satCheck.GetCurrentMaxBondOrder(redChild[1].Atoms[i], redChild[1]); } bool isok = true; if (red1attachpoints % 2 == 1 ^ red2attachpoints % 2 == 1) { isok = false; var firstToBalance = redChild[1]; var secondToBalance = blueChild[0]; if (red1attachpoints % 2 == 1) { firstToBalance = redChild[0]; secondToBalance = blueChild[1]; } //we need an atom which has //- an uneven number of "attachment points" and //- an even number of outgoing bonds foreach (var atom in firstToBalance.Atoms) { if (satCheck.GetCurrentMaxBondOrder(atom, firstToBalance) % 2 == 1 && firstToBalance.GetBondOrderSum(atom) % 2 == 0) { //we remove this from it's current container and add it to the other one firstToBalance.RemoveAtom(atom); secondToBalance.Atoms.Add(atom); isok = true; break; } } } //if we have combinable fragments if (isok) { //combine the fragments crosswise var newstrucs = new IChemObjectSet <IAtomContainer> [2]; newstrucs[0] = dad.Builder.NewAtomContainerSet(); newstrucs[0].AddRange(ConnectivityChecker.PartitionIntoMolecules(redChild[0])); newstrucs[0].AddRange(ConnectivityChecker.PartitionIntoMolecules(blueChild[1])); newstrucs[1] = dad.Builder.NewAtomContainerSet(); newstrucs[1].AddRange(ConnectivityChecker.PartitionIntoMolecules(redChild[1])); newstrucs[1].AddRange(ConnectivityChecker.PartitionIntoMolecules(blueChild[0])); //and merge var children = new List <IAtomContainer>(2); for (int f = 0; f < 2; f++) { var structrue = pfsm.Generate2(newstrucs[f]); if (structrue != null) { //if children are not correct, the outer loop will repeat, //so we ignore this children.Add(structrue); } } if (children.Count == 2 && ConnectivityChecker.IsConnected(children[0]) && ConnectivityChecker.IsConnected(children[1])) { return(children); } } tries++; if (tries > 20) { throw new CDKException("Could not mate these properly"); } } }