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)); }
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); }