Beispiel #1
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);
        }
Beispiel #2
0
        public static int DfsVisit(Graph g, int v, Matching m, BitArray unvisited, bool match)
        {
            unvisited.Set(v, false);
            int nMatched = 0;
            int d        = g.Degree(v);

            while (--d >= 0)
            {
                int w = g.EdgeAt(v, d).Other(v);
                if (unvisited[w])
                {
                    if (match)
                    {
                        m.Match(v, w);
                        return(2 + DfsVisit(g, w, m, unvisited, false));
                    }
                    else
                    {
                        nMatched += DfsVisit(g, w, m, unvisited, true);
                    }
                }
            }
            return(nMatched);
        }
Beispiel #3
0
        // invariant, m is a perfect matching
        private static Graph CopyAndAssign(Graph delocalised, BitArray subset, BitArray aromatic, Matching m)
        {
            Graph localised = new Graph(delocalised.Order);

            localised.SetFlags(delocalised.GetFlags() & ~Graph.HAS_AROM);
            for (int u = 0; u < delocalised.Order; u++)
            {
                localised.AddAtom(delocalised.GetAtom(u).AsAliphaticForm());
                localised.AddTopology(delocalised.TopologyOf(u));
                int d = delocalised.Degree(u);
                for (int j = 0; j < d; ++j)
                {
                    Edge e = delocalised.EdgeAt(u, j);
                    int  v = e.Other(u);
                    if (v < u)
                    {
                        var aa = e.Bond;
                        if (aa == Bond.Single)
                        {
                            if (aromatic[u] && aromatic[v])
                            {
                                localised.AddEdge(Bond.Single.CreateEdge(u, v));
                            }
                            else
                            {
                                localised.AddEdge(Bond.Implicit.CreateEdge(u, v));
                            }
                        }
                        else if (aa == Bond.Aromatic)
                        {
                            if (subset[u] && m.Other(u) == v)
                            {
                                localised.AddEdge(Bond.DoubleAromatic.CreateEdge(u, v));
                            }
                            else if (aromatic[u] && aromatic[v])
                            {
                                localised.AddEdge(Bond.ImplicitAromatic.CreateEdge(u, v));
                            }
                            else
                            {
                                localised.AddEdge(Bond.Implicit.CreateEdge(u, v));
                            }
                        }
                        else if (aa == Bond.Implicit)
                        {
                            if (subset[u] && m.Other(u) == v)
                            {
                                localised.AddEdge(Bond.DoubleAromatic.CreateEdge(u, v));
                            }
                            else if (aromatic[u] && aromatic[v])
                            {
                                localised.AddEdge(Bond.ImplicitAromatic.CreateEdge(u, v));
                            }
                            else
                            {
                                localised.AddEdge(e);
                            }
                        }
                        else
                        {
                            localised.AddEdge(e);
                        }
                    }
                }
            }
            return(localised);
        }
Beispiel #4
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);
        }
Beispiel #5
0
        [TestMethod()] public void IsEmptyTest()
        {
            Matching matching = Matching.CreateEmpty(Graph.FromSmiles("CCCCC"));

            Assert.AreEqual(0, matching.GetMatches().Count());
        }
Beispiel #6
0
        public static int FindPath(Graph g, int v, int end, BitArray unvisited, int[] path, int len, Matching m, bool matchNeeded)
        {
            unvisited.Set(v, false);
            path[len++] = v;
            int l;
            int d = g.Degree(v);

            for (int j = 0; j < d; ++j)
            {
                Edge e = g.EdgeAt(v, j);
                // explicit single bond can not be augmented along!!
                if (e.Bond == Bond.Single)
                {
                    continue;
                }
                int w = e.Other(v);
                if (unvisited[w])
                {
                    if (w == end)
                    {
                        path[len] = w;
                        len++;
                        unvisited.Set(v, true);
                        // odd length path no good
                        return(((len & 0x1) == 1) ? 0 : len);
                    }
                    else if ((m.Other(w) == v) == matchNeeded)
                    {
                        if ((l = FindPath(g, w, end, unvisited, path, len, m, !matchNeeded)) > 0)
                        {
                            unvisited.Set(v, true);
                            return(l);
                        }
                    }
                }
            }
            unvisited.Set(v, true);
            return(0);
        }
Beispiel #7
0
 /// <summary>
 /// Utility to maximise an existing matching of the provided graph.
 /// </summary>
 /// <param name="g">a graph</param>
 /// <param name="m">matching on the graph</param>
 /// <param name="n"></param>
 /// <returns>the maximal matching on the graph</returns>
 public static int Maximise(Graph g, Matching m, int n)
 {
     return(Maximise(g, m, n, IntSet.Universe));
 }
Beispiel #8
0
        /// <summary>
        /// Utility to maximise an existing matching of the provided graph.
        /// </summary>
        /// <param name="g">a graph</param>
        /// <param name="m">matching on the graph, will me modified</param>
        /// <param name="n">current matching cardinality</param>
        /// <param name="s">subset of vertices to match</param>
        /// <returns>the maximal matching on the graph</returns>
        public static int Maximise(Graph g, Matching m, int n, IntSet s)
        {
            MaximumMatching mm = new MaximumMatching(g, m, n, s);

            return(mm.nMatched);
        }