Exemplo n.º 1
0
        /// <summary>
        /// Create an arbitrary matching on the subset of vertices ('s') of provided
        /// graph. The provided matching should be empty.
        ///
        /// <param name="g">graph to match</param>
        /// <param name="m">empty matching (presumed)</param>
        /// <param name="s">subset of vertices</param>
        /// <returns>number of vertices matched</returns>
        /// </summary>
        public static int Initial(Graph g, Matching m, BitArray s)
        {
            int nMatched = 0;

            for (int v = BitArrays.NextSetBit(s, 0); v >= 0; v = BitArrays.NextSetBit(s, v + 1))
            {
                // skip if already matched
                if (m.Matched(v))
                {
                    continue;
                }

                // find a single edge which is not matched and match it
                int d = g.Degree(v);
                for (int j = 0; j < d; ++j)
                {
                    Edge e = g.EdgeAt(v, j);
                    int  w = e.Other(v);
                    if ((e.Bond != Bond.Single) && m.Unmatched(w) && s[w])
                    {
                        m.Match(v, w);
                        nMatched += 2;
                        break;
                    }
                }
            }

            return(nMatched);
        }
Exemplo n.º 2
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);
        }
Exemplo n.º 3
0
 // invariant, m is a perfect matching
 private static Graph Assign(Graph g, BitArray subset, BitArray aromatic, Matching m)
 {
     g.SetFlags(g.GetFlags() & ~Graph.HAS_AROM);
     for (int u = BitArrays.NextSetBit(aromatic, 0); u >= 0; u = BitArrays.NextSetBit(aromatic, u + 1))
     {
         g.SetAtom(u, g.GetAtom(u).AsAliphaticForm());
         int deg = g.Degree(u);
         for (int j = 0; j < deg; ++j)
         {
             Edge e = g.EdgeAt(u, j);
             int  v = e.Other(u);
             if (v < u)
             {
                 var aa = e.Bond;
                 if (aa == Bond.Single)
                 {
                     if (aromatic[u] && aromatic[v])
                     {
                         e.SetBond(Bond.Single);
                     }
                     else
                     {
                         e.SetBond(Bond.Implicit);
                     }
                 }
                 else if (aa == Bond.Aromatic)
                 {
                     if (subset[u] && m.Other(u) == v)
                     {
                         e.SetBond(Bond.DoubleAromatic);
                         g.UpdateBondedValence(u, +1);
                         g.UpdateBondedValence(v, +1);
                     }
                     else if (aromatic[v])
                     {
                         e.SetBond(Bond.ImplicitAromatic);
                     }
                     else
                     {
                         e.SetBond(Bond.Implicit);
                     }
                 }
                 else if (aa == Bond.Implicit)
                 {
                     if (subset[u] && m.Other(u) == v)
                     {
                         e.SetBond(Bond.DoubleAromatic);
                         g.UpdateBondedValence(u, +1);
                         g.UpdateBondedValence(v, +1);
                     }
                     else if (aromatic[u] && aromatic[v])
                     {
                         e.SetBond(Bond.ImplicitAromatic);
                     }
                 }
             }
         }
     }
     return(g);
 }
Exemplo n.º 4
0
        /// <summary>
        /// List all differences between the two bit vectors. Unlike
        /// <see cref="ListDifferences(BitArray, BitArray)"/> which only list
        /// those which are set in <paramref name="s"/> but not in <paramref name="t"/>.
        /// </summary>
        /// <param name="s">a bit vector</param>
        /// <param name="t">another bit vector</param>
        /// <returns>all differences between <paramref name="s"/> and <paramref name="t"/></returns>
        public static IReadOnlyCollection <int> Differences(BitArray s, BitArray t)
        {
            var u   = (BitArray)s.Clone();
            var v   = (BitArray)t.Clone();
            var len = Math.Max(u.Length, v.Length);

            if (u.Length < len)
            {
                u.Length = len;
            }
            if (v.Length < len)
            {
                v.Length = len;
            }
            u.Xor(v);

            var differences = new SortedSet <int>();

            for (int i = BitArrays.NextSetBit(u, 0); i >= 0; i = BitArrays.NextSetBit(u, i + 1))
            {
                differences.Add(i);
            }

            return(differences);
        }
Exemplo n.º 5
0
 public void Flag(bool[] mark)
 {
     mark[u] = true;
     for (int i = BitArrays.NextSetBit(xs, 0); i >= 0; i = BitArrays.NextSetBit(xs, i + 1))
     {
         mark[i] = true;
     }
 }
Exemplo n.º 6
0
            public override int[] ToArray()
            {
                int[] xs = new int[Count];
                int   n  = 0;

                for (int i = BitArrays.NextSetBit(set, 0); i >= 0; i = BitArrays.NextSetBit(set, i + 1))
                {
                    xs[n++] = i;
                }
                return(xs);
            }
Exemplo n.º 7
0
        /// <summary>
        ///  Converts a CDKRGraph bitset (set of CDKRNode)
        /// to a list of CDKRMap that represents the
        /// mapping between to substructures in G1 and G2
        /// (the projection of the CDKRGraph bitset on G1
        /// and G2).
        ///
        /// <param name="set">the BitArray</param>
        /// <returns>the CDKRMap list</returns>
        /// </summary>
        public IReadOnlyList <CDKRMap> BitSetToRMap(BitArray set)
        {
            List <CDKRMap> rMapList = new List <CDKRMap>();

            for (int x = BitArrays.NextSetBit(set, 0); x >= 0; x = BitArrays.NextSetBit(set, x + 1))
            {
                CDKRNode xNode = Graph[x];
                rMapList.Add(xNode.RMap);
            }
            return(rMapList);
        }
Exemplo n.º 8
0
        /////////////////////////////////
        // BitArray tools
        /// <summary>
        ///  Projects a RGraph bitset on the source graph G1.
        /// </summary>
        /// <param name="set">RGraph BitArray to project</param>
        /// <returns>The associate BitArray in G1</returns>
        public BitArray ProjectG1(BitArray set)
        {
            BitArray projection = new BitArray(FirstGraphSize);
            RNode    xNode      = null;

            for (int x = BitArrays.NextSetBit(set, 0); x >= 0; x = BitArrays.NextSetBit(set, x + 1))
            {
                xNode = (RNode)graph[x];
                projection.Set(xNode.RMap.Id1, true);
            }
            return(projection);
        }
Exemplo n.º 9
0
        /// <summary>
        ///  Projects a CDKRGraph bitset on the source graph G2.
        /// </summary>
        /// <param name="set">CDKRGraph BitArray to project</param>
        /// <returns>The associate BitArray in G2</returns>
        public BitArray ProjectG2(BitArray set)
        {
            BitArray projection = new BitArray(SecondGraphSize);
            CDKRNode xNode      = null;

            for (int x = BitArrays.NextSetBit(set, 0); x >= 0; x = BitArrays.NextSetBit(set, x + 1))
            {
                xNode = Graph[x];
                projection.Set(xNode.RMap.Id2, true);
            }
            return(projection);
        }
Exemplo n.º 10
0
        public bool Encode(long[] current, long[] next)
        {
            bool configured = false;

            for (int i = BitArrays.NextSetBit(unconfigured, 0); i >= 0; i = BitArrays.NextSetBit(unconfigured, i + 1))
            {
                if (encoders[i].Encode(current, next))
                {
                    unconfigured.Set(i, false); // don't configure again (unless reset)
                    configured = true;
                }
            }
            return(configured);
        }
Exemplo n.º 11
0
        /// <summary>
        /// Build an indexed lookup of vertex color. The vertex color indicates which
        /// cycle a given vertex belongs. If a vertex belongs to more then one cycle
        /// it is colored '0'. If a vertex belongs to no cycle it is colored '-1'.
        /// </summary>
        /// <returns>vertex colors</returns>
        private int[] BuildVertexColor()
        {
            int[] color = new int[g.Count];

            int n = 1;

            Arrays.Fill(color, -1);
            foreach (var cycle in cycles)
            {
                for (int i = BitArrays.NextSetBit(cycle, 0); i >= 0; i = BitArrays.NextSetBit(cycle, i + 1))
                {
                    color[i] = color[i] < 0 ? n : 0;
                }
                n++;
            }

            return(color);
        }
Exemplo n.º 12
0
        /// <summary>
        /// Assign a Kekulé representation to the aromatic systems of a compound.
        /// </summary>
        /// <param name="ac">structural representation</param>
        /// <exception cref="CDKException">a Kekulé form could not be assigned</exception>
        public static void Kekulize(IAtomContainer ac)
        {
            // storage of pairs of atoms that have pi-bonded
            var matching = Matching.WithCapacity(ac.Atoms.Count);

            // exract data structures for efficient access
            var atoms = ac.Atoms.ToArray();
            var bonds = EdgeToBondMap.WithSpaceFor(ac);
            var graph = GraphUtil.ToAdjList(ac, bonds);

            // determine which atoms are available to have a pi bond placed
            var available = IsAvailable(graph, atoms, bonds);

            // attempt to find a perfect matching such that a pi bond is placed
            // next to each available atom. if not found the solution is ambiguous
            if (!matching.Perfect(graph, available))
            {
                throw new CDKException("Cannot assign Kekulé structure without randomly creating radicals.");
            }

            // propagate bond order information from the matching
            foreach (var bond in ac.Bonds)
            {
                if (bond.Order == BondOrder.Unset && bond.IsAromatic)
                {
                    bond.Order = BondOrder.Single;
                }
            }
            for (int v = BitArrays.NextSetBit(available, 0); v >= 0; v = BitArrays.NextSetBit(available, v + 1))
            {
                var w    = matching.Other(v);
                var bond = bonds[v, w];

                // sanity check, something wrong if this happens
                if (bond.Order.Numeric() > 1)
                {
                    throw new CDKException("Cannot assign Kekulé structure, non-sigma bond order has already been assigned?");
                }

                bond.Order = BondOrder.Double;
                available.Set(w, false);
            }
        }
Exemplo n.º 13
0
        /// <summary>
        /// Check if it is possible to assign electrons to the subgraph (specified by
        /// the set bits in of <paramref name="bs"/>). Each connected subset is counted up and
        /// checked for odd cardinality.
        /// </summary>
        /// <param name="g"> graph</param>
        /// <param name="bs">binary set indicated vertices for the subgraph</param>
        /// <returns>there is an odd cardinality subgraph</returns>
        private static bool ContainsOddCardinalitySubgraph(Graph g, BitArray bs)
        {
            // mark visited those which are not in any subgraph
            bool[] visited = new bool[g.Order];
            for (int i = BitArrays.NextClearBit(bs, 0); i < g.Order; i = BitArrays.NextClearBit(bs, i + 1))
            {
                visited[i] = true;
            }

            // from each unvisited vertices visit the connected vertices and count
            // how many there are in this component. if there is an odd number there
            // is no assignment of double bonds possible
            for (int i = BitArrays.NextSetBit(bs, 0); i >= 0; i = BitArrays.NextSetBit(bs, i + 1))
            {
                if (!visited[i] && IsOdd(Visit(g, i, 0, visited)))
                {
                    return(true);
                }
            }

            return(false);
        }
Exemplo n.º 14
0
        /// <summary>
        /// When precisely two vertices are unmatched we only need to find a single
        /// augmenting path. Rather than run through edmonds with blossoms etc we
        /// simple do a targest DFS for the path.
        ///
        /// <param name="g">graph</param>
        /// <param name="m">matching</param>
        /// <param name="nMatched">current matching cardinality must be |s|-nMathced == 2</param>
        /// <param name="s">subset size</param>
        /// <returns>new match cardinality</returns>
        /// </summary>
        public static int AugmentOnce(Graph g, Matching m, int nMatched, BitArray s)
        {
            int vStart = BitArrays.NextSetBit(s, 0);

            while (vStart >= 0)
            {
                if (!m.Matched(vStart))
                {
                    break;
                }
                vStart = BitArrays.NextSetBit(s, vStart + 1);
            }
            int vEnd = BitArrays.NextSetBit(s, vStart + 1);

            while (vEnd >= 0)
            {
                if (!m.Matched(vEnd))
                {
                    break;
                }
                vEnd = BitArrays.NextSetBit(s, vEnd + 1);
            }

            // find an augmenting path between vStart and vEnd
            int[] path = new int[g.Order];
            int   len  = FindPath(g, vStart, vEnd, s, path, 0, m, false);

            if (len > 0)
            {
                // augment
                for (int i = 0; i < len; i += 2)
                {
                    m.Match(path[i], path[i + 1]);
                }
                nMatched += 2;
            }

            return(nMatched);
        }
Exemplo n.º 15
0
        public static int Dfs(Graph g, Matching m, BitArray s)
        {
            int      nMatched  = 0;
            BitArray unvisited = (BitArray)s.Clone();

            // visit those with degree 1 first and expand out matching
            for (int v = BitArrays.NextSetBit(unvisited, 0); v >= 0; v = BitArrays.NextSetBit(unvisited, v + 1))
            {
                if (!m.Matched(v))
                {
                    int cnt = 0;
                    int d   = g.Degree(v);
                    while (--d >= 0)
                    {
                        int w = g.EdgeAt(v, d).Other(v);
                        if (unvisited[w])
                        {
                            ++cnt;
                        }
                    }
                    if (cnt == 1)
                    {
                        nMatched += DfsVisit(g, v, m, unvisited, true);
                    }
                }
            }

            // now those which aren't degree 1
            for (int v = BitArrays.NextSetBit(unvisited, 0); v >= 0; v = BitArrays.NextSetBit(unvisited, v + 1))
            {
                if (!m.Matched(v))
                {
                    nMatched += DfsVisit(g, v, m, unvisited, true);
                }
            }

            return(nMatched);
        }
Exemplo n.º 16
0
        /// <summary>
        /// Create the topologies (stereo configurations) for the chemical graph. The
        /// topologies define spacial arrangement around atoms.
        /// </summary>
        private void CreateTopologies(CharBuffer buffer)
        {
            // create topologies (stereo configurations)
            foreach (var e in configurations)
            {
                AddTopology(e.Key,
                            Topology.ToExplicit(g, e.Key, e.Value));
            }

            for (int v = BitArrays.NextSetBit(checkDirectionalBonds, 0); v >= 0; v = BitArrays.NextSetBit(checkDirectionalBonds, v + 1))
            {
                int nUpV   = 0;
                int nDownV = 0;
                int nUpW   = 0;
                int nDownW = 0;
                int w      = -1;

                {
                    int d = g.Degree(v);
                    for (int j = 0; j < d; ++j)
                    {
                        Edge e    = g.EdgeAt(v, j);
                        Bond bond = e.GetBond(v);
                        if (bond == Bond.Up)
                        {
                            nUpV++;
                        }
                        else if (bond == Bond.Down)
                        {
                            nDownV++;
                        }
                        else if (bond == Bond.Double)
                        {
                            w = e.Other(v);
                        }
                    }
                }

                if (w < 0)
                {
                    continue;
                }

                BitArrays.EnsureCapacity(checkDirectionalBonds, w + 1);
                checkDirectionalBonds.Set(w, false);

                {
                    int d = g.Degree(w);
                    for (int j = 0; j < d; ++j)
                    {
                        Edge e    = g.EdgeAt(w, j);
                        Bond bond = e.GetBond(w);
                        if (bond == Bond.Up)
                        {
                            nUpW++;
                        }
                        else if (bond == Bond.Down)
                        {
                            nDownW++;
                        }
                    }
                }

                if (nUpV + nDownV == 0 || nUpW + nDownW == 0)
                {
                    continue;
                }

                if (nUpV > 1)
                {
                    throw new InvalidSmilesException("Multiple directional bonds on atom " + v, buffer);
                }
                if (nDownV > 1)
                {
                    throw new InvalidSmilesException("Multiple directional bonds on atom " + v, buffer);
                }
                if (nUpW > 1)
                {
                    throw new InvalidSmilesException("Multiple directional bonds on atom " + w, buffer);
                }
                if (nDownW > 1)
                {
                    throw new InvalidSmilesException("Multiple directional bonds on atom " + w, buffer);
                }
            }
        }
Exemplo n.º 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));
        }
Exemplo n.º 18
0
        /// <summary>
        ///  Parsing of the CDKRGraph. This is the recursive method
        ///  to perform a query. The method will recursively
        ///  parse the CDKRGraph thru connected nodes and visiting the
        ///  CDKRGraph using allowed adjacency relationship.
        /// </summary>
        /// <param name="traversed">node already parsed</param>
        /// <param name="extension">possible extension node (allowed neighbors)</param>
        /// <param name="forbidden">node forbidden (set of node incompatible with the current solution)</param>
        private void ParseRec(BitArray traversed, BitArray extension, BitArray forbidden)
        {
            BitArray newTraversed  = null;
            BitArray newExtension  = null;
            BitArray newForbidden  = null;
            BitArray potentialNode = null;

            CheckTimeOut();

            // if there is no more extension possible we
            // have reached a potential new solution
            if (BitArrays.IsEmpty(extension))
            {
                Solution(traversed);
            } // carry on with each possible extension
            else
            {
                // calculates the set of nodes that may still
                // be reached at this stage (not forbidden)
                potentialNode = ((BitArray)GraphBitSet.Clone());
                BitArrays.AndNot(potentialNode, forbidden);
                potentialNode.Or(traversed);

                // checks if we must continue the search
                // according to the potential node set
                if (MustContinue(potentialNode))
                {
                    // carry on research and update iteration count
                    NbIteration = NbIteration + 1;

                    // for each node in the set of possible extension (neighbors of
                    // the current partial solution, include the node to the solution
                    // and parse recursively the CDKRGraph with the new context.
                    for (int x = BitArrays.NextSetBit(extension, 0); x >= 0; x = BitArrays.NextSetBit(extension, x + 1))
                    {
#if !DEBUG && !TEST
                        if (IsStop)
                        {
                            break;
                        }
#endif

                        // evaluates the new set of forbidden nodes
                        // by including the nodes not compatible with the
                        // newly accepted node.
                        newForbidden = (BitArray)forbidden.Clone();
                        newForbidden.Or((Graph[x]).Forbidden);

                        // if maxIterator is the first time we are here then
                        // traversed is empty and we initialize the set of
                        // possible extensions to the extension of the first
                        // accepted node in the solution.
                        if (BitArrays.IsEmpty(traversed))
                        {
                            newExtension = (BitArray)((Graph[x]).Extension.Clone());
                        } // else we simply update the set of solution by
                          // including the neighbors of the newly accepted node
                        else
                        {
                            newExtension = (BitArray)extension.Clone();
                            newExtension.Or((Graph[x]).Extension);
                        }

                        // extension my not contain forbidden nodes
                        BitArrays.AndNot(newExtension, newForbidden);

                        // create the new set of traversed node
                        // (update current partial solution)
                        // and add x to the set of forbidden node
                        // (a node may only appear once in a solution)
                        newTraversed = (BitArray)traversed.Clone();
                        newTraversed.Set(x, true);
                        forbidden.Set(x, true);

                        // parse recursively the CDKRGraph
                        ParseRec(newTraversed, newExtension, newForbidden);
                    }
                }
            }
        }
Exemplo n.º 19
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);
        }
Exemplo n.º 20
0
        /// <summary>
        /// Create the topologies (stereo configurations) for the chemical graph. The
        /// topologies define spacial arrangement around atoms.
        /// </summary>
        private void CreateTopologies(CharBuffer buffer)
        {
            // create topologies (stereo configurations)
            foreach (var e in configurations)
            {
                AddTopology(e.Key,
                            Topology.ToExplicit(g, e.Key, e.Value));
            }

            for (int v = BitArrays.NextSetBit(checkDirectionalBonds, 0); v >= 0; v = BitArrays.NextSetBit(checkDirectionalBonds, v + 1))
            {
                int nUpV   = 0;
                int nDownV = 0;
                int nUpW   = 0;
                int nDownW = 0;
                int w      = -1;

                {
                    int d = g.Degree(v);
                    for (int j = 0; j < d; ++j)
                    {
                        Edge e    = g.EdgeAt(v, j);
                        Bond bond = e.GetBond(v);
                        if (bond == Bond.Up)
                        {
                            nUpV++;
                        }
                        else if (bond == Bond.Down)
                        {
                            nDownV++;
                        }
                        else if (bond == Bond.Double)
                        {
                            w = e.Other(v);
                        }
                    }
                }

                if (w < 0)
                {
                    continue;
                }

                BitArrays.EnsureCapacity(checkDirectionalBonds, w + 1);
                checkDirectionalBonds.Set(w, false);

                {
                    int d = g.Degree(w);
                    for (int j = 0; j < d; ++j)
                    {
                        Edge e    = g.EdgeAt(w, j);
                        Bond bond = e.GetBond(w);
                        if (bond == Bond.Up)
                        {
                            nUpW++;
                        }
                        else if (bond == Bond.Down)
                        {
                            nDownW++;
                        }
                    }
                }

                if (nUpV + nDownV == 0 || nUpW + nDownW == 0)
                {
                    continue;
                }

                if (nUpV > 1 || nDownV > 1)
                {
                    int offset1 = -1, offset2 = -1;
                    foreach (var e in g.GetEdges(v))
                    {
                        if (e.Bond.IsDirectional)
                        {
                            if (offset1 < 0)
                            {
                                offset1 = bondStrPos[e];
                            }
                            else
                            {
                                offset2 = bondStrPos[e];
                            }
                        }
                    }
                    var errorPos = InvalidSmilesException.Display(buffer,
                                                                  offset1 - buffer.Length,
                                                                  offset2 - buffer.Length);
                    if (strict)
                    {
                        throw new InvalidSmilesException($"Ignored invalid Cis/Trans specification: {errorPos}");
                    }
                    else
                    {
                        warnings.Add($"Ignored invalid Cis/Trans specification: {errorPos}");
                    }
                }
                if (nUpW > 1 || nDownW > 1)
                {
                    int offset1 = -1;
                    int offset2 = -1;
                    foreach (var e in g.GetEdges(w))
                    {
                        if (e.Bond.IsDirectional)
                        {
                            if (offset1 < 0)
                            {
                                offset1 = bondStrPos[e];
                            }
                            else
                            {
                                offset2 = bondStrPos[e];
                            }
                        }
                    }
                    var errorPos = InvalidSmilesException.Display(buffer,
                                                                  offset1 - buffer.Length,
                                                                  offset2 - buffer.Length);
                    if (strict)
                    {
                        throw new InvalidSmilesException($"Ignored invalid Cis/Trans specification: {errorPos}");
                    }
                    else
                    {
                        warnings.Add($"Ignored invalid Cis/Trans specification: {errorPos}");
                    }
                }
            }
        }