예제 #1
0
        public override long[] Generate(IAtomContainer container)
        {
            int[][]    graph      = ToAdjList(container);
            Suppressed suppressed = suppression.Suppress(container);

            return(Generate(seedGenerator.Generate(container), factory.Create(container, graph), graph, suppressed));
        }
예제 #2
0
        public void Bitset()
        {
            BitArray set = new BitArray(48);

            set.Set(2, true);
            set.Set(3, true);
            set.Set(5, true);
            set.Set(7, true);
            set.Set(11, true);
            set.Set(42, true);
            Suppressed suppressed = Suppressed.FromBitSet(set);

            Assert.IsTrue(suppressed.Contains(2));
            Assert.IsTrue(suppressed.Contains(3));
            Assert.IsTrue(suppressed.Contains(5));
            Assert.IsTrue(suppressed.Contains(7));
            Assert.IsTrue(suppressed.Contains(11));
            Assert.IsTrue(suppressed.Contains(42));

            Assert.IsFalse(suppressed.Contains(0));
            Assert.IsFalse(suppressed.Contains(1));
            Assert.IsFalse(suppressed.Contains(4));
            Assert.IsFalse(suppressed.Contains(6));
            Assert.IsFalse(suppressed.Contains(8));
            Assert.IsFalse(suppressed.Contains(9));
            Assert.IsFalse(suppressed.Contains(10));
            Assert.IsFalse(suppressed.Contains(12));
            Assert.IsFalse(suppressed.Contains(13));
            Assert.IsFalse(suppressed.Contains(14));
        }
예제 #3
0
        public void None()
        {
            Suppressed suppressed = Suppressed.None;

            for (int i = 0; i < 1000; i++)
            {
                Assert.IsFalse(suppressed.Contains(i));
            }
        }
예제 #4
0
            public override Suppressed Suppress(IAtomContainer container)
            {
                BitArray hydrogens = new BitArray(container.Atoms.Count);

                for (int i = 0; i < container.Atoms.Count; i++)
                {
                    IAtom atom = container.Atoms[i];
                    hydrogens.Set(i, atom is IPseudoAtom);
                }
                return(Suppressed.FromBitSet(hydrogens));
            }
예제 #5
0
        public void TestGetUnsuppressed()
        {
            var        suppression = AtomSuppression.Unsuppressed;
            var        m_container = new Mock <IAtomContainer>(); var container = m_container.Object;
            Suppressed suppressed = suppression.Suppress(container);

            Assert.IsFalse(suppressed.Contains(0));
            Assert.IsFalse(suppressed.Contains(1));
            Assert.IsFalse(suppressed.Contains(2));
            Assert.IsFalse(suppressed.Contains(3));
            Assert.IsFalse(suppressed.Contains(4));
        }
예제 #6
0
        public void TestRotation()
        {
            var m_seedMock = new Mock <IAtomHashGenerator>(); var seedMock = m_seedMock.Object;
            var m_container = new Mock <IAtomContainer>(); var container = m_container.Object;

            SuppressedAtomHashGenerator generator = new SuppressedAtomHashGenerator(new Mock <IAtomHashGenerator>().Object,
                                                                                    new Xorshift(), AtomSuppression.Unsuppressed, 2);

            int[][] graph = new int[][] { new[] { 1, 2, 3 }, new[] { 0 }, new[] { 0 }, new[] { 0 } };

            // simulate 3 identical neighbors
            long[] invs    = new long[] { 21, 31, 31, 31 };
            long[] unique  = new long[4];
            long[] rotated = new long[4];

            // non-suppressed
            {
                long value = generator.Next(graph, 0, invs, unique, rotated, Suppressed.None);

                Assert.IsTrue(Compares.AreDeepEqual(new long[] { 31, 0, 0, 0 }, unique));
                Assert.IsTrue(Compares.AreDeepEqual(new long[] { generator.Rotate(31, 2), 0, 0, 0 }, rotated));
                Assert.IsTrue(Compares.AreDeepEqual(
                                  value,
                                  generator.Distribute(21) ^ 31 ^ generator.Rotate(31) ^ generator.Rotate(31, 2)));
            }

            // okay now suppress vertices 1
            {
                BitArray suppressed = new BitArray(3);
                suppressed.Set(1, true);

                long value = generator.Next(graph, 0, invs, unique, rotated, Suppressed.FromBitSet(suppressed));

                Assert.IsTrue(Compares.AreDeepEqual(new long[] { 31, 0, 0, 0 }, unique));
                Assert.IsTrue(Compares.AreDeepEqual(new long[] { generator.Rotate(31, 1), 0, 0, 0 }, rotated)); // 31 only encountered twice
                Assert.IsTrue(Compares.AreDeepEqual(value, generator.Distribute(21) ^ 31 ^ generator.Rotate(31)));
            }

            // okay now suppress vertices 1 and 3
            {
                BitArray suppressed = new BitArray(4);
                suppressed.Set(1, true);
                suppressed.Set(3, true);

                long value = generator.Next(graph, 0, invs, unique, rotated, Suppressed.FromBitSet(suppressed));

                Assert.IsTrue(Compares.AreDeepEqual(new long[] { 31, 0, 0, 0 }, unique));
                Assert.IsTrue(Compares.AreDeepEqual(new long[] { 31, 0, 0, 0 }, rotated));  // 31 only encountered once and is not rotated
                Assert.IsTrue(Compares.AreDeepEqual(value, generator.Distribute(21) ^ 31)); // only encountered once
            }
        }
예제 #7
0
        private long[] Generate(IAtomContainer container, long[] seeds, IStereoEncoder encoder, int[][] graph)
        {
            Suppressed suppressed = suppression.Suppress(container);

            // compute original values then find indices equivalent values
            long[] original      = simple.Generate(seeds, encoder, graph, suppressed);
            var    equivalentSet = finder.Find(original, container, graph);
            var    equivalents   = equivalentSet.ToArray();

            // size of the matrix we need to make
            int n = original.Length;
            int m = equivalents.Length;

            // skip when there are no equivalent atoms
            if (m < 2)
            {
                return(original);
            }

            // matrix of perturbed values and identity values
            long[][] perturbed = Arrays.CreateJagged <long>(n, m + 1);

            // set the original values in the first column
            for (int i = 0; i < n; i++)
            {
                perturbed[i][0] = original[i];
            }

            // systematically perturb equivalent vertex
            for (int i = 0; i < m; i++)
            {
                int equivalentIndex = equivalents[i];

                // perturb the value and reset stereo configuration
                original[equivalentIndex] = Rotate(original[equivalentIndex]);
                encoder.Reset();

                // compute new hash codes and copy the values a column in the matrix
                long[] tmp = simple.Generate(Copy(original), encoder, graph, suppressed);
                for (int j = 0; j < n; j++)
                {
                    perturbed[j][i + 1] = tmp[j];
                }

                // reset value
                original[equivalentIndex] = perturbed[equivalentIndex][0];
            }

            return(Combine(perturbed));
        }
예제 #8
0
        public long[] Generate(IAtomContainer container)
        {
            Suppressed suppressed = suppression.Suppress(container);

            int n    = container.Atoms.Count;
            int m    = n - suppressed.Count; // number of non-suppressed vertices
            int seed = m > 1 ? 9803 % m : 1;

            long[] hashes = new long[n];

            for (int i = 0; i < n; i++)
            {
                hashes[i] = Distribute(seed * encoder.Encode(container.Atoms[i], container));
            }
            return(hashes);
        }
예제 #9
0
        public void TestGenerate_Simple()
        {
            var m_seedMock = new Mock <IAtomHashGenerator>(); var seedMock = m_seedMock.Object;
            var m_container = new Mock <IAtomContainer>(); var container = m_container.Object;

            SuppressedAtomHashGenerator generator = new SuppressedAtomHashGenerator(new Mock <IAtomHashGenerator>().Object,
                                                                                    new Xorshift(), AtomSuppression.Unsuppressed, 2);

            // no suppression
            {
                // first iteration, values are distributed and then neighbours xor'd
                // in. when two neighbours have the same value the second should be
                // rotated
                long[] first = new long[] { generator.Distribute(1) ^ 2L,
                                            generator.Distribute(2L) ^ 1L ^ generator.Rotate(1L), generator.Distribute(1) ^ 2L };

                long[] second = new long[] { generator.Distribute(first[0]) ^ first[1],
                                             generator.Distribute(first[1]) ^ first[0] ^ generator.Rotate(first[2]),
                                             generator.Distribute(first[2]) ^ first[1] };

                Assert.IsTrue(Compares.AreDeepEqual(
                                  second,
                                  generator.Generate(new long[] { 1L, 2L, 1L }, StereoEncoder.Empty, new int[][] { new[] { 1 }, new[] { 0, 2 }, new[] { 1 } },
                                                     Suppressed.None)));
            }
            // vertex '2' supressed
            BitArray suppressed = new BitArray(3);

            suppressed.Set(2, true);
            {
                long[] first = new long[] { generator.Distribute(1) ^ 2L, generator.Distribute(2L) ^ 1L, // generator.Rotate(1L) not included is '[2]' is suppressed
                                            0L, };

                long[] second = new long[] { generator.Distribute(first[0]) ^ first[1], // generator.Rotate(first[2]) not included is '[2]' is suppressed
                                             generator.Distribute(first[1]) ^ first[0], 0L };

                Assert.IsTrue(Compares.AreDeepEqual(
                                  second,
                                  generator.Generate(new long[] { 1L, 2L, 1L }, StereoEncoder.Empty, new int[][] { new[] { 1 }, new[] { 0, 2 }, new[] { 1 } },
                                                     Suppressed.FromBitSet(suppressed))));
            }
        }
예제 #10
0
        public void TestGenerate_Disconnected()
        {
            var m_seedMock = new Mock <IAtomHashGenerator>(); var seedMock = m_seedMock.Object;
            var m_container = new Mock <IAtomContainer>(); var container = m_container.Object;

            SuppressedAtomHashGenerator generator = new SuppressedAtomHashGenerator(new Mock <IAtomHashGenerator>().Object,
                                                                                    new Xorshift(), AtomSuppression.Unsuppressed, 2);
            // there are no neighbours, the values should be rotated
            long expected = generator.Distribute(generator.Distribute(1));

            Assert.IsTrue(Compares.AreDeepEqual(
                              new long[] { expected, expected, expected },
                              generator.Generate(new long[] { 1L, 1L, 1L }, StereoEncoder.Empty, new int[][] { new int[] { }, new int[] { }, new int[] { } },
                                                 Suppressed.None)));
            BitArray suppressed = new BitArray(3);

            suppressed.Set(1, true);
            Assert.IsTrue(Compares.AreDeepEqual(
                              new long[] { expected, 0L, expected },
                              generator.Generate(new long[] { 1L, 1L, 1L }, StereoEncoder.Empty, new int[][] { new int[] { }, new int[] { }, new int[] { } },
                                                 Suppressed.FromBitSet(suppressed))));
        }
예제 #11
0
        public void TestGenerate_ZeroDepth()
        {
            var m_seedMock = new Mock <IAtomHashGenerator>(); var seedMock = m_seedMock.Object;
            var m_container = new Mock <IAtomContainer>(); var container = m_container.Object;

            SuppressedAtomHashGenerator generator = new SuppressedAtomHashGenerator(new Mock <IAtomHashGenerator>().Object,
                                                                                    new Xorshift(), AtomSuppression.Unsuppressed, 0);

            Assert.IsTrue(Compares.AreDeepEqual(
                              new long[] { 1L, 1L, 1L },
                              generator.Generate(new long[] { 1L, 1L, 1L }, StereoEncoder.Empty, new int[][] { new int[] { }, new int[] { }, new int[] { } },
                                                 Suppressed.None)));

            BitArray suppressed = new BitArray(3);

            suppressed.Set(0, true);
            suppressed.Set(2, true);

            Assert.IsTrue(Compares.AreDeepEqual(
                              new long[] { 0L, 1L, 0L },
                              generator.Generate(new long[] { 1L, 1L, 1L }, StereoEncoder.Empty, new int[][] { new int[] { }, new int[] { }, new int[] { } },
                                                 Suppressed.FromBitSet(suppressed))));
        }
예제 #12
0
        public void TestAnyPseudos()
        {
            var suppression = AtomSuppression.AnyPseudos;
            var m_container = new Mock <IAtomContainer>(); var container = m_container.Object;

            m_container.SetupGet(n => n.Atoms.Count).Returns(5);

            var m_carbon = new Mock <IAtom>(); var carbon = m_carbon.Object;
            var m_pseudo = new Mock <IPseudoAtom>(); var pseudo = m_pseudo.Object;

            m_container.SetupGet(n => n.Atoms[0]).Returns(carbon);
            m_container.SetupGet(n => n.Atoms[1]).Returns(pseudo);
            m_container.SetupGet(n => n.Atoms[2]).Returns(carbon);
            m_container.SetupGet(n => n.Atoms[3]).Returns(carbon);
            m_container.SetupGet(n => n.Atoms[4]).Returns(pseudo);

            Suppressed suppressed = suppression.Suppress(container);

            Assert.IsFalse(suppressed.Contains(0));
            Assert.IsTrue(suppressed.Contains(1));
            Assert.IsFalse(suppressed.Contains(2));
            Assert.IsFalse(suppressed.Contains(3));
            Assert.IsTrue(suppressed.Contains(4));
        }
예제 #13
0
        /// <summary>
        /// Package-private method for generating the hash for the given molecule.
        /// The initial invariants are passed as to the method along with an
        /// adjacency list representation of the graph.
        /// </summary>
        /// <param name="current">initial invariants</param>
        /// <param name="encoder"></param>
        /// <param name="graph">adjacency list representation</param>
        /// <param name="suppressed"></param>
        /// <returns>hash codes for atoms</returns>
        public override long[] Generate(long[] current, IStereoEncoder encoder, int[][] graph, Suppressed suppressed)
        {
            int n    = graph.Length;
            var next = Copy(current);

            // buffers for including adjacent invariants
            var unique   = new long[n];
            var included = new long[n];

            while (encoder.Encode(current, next))
            {
                Copy(next, current);
            }

            for (int d = 0; d < depth; d++)
            {
                for (int v = 0; v < n; v++)
                {
                    next[v] = Next(graph, v, current, unique, included);
                }

                Copy(next, current);

                while (encoder.Encode(current, next))
                {
                    Copy(next, current);
                }
            }

            return(current);
        }
예제 #14
0
 /// <summary>
 /// Internal method invoked by 'molecule' hash generators.
 /// </summary>
 /// <param name="current">the current invariants</param>
 /// <param name="encoder">encoder used for encoding stereo-chemistry</param>
 /// <param name="graph">adjacency list representation of the molecule</param>
 /// <param name="suppressed">bit set marks vertices which are 'suppressed' (may be ignored)</param>
 /// <returns>the atom hash values</returns>
 public abstract long[] Generate(long[] current, IStereoEncoder encoder, int[][] graph, Suppressed suppressed);
예제 #15
0
        /// <summary>
        /// Determine the next value of the atom at index <paramref name="v"/>. The value is
        /// calculated by combining the current values of adjacent atoms. When a
        /// duplicate value is found it can not be directly included and is
        /// <i>rotated</i> the number of times it has previously been seen.
        /// </summary>
        /// <param name="graph">adjacency list representation of connected atoms</param>
        /// <param name="v">the atom to calculate the next value for</param>
        /// <param name="current">the current values</param>
        /// <param name="unique">buffer for working out which adjacent values are unique</param>
        /// <param name="included">buffer for storing the rotated <i>unique</i> value, this value is <i>rotated</i> each time the same value is found.</param>
        /// <param name="suppressed">bit set indicates which atoms are 'suppressed'</param>
        /// <returns>the next value for <paramref name="v"/></returns>
        internal long Next(int[][] graph, int v, long[] current, long[] unique, long[] included, Suppressed suppressed)
        {
            if (suppressed.Contains(v))
            {
                return(current[v]);
            }

            long invariant = Distribute(current[v]);
            int  nUnique   = 0;

            foreach (var w in graph[v])
            {
                // skip suppressed atom
                if (suppressed.Contains(w))
                {
                    continue;
                }

                long adjInv = current[w];

                // find index of already included neighbor
                int i = 0;
                while (i < nUnique && unique[i] != adjInv)
                {
                    ++i;
                }

                // no match, then the value is unique, use adjInv
                // match, then rotate the previously included value
                included[i] = (i == nUnique) ? unique[nUnique++] = adjInv : Rotate(included[i]);

                invariant ^= included[i];
            }

            return(invariant);
        }
예제 #16
0
        /// <summary>
        /// Package-private method for generating the hash for the given molecule.
        /// The initial invariants are passed as to the method along with an
        /// adjacency list representation of the graph.
        /// </summary>
        /// <param name="current">initial invariants</param>
        /// <param name="encoder"></param>
        /// <param name="graph">adjacency list representation</param>
        /// <param name="suppressed"></param>
        /// <returns>hash codes for atoms</returns>
        public override long[] Generate(long[] current, IStereoEncoder encoder, int[][] graph, Suppressed suppressed)
        {
            // for the stereo perception depending on how the
            // (BasicPermutationParity) is done we need to set the value to be as
            // high (or low) as possible
            foreach (var i in suppressed.ToArray())
            {
                current[i] = long.MaxValue;
            }

            int n = graph.Length;

            long[] next = Copy(current);

            // buffers for including adjacent invariants
            long[] unique   = new long[n];
            long[] included = new long[n];

            while (encoder.Encode(current, next))
            {
                Copy(next, current);
            }

            for (int d = 0; d < depth; d++)
            {
                for (int v = 0; v < n; v++)
                {
                    next[v] = Next(graph, v, current, unique, included, suppressed);
                }

                Copy(next, current);

                while (encoder.Encode(current, next))
                {
                    Copy(next, current);
                }
            }

            // zero all suppressed values so they are not combined in any molecule
            // hash
            foreach (var i in suppressed.ToArray())
            {
                current[i] = 0L;
            }

            return(current);
        }