Exemple #1
0
        /// <summary>
        /// adds a dummy atom to the current queue manager which duplicates the atom in question
        /// </summary>
        /// <param name="childAtom">atom to duplicate</param>
        /// <param name="queueManager">what it says</param>
        /// <param name="parentAtomdata">data about the current atom on the queue</param>
        private static void AddDummyAtom(Atom childAtom, CipBandQueue queueManager, CipData parentAtomdata)
        {
            Atom dummy = new Atom
            {
                Element       = childAtom.Element,
                IsotopeNumber = childAtom.IsotopeNumber
            };

            //and shove it on the queue

            queueManager.Enqueue(new CipData
            {
                CurrentAtom = dummy,
                RootAtom    = parentAtomdata.RootAtom,
                Source      = parentAtomdata.CurrentAtom
            });
        }
Exemple #2
0
        public bool DeterminePriorities(out Dictionary <Atom, int> priorities, params Atom[] startAtoms)
        {
            //the band manager swaps queues from band to band
            CipBandQueue queueManager = new CipBandQueue();
            //this keeps a list of priorities as assigned to the root atoms.
            Dictionary <Atom, int> rootPriority = new Dictionary <Atom, int>();
            //keep track of atoms we've already visited so far:  this helps us to locate cycles
            HashSet <Atom> visitedAtoms = new HashSet <Atom>();

            //we scan outward from the root atom in concentric bands.
            //at the end of each band we check for distinctness

            //add the children of the start atoms to the first band,
            foreach (Atom startAtom in startAtoms)
            {
                foreach (Atom atom in startAtom.NeighboursExcept(startAtoms))
                {
                    CipData data = new CipData
                    {
                        RootAtom    = atom,
                        CurrentAtom = atom,
                        Source      = startAtom
                    };

                    //create a singleton list for each atom
                    List <CipData> newAtomList = new List <CipData> {
                        data
                    };
                    //set the p of each atom to zero
                    rootPriority[atom] = 0;

                    queueManager.Enqueue(data);
                }
            }

            //check there are four immediate first-generation children - if not, throw an exception

            if (queueManager.Count != 4)
            {
                throw new ArgumentException("Number of neigbouring atoms does not equal 4.");
            }

            //while we have no distinct set of CIP priorities - and there are plenty more atoms
            while (queueManager.Any)
            {
                Dictionary <Atom, List <CipData> > currentBandData = new Dictionary <Atom, List <CipData> >();
                //retrieve the current atom band
                while (queueManager.Any)
                {
                    var parentAtomdata = queueManager.Dequeue();
                    //add the child atoms to the next atom band
                    foreach (Atom childAtom in parentAtomdata.CurrentAtom.NeighboursExcept(parentAtomdata.Source))
                    {
                        //if we've visited the atom, add a ghost atom as it's a cycle
                        if (!visitedAtoms.Contains(childAtom))
                        {
                            //mark each atom as visited
                            visitedAtoms.Add(childAtom);

                            queueManager.Enqueue(new CipData
                            {
                                CurrentAtom = childAtom,
                                RootAtom    = parentAtomdata.RootAtom,
                                Source      = parentAtomdata.CurrentAtom
                            });
                            //if we've a multiple bond, add n-1 ghost atoms
                            for (double i = 2.0;
                                 i <= (parentAtomdata.Source.BondBetween(childAtom).OrderValue ?? 1.0);
                                 i++)
                            {
                                AddDummyAtom(childAtom, queueManager, parentAtomdata);
                            }
                        }
                        else
                        {
                            //create a dummy atom identical to the original atom
                            AddDummyAtom(childAtom, queueManager, parentAtomdata);
                        }
                        //and add it to thelookup
                        if (!currentBandData.ContainsKey(parentAtomdata.RootAtom))
                        {
                            currentBandData[parentAtomdata.RootAtom] = new List <CipData>();
                        }
                        currentBandData[parentAtomdata.RootAtom].Add(parentAtomdata);
                    }
                    //we've now run out of atoms from this band
                    //so rank them
                    Dictionary <Atom, int> nextPriorities = RankPriorities(currentBandData);
                    //now add them to the cumulative priorities

                    foreach (var root in nextPriorities.Keys)
                    {
                        rootPriority[root] += nextPriorities[root];
                    }

                    //if the cumulative priorities are all distinct

                    if (rootPriority.Values.Distinct().Count() == rootPriority.Values.Count)
                    {
                        //return the list of priorities by atoms
                        priorities = rootPriority;
                        return(true);
                    }
                    else
                    //multiply all the cumulative priorities by four
                    {
                        foreach (Atom root in rootPriority.Keys)
                        {
                            rootPriority[root] *= 4;
                        }
                        //and swap the queues
                        queueManager.NextBand();
                    }
                }
                //end while
            }
            //if we've got here we've run out of atoms still don't have a set of distinct priorities.
            priorities = null;
            return(false);
        }