Esempio n. 1
0
        public void MergeSort()
        {
            int n = 100;

            // random (unique) values in random order
            Random             rnd    = new Random();
            ICollection <long> values = new HashSet <long>();

            while (values.Count < n)
            {
                values.Add((long)(((ulong)((uint)rnd.Next()) << 32) + ((uint)rnd.Next())));
            }

            long[] prev = values.ToArray();

            // ident array
            int[] vs = new int[n];
            for (int i = 0; i < n; i++)
            {
                vs[i] = i;
            }

            InvariantRanker invRanker = new InvariantRanker(n);

            invRanker.SortBy(vs, 0, n, prev, prev);

            // check they are sorted
            for (int i = 1; i < n; i++)
            {
                Assert.IsTrue(prev[vs[i]] > prev[vs[i - 1]]);
            }
        }
Esempio n. 2
0
 public void InsertionSort_range()
 {
     long[] prev = new long[] { 12, 11, 10, 9, 8, 7 };
     long[] curr = new long[] { 12, 11, 10, 9, 8, 7 };
     int[]  vs   = new int[] { 0, 1, 2, 3, 4, 5 };
     InvariantRanker.InsertionSortBy(vs, 2, 3, curr, prev);
     Assert.IsTrue(Compares.AreEqual(new int[] { 0, 1, 4, 3, 2, 5 }, vs));
 }
Esempio n. 3
0
 public void Less()
 {
     long[] prev = new long[] { 1, 1, 2, 2 };
     long[] curr = new long[] { 1, 1, 2, 2 };
     Assert.IsFalse(InvariantRanker.Less(0, 1, curr, prev));
     Assert.IsFalse(InvariantRanker.Less(2, 3, curr, prev));
     Assert.IsTrue(InvariantRanker.Less(0, 2, curr, prev));
     Assert.IsTrue(InvariantRanker.Less(0, 3, curr, prev));
     Assert.IsTrue(InvariantRanker.Less(1, 2, curr, prev));
     Assert.IsTrue(InvariantRanker.Less(1, 3, curr, prev));
 }
Esempio n. 4
0
 public void LessUsingPrev()
 {
     long[] prev = new long[] { 1, 1, 2, 2 };
     long[] curr = new long[] { 1, 2, 1, 2 };
     // 0,1 and 2,3 are only less is we inspect the 'curr' invariants
     Assert.IsTrue(InvariantRanker.Less(0, 1, curr, prev));
     Assert.IsTrue(InvariantRanker.Less(2, 3, curr, prev));
     // these values are only less inspecting the first invariants
     Assert.IsTrue(InvariantRanker.Less(0, 2, curr, prev));
     Assert.IsTrue(InvariantRanker.Less(0, 3, curr, prev));
     Assert.IsTrue(InvariantRanker.Less(1, 2, curr, prev));
     Assert.IsTrue(InvariantRanker.Less(1, 3, curr, prev));
 }
Esempio n. 5
0
        public void Rank_all_unique()
        {
            InvariantRanker ranker = new InvariantRanker(7);

            long[] prev = new long[] { 1, 1, 1, 1, 1, 1, 1 };
            long[] curr = new long[] { 7, 3, 1, 0, 91, 32, 67 };

            // no we leave extra space
            int[] vs = new int[] { 0, 1, 2, 3, 4, 5, 6 };
            int[] ws = new int[7];

            int ranks = ranker.Rank(vs, ws, 7, curr, prev);

            Assert.AreEqual(7, ranks);

            // assigned ranks (note: unique assigned first)
            Assert.IsTrue(Compares.AreEqual(new long[] { 4, 3, 2, 1, 7, 5, 6 }, prev));

            // no non-unique vertices
            Assert.IsTrue(Compares.AreEqual(new int[] { -1, 0, 0, 0, 0, 0, 0 }, ws));
        }
Esempio n. 6
0
        public void Rank_all_equiv()
        {
            InvariantRanker ranker = new InvariantRanker(6);

            long[] prev = new long[] { 1, 1, 1, 1, 1, 1 };
            long[] curr = new long[] { 42, 42, 42, 42, 42, 42 };

            // no we leave extra space
            int[] vs = new int[] { 0, 1, 2, 3, 4, 5 };
            int[] ws = new int[6];

            int ranks = ranker.Rank(vs, ws, 6, curr, prev);

            Assert.AreEqual(1, ranks);

            // assigned ranks (note: unique assigned first)
            Assert.IsTrue(Compares.AreEqual(new long[] { 1, 1, 1, 1, 1, 1 }, prev));

            // remaining non-unique vertices
            Assert.IsTrue(Compares.AreEqual(new int[] { 0, 1, 2, 3, 4, 5 }, ws));
        }
Esempio n. 7
0
        /// <summary>
        /// Internal - refine invariants to a canonical labelling and symmetry classes.
        /// </summary>
        /// <param name="invariants">the invariants to refine (canonical labelling gets written here)</param>
        /// <param name="hydrogens">binary vector of terminal hydrogens</param>
        /// <returns>the symmetry classes</returns>
        private long[] Refine(long[] invariants, bool[] hydrogens)
        {
            int ord = g.Length;

            InvariantRanker ranker = new InvariantRanker(ord);

            // current/next vertices, these only hold the vertices which are
            // equivalent
            int[] currVs = new int[ord];
            int[] nextVs = new int[ord];

            // fill with identity (also set number of non-unique)
            int nnu = ord;

            for (int i = 0; i < ord; i++)
            {
                currVs[i] = i;
            }

            long[] prev = invariants;
            long[] curr = Arrays.CopyOf(invariants, ord);

            // initially all labels are 1, the input invariants are then used to
            // refine this coarse partition
            Arrays.Fill(prev, 1L);

            // number of ranks
            int n = 0, m = 0;

            // storage of symmetry classes
            long[] symmetry = null;

            while (n < ord)
            {
                // refine the initial invariants using product of primes from
                // adjacent ranks
                while ((n = ranker.Rank(currVs, nextVs, nnu, curr, prev)) > m && n < ord)
                {
                    nnu = 0;
                    for (int i = 0; i < ord && nextVs[i] >= 0; i++)
                    {
                        int v = nextVs[i];
                        currVs[nnu++] = v;
                        curr[v]       = hydrogens[v] ? prev[v] : PrimeProduct(g[v], prev, hydrogens);
                    }
                    m = n;
                }

                if (symmetry == null)
                {
                    // After symmetry classes have been found without hydrogens we add
                    // back in the hydrogens and assign ranks. We don't refine the
                    // partition until the next time round the while loop to avoid
                    // artificially splitting due to hydrogen representation, for example
                    // the two hydrogens are equivalent in this SMILES for ethane '[H]CC'
                    for (int i = 0; i < g.Length; i++)
                    {
                        if (hydrogens[i])
                        {
                            curr[i]      = prev[g[i][0]];
                            hydrogens[i] = false;
                        }
                    }
                    n        = ranker.Rank(currVs, nextVs, nnu, curr, prev);
                    symmetry = Arrays.CopyOf(prev, ord);

                    // Update the buffer of non-unique vertices as hydrogens next
                    // to discrete heavy atoms are also discrete (and removed from
                    // 'nextVs' during ranking.
                    nnu = 0;
                    for (int i = 0; i < ord && nextVs[i] >= 0; i++)
                    {
                        currVs[nnu++] = nextVs[i];
                    }
                }

                // partition is discrete or only symmetry classes are needed
                if (symOnly || n == ord)
                {
                    return(symmetry);
                }

                // artificially split the lowest cell, we perturb the value
                // of all vertices with equivalent rank to the lowest non-unique
                // vertex
                int lo = nextVs[0];
                for (int i = 1; i < ord && nextVs[i] >= 0 && prev[nextVs[i]] == prev[lo]; i++)
                {
                    prev[nextVs[i]]++;
                }

                // could also swap but this is cleaner
                Array.Copy(nextVs, 0, currVs, 0, nnu);
            }

            return(symmetry);
        }