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)); }
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)); }
public void None() { Suppressed suppressed = Suppressed.None; for (int i = 0; i < 1000; i++) { Assert.IsFalse(suppressed.Contains(i)); } }
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)); }
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)); }
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 } }
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)); }
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); }
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)))); } }
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)))); }
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)))); }
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)); }
/// <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); }
/// <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);
/// <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); }
/// <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); }