Пример #1
0
        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;
        }
Пример #2
0
        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;
        }
Пример #3
0
        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;
        }
Пример #4
0
        /// <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");
                }
            }
        }