예제 #1
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);
 }
예제 #2
0
        [TestMethod()] public void Adjusted_other()
        {
            Matching matching = Matching.CreateEmpty(Graph.FromSmiles("CCCCC"));

            matching.Match(0, 1);
            matching.Match(2, 3);
            matching.Match(1, 2); // 0-1 and 2-3 should not be

            Assert.AreEqual(matching.Other(1), 2);
            Assert.AreEqual(matching.Other(2), 1);
        }
예제 #3
0
        public void Adjusted_other_invalid()
        {
            Matching matching = Matching.CreateEmpty(Graph.FromSmiles("CCCCC"));

            matching.Match(0, 1);
            matching.Match(2, 3);
            matching.Match(1, 2); // 0-1 and 2-3 should not be

            matching.Other(0);
        }
예제 #4
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);
        }
예제 #5
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);
        }
예제 #6
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);
        }
예제 #7
0
        /// <summary>
        /// Find an augmenting path an alternate it's matching. If an augmenting path
        /// was found then the search must be restarted. If a blossom was detected
        /// the blossom is contracted and the search continues.
        /// </summary>
        /// <returns>an augmenting path was found</returns>
        private bool Augment()
        {
            // reset data structures
            Arrays.Fill(even, nil);
            Arrays.Fill(odd, nil);
            uf.Clear();
            bridges.Clear();
            queue.Clear();

            // queue every unmatched vertex and place in the
            // even level (level = 0)
            for (int v = 0; v < graph.Order; v++)
            {
                if (subset.Contains(v) && matching.Unmatched(v))
                {
                    even[v] = v;
                    queue.Enqueue(v);
                }
            }

            // for each 'free' vertex, start a bfs search
            while (!queue.IsEmpty())
            {
                int v = queue.Poll();

                int d = graph.Degree(v);
                for (int j = 0; j < d; ++j)
                {
                    Edge e = graph.EdgeAt(v, j);
                    if (e.Bond == Bond.Single)
                    {
                        continue;
                    }
                    int w = e.Other(v);

                    if (!subset.Contains(w))
                    {
                        continue;
                    }

                    // the endpoints of the edge are both at even levels in the
                    // forest - this means it is either an augmenting path or
                    // a blossom
                    if (even[uf.Find(w)] != nil)
                    {
                        if (Check(v, w))
                        {
                            return(true);
                        }
                    }

                    // add the edge to the forest if is not already and extend
                    // the tree with this matched edge
                    else if (odd[w] == nil)
                    {
                        odd[w] = v;
                        int u = matching.Other(w);
                        // add the matched edge (potential though a blossom) if it
                        // isn't in the forest already
                        if (even[uf.Find(u)] == nil)
                        {
                            even[u] = w;
                            queue.Enqueue(u);
                        }
                    }
                }
            }

            // no augmenting paths, matching is maximum
            return(false);
        }