Пример #1
0
        /// <summary>
        /// Check if all the edges of the <paramref name="cycle"/> are present in the current
        /// <see cref="basis"/>.
        /// </summary>
        /// <param name="cycle">an initial cycle</param>
        /// <returns>any edges of the basis are present</returns>
        public bool IsSubsetOfBasis(Cycle cycle)
        {
            BitArray edgeVector = cycle.EdgeVector;
            int      intersect  = BitArrays.Cardinality(And(edgesOfBasis, edgeVector));

            return(intersect == cycle.Length);
        }
        public void TestBug931608()
        {
            var            builder    = CDK.Builder;
            var            filename   = "NCDK.Data.MDL.bug931608-1.mol";
            var            ins        = ResourceLoader.GetAsStream(filename);
            var            reader     = new MDLV2000Reader(ins, ChemObjectReaderMode.Strict);
            IAtomContainer structure1 = (IAtomContainer)reader.Read(builder.NewAtomContainer());

            filename = "NCDK.Data.MDL.bug931608-2.mol";
            ins      = ResourceLoader.GetAsStream(filename);
            reader   = new MDLV2000Reader(ins, ChemObjectReaderMode.Strict);
            IAtomContainer structure2 = (IAtomContainer)reader.Read(builder.NewAtomContainer());

            AtomContainerManipulator.PercieveAtomTypesAndConfigureAtoms(structure1);
            AtomContainerManipulator.PercieveAtomTypesAndConfigureAtoms(structure2);

            IFingerprinter fingerprinter = GetBitFingerprinter();
            BitArray       bs1           = fingerprinter.GetBitFingerprint(structure1).AsBitSet();
            BitArray       bs2           = fingerprinter.GetBitFingerprint(structure2).AsBitSet();

            // now we do the bool XOR on the two bitsets, leading
            // to a bitset that has all the bits set to "true" which differ
            // between the two original bitsets
            bs1.Xor(bs2);
            // cardinality gives us the number of "true" bits in the
            // result of the XOR operation.
            int cardinality = BitArrays.Cardinality(bs1);

            Assert.AreEqual(0, cardinality);
        }
Пример #3
0
        /// <summary>
        /// Attempt to augment the matching such that it is perfect over the subset
        /// of vertices in the provided graph.
        /// </summary>
        /// <param name="graph">adjacency list representation of graph</param>
        /// <param name="subset">subset of vertices</param>
        /// <returns>the matching was perfect</returns>
        /// <exception cref="ArgumentException">the graph was a different size to the matching capacity</exception>
        public bool Perfect(int[][] graph, BitArray subset)
        {
            if (graph.Length != match.Length || BitArrays.Cardinality(subset) > graph.Length)
            {
                throw new ArgumentException("graph and matching had different capacity");
            }

            // and odd set can never provide a perfect matching
            if ((BitArrays.Cardinality(subset) & 0x1) == 0x1)
            {
                return(false);
            }

            // arbitrary matching was perfect
            if (ArbitaryMatching(graph, subset))
            {
                return(true);
            }

            EdmondsMaximumMatching.Maxamise(this, graph, subset);

            // the matching is imperfect if any vertex was
            for (int v = BitArrays.NextSetBit(subset, 0); v >= 0; v = BitArrays.NextSetBit(subset, v + 1))
            {
                if (Unmatched(v))
                {
                    return(false);
                }
            }

            return(true);
        }
Пример #4
0
        public static Graph GenerateKekuleForm(Graph g, BitArray subset, BitArray aromatic, bool inplace)
        {
            // make initial (empty) matching - then improve it, first
            // by matching the first edges we find, most of time this
            // gives us a perfect matching if not we maximise it
            // with Edmonds' algorithm

            Matching m        = Matching.CreateEmpty(g);
            int      n        = BitArrays.Cardinality(subset);
            int      nMatched = ArbitraryMatching.Initial(g, m, subset);

            if (nMatched < n)
            {
                if (n - nMatched == 2)
                {
                    nMatched = ArbitraryMatching.AugmentOnce(g, m, nMatched, subset);
                }
                if (nMatched < n)
                {
                    nMatched = MaximumMatching.Maximise(g, m, nMatched, IntSet.FromBitArray(subset));
                }
                if (nMatched < n)
                {
                    throw new InvalidSmilesException("Could not Kekulise");
                }
            }
            return(inplace ? Assign(g, subset, aromatic, m)
                           : CopyAndAssign(g, subset, aromatic, m));
        }
Пример #5
0
        private void Reduce(int x, int lim)
        {
            IList <PathEdge> es = pathGraph[x];
            int deg             = es.Count;

            for (int i = 0; i < deg; i++)
            {
                PathEdge e1 = es[i];
                for (int j = i + 1; j < deg; j++)
                {
                    PathEdge e2 = es[j];
                    if (!e1.Intersects(e2))
                    {
                        PathEdge reduced = Reduce(e1, e2, x);
                        if (BitArrays.Cardinality(reduced.xs) >= lim)
                        {
                            continue;
                        }
                        if (reduced.Loop())
                        {
                            if (reduced.CheckPiElectrons(ps))
                            {
                                reduced.Flag(aromatic);
                            }
                        }
                        else
                        {
                            Add(reduced);
                        }
                    }
                }
            }
            pathGraph[x].Clear();
        }
Пример #6
0
        public void Benzylbenzene()
        {
            Graph g = Graph.FromSmiles("c1ccccc1Cc1ccccc1");
            BiconnectedComponents bc = new BiconnectedComponents(g, false);

            Assert.AreEqual(12, BitArrays.Cardinality(bc.Cyclic));
        }
Пример #7
0
 /// <summary>
 /// Find the next index that the <i>cycle</i> intersects with by at least two
 /// vertices. If the intersect of a vertex set with another contains more
 /// then two vertices it cannot be edge disjoint.
 /// </summary>
 /// <param name="start">start searching from here</param>
 /// <param name="cycle">test whether any current cycles are fused with this one</param>
 /// <returns>the index of the first fused after 'start', -1 if none</returns>
 private int IndexOfFused(int start, BitArray cycle)
 {
     for (int i = start; i < cycles.Count(); i++)
     {
         if (BitArrays.Cardinality(And(cycles[i], cycle)) > 1)
         {
             return(i);
         }
     }
     return(-1);
 }
        public void TestGenerateFingerprintNaphthalene()
        {
            var smiles       = "C1=CC2=CC=CC=C2C=C1";
            var smilesParser = CDK.SmilesParser;
            var molecule     = smilesParser.ParseSmiles(smiles);

            AtomContainerManipulator.PercieveAtomTypesAndConfigureAtoms(molecule);
            Aromaticity.CDKLegacy.Apply(molecule);
            ShortestPathFingerprinter fingerprint = new ShortestPathFingerprinter(1024);
            BitArray fingerprint1;

            fingerprint1 = fingerprint.GetBitFingerprint(molecule).AsBitSet();
            Assert.AreEqual(8, BitArrays.Cardinality(fingerprint1));
        }
        public void TestGenerateFingerprintMultiphtalene()
        {
            var smiles       = "C1=CC2=CC=C3C4=CC5=CC6=CC=CC=C6C=C5C=C4C=CC3=C2C=C1";
            var smilesParser = CDK.SmilesParser;
            var molecule     = smilesParser.ParseSmiles(smiles);

            AtomContainerManipulator.PercieveAtomTypesAndConfigureAtoms(molecule);

            AtomContainerManipulator.PercieveAtomTypesAndConfigureAtoms(molecule);
            ShortestPathFingerprinter fingerprint = new ShortestPathFingerprinter(1024);
            BitArray fingerprint1;

            fingerprint1 = fingerprint.GetBitFingerprint(molecule).AsBitSet();
            Assert.AreEqual(15, BitArrays.Cardinality(fingerprint1));
        }
Пример #10
0
        /// <summary>
        /// Add the cycle vertices to our discovered cycles. The cycle is first
        /// checked to see if it is isolated (shares at most one vertex) or
        /// <i>potentially</i> fused.
        /// </summary>
        /// <param name="cycle">newly discovered cyclic vertex set</param>
        private void Add(BitArray cycle)
        {
            BitArray intersect = And(cycle, cyclic);

            if (BitArrays.Cardinality(intersect) > 1)
            {
                AddFused(cycle);
            }
            else
            {
                AddIsolated(cycle);
            }

            cyclic.Or(cycle);
        }
Пример #11
0
        /// <summary>
        /// Convert the set bits of a BitArray to an int[].
        /// </summary>
        /// <param name="set">input with 0 or more set bits</param>
        /// <returns>the bits which are set in the input</returns>
        public static int[] ToArray(BitArray set)
        {
            int[] vertices = new int[BitArrays.Cardinality(set)];
            int   i        = 0;

            // fill the cyclic vertices with the bits that have been set
            for (int v = 0; i < vertices.Length; v++)
            {
                if (set[v])
                {
                    vertices[i++] = v;
                }
            }

            return(vertices);
        }
Пример #12
0
        /// <summary>
        /// Evaluates Tanimoto coefficient for two bit sets.
        /// </summary>
        /// <param name="bitset1">A bitset (such as a fingerprint) for the first molecule</param>
        /// <param name="bitset2">A bitset (such as a fingerprint) for the second molecule</param>
        /// <returns>The Tanimoto coefficient</returns>
        /// <exception cref="CDKException"> if bitsets are not of the same length</exception>
        public static double Calculate(BitArray bitset1, BitArray bitset2)
        {
            double _bitset1_cardinality = BitArrays.Cardinality(bitset1);
            double _bitset2_cardinality = BitArrays.Cardinality(bitset2);

            if (bitset1.Count != bitset2.Count)
            {
                throw new CDKException($"{nameof(bitset1)} and {nameof(bitset2)} must have the same bit length");
            }
            BitArray one_and_two = (BitArray)bitset1.Clone();

            one_and_two.And(bitset2);
            double _common_bit_count = BitArrays.Cardinality(one_and_two);

            return(_common_bit_count / (_bitset1_cardinality + _bitset2_cardinality - _common_bit_count));
        }
Пример #13
0
        /// <summary>
        /// Create a new cyclic vertex search for the provided graph.
        /// </summary>
        /// <param name="graph">adjacency list representation of a graph</param>
        public JumboCyclicVertexSearch(IReadOnlyList <IReadOnlyList <int> > graph)
        {
            this.g = graph;
            int n = graph.Count;

            cyclic = new BitArray(n);

            if (n == 0)
            {
                return;
            }

            state   = new BitArray[n];
            visited = new BitArray(n);

            BitArray empty = new BitArray(n);

            // start from vertex 0
            Search(0, Copy(empty), Copy(empty));

            // if g is a fragment we will not have visited everything
            int v = 0;

            while (BitArrays.Cardinality(visited) != n)
            {
                v++;
                // each search expands to the whole fragment, as we
                // may have fragments we need to visit 0 and then
                // check every other vertex
                if (!visited[v])
                {
                    Search(v, Copy(empty), Copy(empty));
                }
            }

            // allow the states to be collected
            state   = null;
            visited = null;
        }
Пример #14
0
        private void StoreWithComp(Edge e)
        {
            List <Edge> component = new List <Edge>(6);
            Edge        f;

            BitArray tmp = new BitArray(g.Order);

            // count the number of unique vertices and edges
            int  numEdges = 0;
            bool spiro    = false;

            do
            {
                f = stack[--nstack];
                int v = f.Either();
                int w = f.Other(v);

                if (cyclic[v] || cyclic[w])
                {
                    spiro = true;
                }

                tmp.Set(v, true);
                tmp.Set(w, true);

                component.Add(f);
                numEdges++;
            } while (f != e);

            cyclic.Or(tmp);

            if (!spiro && BitArrays.Cardinality(tmp) == numEdges)
            {
                simple.Or(tmp);
            }

            components.Add(component);
        }
Пример #15
0
 private static bool HasOddCardinality(BitArray s)
 {
     return((BitArrays.Cardinality(s) & 0x1) == 1);
 }
Пример #16
0
        public static Graph Resonate(Graph g, BitArray cyclic, bool ordered)
        {
            BitArray subset = new BitArray(g.Order);

            for (int u = BitArrays.NextSetBit(cyclic, 0); u >= 0; u = BitArrays.NextSetBit(cyclic, u + 1))
            {
                // candidates must have a bonded
                // valence of one more than their degree
                // and in a ring
                int uExtra = g.BondedValence(u) - g.Degree(u);
                if (uExtra > 0)
                {
                    int  other  = -1;
                    Edge target = null;

                    int d = g.Degree(u);
                    for (int j = 0; j < d; ++j)
                    {
                        Edge e = g.EdgeAt(u, j);
                        int  v = e.Other(u);
                        // check for bond validity
                        if (e.Bond.Order == 2)
                        {
                            int vExtra = g.BondedValence(v) - g.Degree(v);
                            if (cyclic[v] && vExtra > 0)
                            {
                                if (HasAdjDirectionalLabels(g, e, cyclic) && !InSmallRing(g, e))
                                {
                                    other = -1;
                                    break;
                                }
                                if (vExtra > 1 && HasAdditionalCyclicDoubleBond(g, cyclic, u, v))
                                {
                                    other = -1;
                                    break;
                                }
                                if (other == -1)
                                {
                                    other  = v; // first one
                                    target = e;
                                }
                                else
                                {
                                    other = -2; // found more than one
                                }
                            }
                            // only one double bond don't check any more
                            if (uExtra == 1)
                            {
                                break;
                            }
                        }
                    }

                    if (other >= 0)
                    {
                        subset.Set(u, true);
                        subset.Set(other, true);
                        target.SetBond(Bond.Implicit);
                    }
                }
            }

            if (!ordered)
            {
                g = g.Sort(new Graph.CanOrderFirst());
            }

            Matching m        = Matching.CreateEmpty(g);
            int      n        = BitArrays.Cardinality(subset);
            int      nMatched = ArbitraryMatching.Dfs(g, m, subset);

            if (nMatched < n)
            {
                if (n - nMatched == 2)
                {
                    nMatched = ArbitraryMatching.AugmentOnce(g, m, nMatched, subset);
                }
                if (nMatched < n)
                {
                    nMatched = MaximumMatching.Maximise(g, m, nMatched, IntSet.FromBitArray(subset));
                }
                if (nMatched < n)
                {
                    throw new ApplicationException("Could not Kekulise");
                }
            }

            // assign new double bonds
            for (int v = BitArrays.NextSetBit(subset, 0); v >= 0; v = BitArrays.NextSetBit(subset, v + 1))
            {
                int w = m.Other(v);
                subset.Set(w, false);
                g.CreateEdge(v, w).SetBond(Bond.Double);
            }

            return(g);
        }
Пример #17
0
        /// <summary>
        /// Assign an arbitrary matching that covers the subset of vertices.
        /// </summary>
        /// <param name="graph">adjacency list representation of graph</param>
        /// <param name="subset">subset of vertices in the graph</param>
        /// <returns>the matching was perfect</returns>
        internal bool ArbitaryMatching(int[][] graph, BitArray subset)
        {
            BitArray unmatched = new BitArray(subset.Length);

            // indicates the deg of each vertex in unmatched subset
            int[] deg = new int[graph.Length];

            // queue/stack of vertices with deg1 vertices
            int[] deg1 = new int[graph.Length];
            int   nd1 = 0, nMatched = 0;

            for (int v = BitArrays.NextSetBit(subset, 0); v >= 0; v = BitArrays.NextSetBit(subset, v + 1))
            {
                if (Matched(v))
                {
                    Trace.Assert(subset[Other(v)]);
                    nMatched++;
                    continue;
                }
                unmatched.Set(v, true);
                foreach (var w in graph[v])
                {
                    if (subset[w] && Unmatched(w))
                    {
                        deg[v]++;
                    }
                }
                if (deg[v] == 1)
                {
                    deg1[nd1++] = v;
                }
            }

            while (!BitArrays.IsEmpty(unmatched))
            {
                int v = -1;

                // attempt to select a vertex with degree = 1 (in matched set)
                while (nd1 > 0)
                {
                    v = deg1[--nd1];
                    if (unmatched[v])
                    {
                        break;
                    }
                }

                // no unmatched degree 1 vertex, select the first unmatched
                if (v < 0 || unmatched[v])
                {
                    v = BitArrays.NextSetBit(unmatched, 0);
                }

                unmatched.Set(v, false);

                // find a unmatched edge and match it, adjacent degrees are updated
                foreach (var w in graph[v])
                {
                    if (unmatched[w])
                    {
                        Match(v, w);
                        nMatched += 2;
                        unmatched.Set(w, false);
                        // update neighbors of w and v (if needed)
                        foreach (var u in graph[w])
                        {
                            if (--deg[u] == 1 && unmatched[u])
                            {
                                deg1[nd1++] = u;
                            }
                        }

                        // if deg == 1, w is the only neighbor
                        if (deg[v] > 1)
                        {
                            foreach (var u in graph[v])
                            {
                                if (--deg[u] == 1 && unmatched[u])
                                {
                                    deg1[nd1++] = u;
                                }
                            }
                        }
                        break;
                    }
                }
            }

            return(nMatched == BitArrays.Cardinality(subset));
        }