Exemplo n.º 1
0
        /// <summary>
        /// Permute the vertices of a graph using a given permutation.
        /// </summary>
        /// <example>
        /// <code>
        /// g = CNCO
        /// h = g.Permuate(new int[]{1, 0, 3, 2});
        /// h = NCOC
        /// </code>
        /// </example>
        /// <param name="p">a permutation mapping indicate the new index of each atom</param>
        /// <returns>a new chemical graph with the vertices permuted by the given Ordering</returns>
        public Graph Permute(int[] p)
        {
            if (p.Length != order)
            {
                throw new ArgumentException("permuation size should equal |V| (Order)");
            }

            Graph cpy = new Graph(order)
            {
                flags = flags,
                order = order,
                size  = size
            };

            for (int u = 0; u < order; u++)
            {
                int d = degrees[u];
                // v is the image of u in the permutation
                int v = p[u];
                if (d > 4)
                {
                    cpy.edges[v] = new Edge[d];
                }
                cpy.atoms[v]    = atoms[u];
                cpy.valences[v] = valences[u];
                cpy.AddTopology(TopologyOf(u).Transform(p));
                while (--d >= 0)
                {
                    Edge e = EdgeAt(u, d);

                    // important this is the second time we have seen the edge
                    // so the capacity must have been allocated. otherwise we
                    // would get an index out of bounds
                    if (u > e.Other(u))
                    {
                        // w is the image of vertex adjacen to u
                        int  w = p[e.Other(u)];
                        Edge f = new Edge(v, w, e.GetBond(u));
                        cpy.edges[v][cpy.degrees[v]++] = f;
                        cpy.edges[w][cpy.degrees[w]++] = f;
                        cpy.size++;
                    }
                }
            }

            // ensure edges are in sorted order
            return(cpy.Sort(new CanOrderFirst()));
        }
Exemplo n.º 2
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.º 3
0
        private static bool IsRedundantDirectionalEdge(Graph g, Edge edge, BitArray unspecified)
        {
            if (!edge.Bond.IsDirectional)
            {
                return(false);
            }
            int u = edge.Either();
            int v = edge.Other(u);

            if (!unspecified[u])
            {
                foreach (Edge f in g.GetEdges(u))
                {
                    if (f.Bond.IsDirectional && edge != f)
                    {
                        return(true);
                    }
                }
            }
            else if (!unspecified[v])
            {
                foreach (Edge f in g.GetEdges(v))
                {
                    if (f.Bond.IsDirectional && edge != f)
                    {
                        return(true);
                    }
                }
            }
            return(false);
        }
            private void Flip(Graph g, Edge e, BitArray dbAtoms)
            {
                var u = e.Either();
                var v = e.Other(u);

                if (ordering[u] < ordering[v])
                {
                    var first = FirstDirectionalLabel(g, u);
                    if (first != null)
                    {
                        Flip(first, u, dbAtoms);
                    }
                    else
                    {
                        first = FirstDirectionalLabel(g, v);
                        Flip(first, v, dbAtoms);
                    }
                }
                else
                {
                    var first = FirstDirectionalLabel(g, v);
                    if (first != null)
                    {
                        Flip(first, v, dbAtoms);
                    }
                    else
                    {
                        first = FirstDirectionalLabel(g, u);
                        Flip(first, u, dbAtoms);
                    }
                }
            }
 private void Flip(Edge first, int u, BitArray dbAtoms)
 {
     if (ordering[first.Other(u)] < ordering[u])
     {
         if (first.GetBond(u) == Bond.Up)
         {
             InvertExistingDirectionalLabels(g,
                                             new BitArray(g.Order),
                                             acc,
                                             dbAtoms,
                                             u);
         }
     }
     else
     {
         if (first.GetBond(u) == Bond.Down)
         {
             InvertExistingDirectionalLabels(g,
                                             new BitArray(g.Order),
                                             acc,
                                             dbAtoms,
                                             u);
         }
     }
 }
Exemplo n.º 6
0
        internal static bool InSmallRing(Graph g, int v, int prev, int t, int d, BitArray visit)
        {
            if (d > 7)
            {
                return(false);
            }
            if (v == t)
            {
                return(true);
            }
            if (visit[v])
            {
                return(false);
            }
            visit.Set(v, true);
            int deg = g.Degree(v);

            for (int j = 0; j < deg; ++j)
            {
                Edge e = g.EdgeAt(v, j);
                int  w = e.Other(v);
                if (w == prev)
                {
                    continue;
                }
                if (InSmallRing(g, w, v, t, d + 1, visit))
                {
                    return(true);
                }
            }
            return(false);
        }
            private static bool HasAdjDirectionalLabels(Graph g, Edge e)
            {
                int u = e.Either();
                int v = e.Other(u);

                return(HasAdjDirectionalLabels(g, u) && HasAdjDirectionalLabels(g, v));
            }
Exemplo n.º 8
0
        /// <summary>
        /// First traversal of the molecule assigns ring bonds (numbered later) and
        /// configures topologies.
        /// </summary>
        /// <param name="u">the vertex to visit</param>
        /// <param name="p">the atom we came from</param>
        void Prepare(int u, int p)
        {
            visitedAt[u]    = nVisit++;
            tokens[u]       = g.GetAtom(u).Token;
            tokens[u].Graph = g;
            tokens[u].Index = u;

            int d = g.Degree(u);

            for (int j = 0; j < d; ++j)
            {
                Edge e = g.EdgeAt(u, j);
                int  v = e.Other(u);
                if (visitedAt[v] < 0)
                {
                    Prepare(v, u);
                }
                else if (v != p && visitedAt[v] < visitedAt[u])
                {
                    CyclicEdge(v, u, e.GetBond(v));
                }
            }

            PrepareStereochemistry(u, p);
        }
Exemplo n.º 9
0
        /// <summary>
        /// Second traversal writes the bonds and atoms to the SMILES string.
        /// </summary>
        /// <param name="u">a vertex</param>
        /// <param name="p">previous vertex</param>
        /// <param name="b">the bond from the previous vertex to this vertex</param>
        public void Write(int u, int p, Bond b)
        {
            visitedAt[u] = nVisit++;

            int remaining = g.Degree(u);

            if (u != p)
            {
                remaining--;
            }

            // assign ring numbers
            if (rings.TryGetValue(u, out IList <RingClosure> closures))
            {
                foreach (var rc in closures)
                {
                    // as we are composing tokens, make sure apply in reverse
                    int rnum = rnums.Next();
                    if (rc.Register(rnum))
                    {
                        int v = rc.Other(u);
                        tokens[u] = new RingNumberToken(new RingBondToken(tokens[u],
                                                                          rc.GetBond(u)),
                                                        rnum);
                        rnums.Use(rnum);
                    }
                    else
                    {
                        tokens[u] = new RingNumberToken(tokens[u],
                                                        rc.RNum);
                        rnums.Free(rc.RNum);
                    }
                    remaining--;
                }
            }

            sb.Append(b.Token);
            tokens[u].Append(sb);

            int d = g.Degree(u);

            for (int j = 0; j < d; ++j)
            {
                Edge e = g.EdgeAt(u, j);
                int  v = e.Other(u);
                if (visitedAt[v] < 0)
                {
                    if (--remaining > 0)
                    {
                        sb.Append('(');
                        Write(v, u, e.GetBond(u));
                        sb.Append(')');
                    }
                    else
                    {
                        Write(v, u, e.GetBond(u));
                    }
                }
            }
        }
Exemplo n.º 10
0
        private static bool HasAdjDirectionalLabels(Graph g, Edge e, BitArray cyclic)
        {
            int u = e.Either();
            int v = e.Other(u);

            return(HasAdjDirectionalLabels(g, u, cyclic) && HasAdjDirectionalLabels(g, v, cyclic));
        }
Exemplo n.º 11
0
        /// <summary>
        /// Copy constructor.
        /// </summary>
        /// <param name="org">original graph</param>
        Graph(Graph org)
        {
            this.order      = org.order;
            this.size       = org.size;
            this.flags      = org.flags;
            this.atoms      = Arrays.CopyOf(org.atoms, order);
            this.valences   = Arrays.CopyOf(org.valences, order);
            this.degrees    = new int[order];
            this.edges      = new Edge[order][];
            this.topologies = Arrays.CopyOf(org.topologies, org.topologies.Length);

            for (int u = 0; u < order; u++)
            {
                int deg = org.degrees[u];
                this.edges[u] = new Edge[deg];
                for (int j = 0; j < deg; ++j)
                {
                    Edge e = org.edges[u][j];
                    int  v = e.Other(u);
                    // important - we have made use edges are allocated
                    if (u > v)
                    {
                        Edge f = new Edge(e);
                        edges[u][degrees[u]++] = f;
                        edges[v][degrees[v]++] = f;
                    }
                }
            }
        }
Exemplo n.º 12
0
        private int Visit(int u, Edge from)
        {
            depth[u] = ++count;
            int d  = g.Degree(u);
            int lo = count + 1;

            while (--d >= 0)
            {
                Edge e = g.EdgeAt(u, d);
                if (e == from)
                {
                    continue;
                }
                int v = e.Other(u);
                if (depth[v] == 0)
                {
                    int res = Visit(v, e);
                    if (res < lo)
                    {
                        lo = res;
                    }
                }
                else if (depth[v] < lo)
                {
                    lo = depth[v];
                }
            }
            if (lo <= depth[u])
            {
                cyclic.Set(u, true);
            }
            return(lo);
        }
Exemplo n.º 13
0
        /// <summary>
        /// Replace an edge in the graph.
        /// </summary>
        /// <param name="org">the original edge</param>
        /// <param name="rep">the replacement</param>
        internal void Replace(Edge org, Edge rep)
        {
            int u = org.Either();
            int v = org.Other(u);

            for (int i = 0; i < degrees[u]; i++)
            {
                if (edges[u][i] == org)
                {
                    edges[u][i] = rep;
                }
            }

            for (int i = 0; i < degrees[v]; i++)
            {
                if (edges[v][i] == org)
                {
                    edges[v][i] = rep;
                }
            }

            int ord = rep.Bond.Order - org.Bond.Order;

            valences[u] += ord;
            valences[v] += ord;
        }
Exemplo n.º 14
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.º 15
0
        /// <summary>
        /// Given a double bond edge traverse the neighbors of both endpoints and
        /// accumulate any explicit replacements in the 'acc' accumulator.
        /// </summary>
        /// <param name="g">  the chemical graph</param>
        /// <param name="e">  a edge in the graph </param>('double bond type')
        /// <param name="ordering"></param>
        /// <param name="acc">accumulator for new edges</param>
        /// <exception cref="InvalidSmilesException">thrown if the edge could not be converted</exception>
        private static void RemoveRedundant(Graph g,
                                            Edge e,
                                            int[] ordering,
                                            Dictionary <Edge, Edge> acc)
        {
            int u = e.Either(), v = e.Other(u);

            ReplaceImplWithExpl(g, e, u, ordering, acc);
            ReplaceImplWithExpl(g, e, v, ordering, acc);
        }
Exemplo n.º 16
0
        /// <summary>
        /// Given a double bond edge traverse the neighbors of both endpoints and
        /// accumulate any explicit replacements in the <paramref name="e"/> accumulator.
        /// </summary>
        /// <param name="g">  the chemical graph</param>
        /// <param name="e">  a edge in the graph </param>('double bond type')
        /// <param name="acc">accumulator for new edges</param>
        /// <exception cref="InvalidSmilesException">thrown if the edge could not be converted</exception>
        private bool ReplaceImplWithExpl(Graph g,
                                         Edge e,
                                         Dictionary <Edge, Edge> acc)
        {
            int u = e.Either(), v = e.Other(u);

            bool uDone = ReplaceImplWithExpl(g, e, u, acc);
            bool vDone = ReplaceImplWithExpl(g, e, v, acc);

            return(uDone || vDone);
        }
Exemplo n.º 17
0
        /// <summary>
        /// Add an labelled edge to the graph.
        /// </summary>
        /// <param name="e">new edge</param>
        public void AddEdge(Edge e)
        {
            int u = e.Either(), v = e.Other(u);

            EnsureEdgeCapacity(u);
            EnsureEdgeCapacity(v);
            edges[u][degrees[u]++] = e;
            edges[v][degrees[v]++] = e;
            int ord = e.Bond.Order;

            valences[u] += ord;
            valences[v] += ord;
            size++;
        }
Exemplo n.º 18
0
        /// <summary>
        /// Access the edge connecting two adjacent vertices.
        /// </summary>
        /// <param name="u">a vertex</param>
        /// <param name="v">another vertex </param>(adjacent to u)
        /// <returns>the edge connected u and v</returns>
        /// <exception cref="ArgumentException">u and v are not adjacent</exception>
        public Edge CreateEdge(int u, int v)
        {
            int d = degrees[u];

            for (int j = 0; j < d; ++j)
            {
                Edge e = edges[u][j];
                if (e.Other(u) == v)
                {
                    return(e);
                }
            }
            throw new ArgumentException(u + ", " + v + " are not adjacent");
        }
Exemplo n.º 19
0
        private void SetAllenalStereo(Graph g, int[] visitedAt, int u)
        {
            Trace.Assert(g.Degree(u) == 2);
            Edge a = g.EdgeAt(u, 0);
            Edge b = g.EdgeAt(u, 1);

            Trace.Assert(a.Bond == Bond.Double &&
                         b.Bond == Bond.Double);

            int aAtom = a.Other(u);
            int bAtom = b.Other(u);

            if (!rings.ContainsKey(aAtom) && !rings.ContainsKey(bAtom))
            {
                // no rings on either end, this is simply the order we visited the
                // atoms in
                tokens[u].Configure(g.TopologyOf(u).ConfigurationOf(visitedAt));
            }
            else
            {
                // hokay this case is harder... this makes me wince but BEAM v2
                // has a much better way of handling this

                // we can be clever here rollback any changes we make (see the
                // tetrahedral handling) however since this is a very rare
                // operation it much simpler to copy the array
                int[] tmp = Arrays.CopyOf(visitedAt, visitedAt.Length);

                if (visitedAt[aAtom] > visitedAt[bAtom])
                {
                    int swap = aAtom;
                    aAtom = bAtom;
                    bAtom = swap;
                }

                Trace.Assert(!rings.ContainsKey(aAtom) || rings[aAtom].Count == 1);
                Trace.Assert(!rings.ContainsKey(bAtom) || rings[bAtom].Count == 1);

                if (rings.ContainsKey(aAtom))
                {
                    tmp[rings[aAtom][0].Other(aAtom)] = visitedAt[aAtom];
                }
                if (rings.ContainsKey(bAtom))
                {
                    tmp[rings[bAtom][0].Other(bAtom)] = visitedAt[bAtom];
                }

                tokens[u].Configure(g.TopologyOf(u).ConfigurationOf(tmp));
            }
        }
Exemplo n.º 20
0
        /// <summary>
        /// Determine if the vertices '<paramref name="u"/>' and '<paramref name="v"/>' are adjacent and there is an edge
        /// which connects them.
        /// </summary>
        /// <param name="u">a vertex</param>
        /// <param name="v">another vertex</param>
        /// <returns>whether they are adjacent</returns>
        public bool Adjacent(int u, int v)
        {
            int d = degrees[u];

            for (int j = 0; j < d; ++j)
            {
                Edge e = edges[u][j];
                if (e.Other(u) == v)
                {
                    return(true);
                }
            }
            return(false);
        }
Exemplo n.º 21
0
        private static bool HasAdjDirectionalLabels(Graph g, int u, BitArray cyclic)
        {
            int d = g.Degree(u);

            for (int j = 0; j < d; ++j)
            {
                Edge f = g.EdgeAt(u, j);
                int  v = f.Other(u);
                if (f.Bond.IsDirectional && cyclic[v])
                {
                    return(true);
                }
            }
            return(false);
        }
Exemplo n.º 22
0
 /// <summary>
 /// Create the current local arrangement for vertex 'u' - if the arrangment
 /// already exists then that arrangement is used.
 /// </summary>
 /// <param name="u">vertex to get the arrangement around</param>
 /// <returns>current local arrangement</returns>
 private LocalArrangement CreateArrangement(int u)
 {
     if (!arrangement.TryGetValue(u, out LocalArrangement la))
     {
         la = new LocalArrangement();
         int d = g.Degree(u);
         for (int j = 0; j < d; ++j)
         {
             Edge e = g.EdgeAt(u, j);
             la.Add(e.Other(u));
         }
         arrangement[u] = la;
     }
     return(la);
 }
Exemplo n.º 23
0
            Edge FirstDirectionalLabel(Graph g, int u)
            {
                Edge first = null;

                foreach (var f in g.GetEdges(u))
                {
                    if (f.Bond == Bond.Up || f.Bond == Bond.Down)
                    {
                        if (first == null || ordering[f.Other(u)] < ordering[first.Other(u)])
                        {
                            first = f;
                        }
                    }
                }
                return(first);
            }
Exemplo n.º 24
0
        private int VisitWithComp(int u, Edge from)
        {
            depth[u] = ++count;
            int j  = g.Degree(u);
            int lo = count + 1;

            while (--j >= 0)
            {
                Edge e = g.EdgeAt(u, j);
                if (e == from)
                {
                    continue;
                }

                int v = e.Other(u);
                if (depth[v] == 0)
                {
                    stack[nstack] = e;
                    ++nstack;
                    int tmp = VisitWithComp(v, e);
                    if (tmp == depth[u])
                    {
                        StoreWithComp(e);
                    }
                    else if (tmp > depth[u])
                    {
                        --nstack;
                    }
                    if (tmp < lo)
                    {
                        lo = tmp;
                    }
                }
                else if (depth[v] < depth[u])
                {
                    // back edge
                    stack[nstack] = e;
                    ++nstack;
                    if (depth[v] < lo)
                    {
                        lo = depth[v];
                    }
                }
            }
            return(lo);
        }
Exemplo n.º 25
0
        /// <summary>
        /// Add an edge to the graph.
        /// </summary>
        /// <param name="e">the edge to add</param>
        /// <returns>graph builder for adding more atoms/connections</returns>
        public GraphBuilder Add(Edge e)
        {
            Bond b = e.Bond;
            int  u = e.Either();
            int  v = e.Other(u);

            if (b == Bond.Single && (!g.GetAtom(u).IsAromatic() || !g.GetAtom(v).IsAromatic()))
            {
                e.SetBond(Bond.Implicit);
            }
            else if (b == Bond.Aromatic && g.GetAtom(u).IsAromatic() && g.GetAtom(v).IsAromatic())
            {
                e.SetBond(Bond.Implicit);
            }
            g.AddEdge(e);
            valence[u] += b.Order;
            valence[v] += b.Order;
            return(this);
        }
Exemplo n.º 26
0
            public bool Less(Graph g, int u, Edge e, Edge f)
            {
                int v = e.Other(u);
                int w = f.Other(u);

                Element vElem = g.GetAtom(v).Element;
                Element wElem = g.GetAtom(w).Element;

                if (vElem == Hydrogen && wElem != Hydrogen)
                {
                    return(true);
                }
                if (vElem != Hydrogen && wElem == Hydrogen)
                {
                    return(false);
                }

                // sort hydrogens by isotope
                return(vElem == Hydrogen && g.GetAtom(v).Isotope < g.GetAtom(w).Isotope);
            }
Exemplo n.º 27
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);
        }
Exemplo n.º 28
0
        /// <summary>
        /// Given a double bond edge traverse the neighbors of one of the endpoints
        /// and accumulate any explicit replacements in the 'acc' accumulator.
        /// </summary>
        /// <param name="g">  the chemical graph</param>
        /// <param name="e">  a edge in the graph </param>('double bond type')
        /// <param name="u">  a endpoint of the edge 'e'</param>
        /// <param name="ordering"></param>
        /// <param name="acc">accumulator for new edges</param>
        /// <exception cref="InvalidSmilesException">thrown if the edge could not be converted</exception>
        private static void ReplaceImplWithExpl(Graph g,
                                                Edge e,
                                                int u,
                                                int[] ordering,
                                                Dictionary <Edge, Edge> acc)
        {
            ICollection <Edge> edges = new SortedSet <Edge>(new S(e, u, ordering));

            foreach (var f in g.GetEdges(u))
            {
                var aa = f.Bond;
                if (aa == Bond.Double)
                {
                    if (!f.Equals(e))
                    {
                        return;
                    }
                }
                else if (aa == Bond.Up || aa == Bond.Down)
                {
                    edges.Add(f);
                }
            }

            if (edges.Count == 2)
            {
                Edge explicit_ = edges.First();
                int  v         = explicit_.Either();
                int  w         = explicit_.Other(v);
                acc[explicit_] = new Edge(v, w, Bond.Implicit);
            }
            else if (edges.Count > 2)
            {
                throw new InvalidSmilesException("Too many up/down bonds on double bonded atom");
            }
        }
Exemplo n.º 29
0
 public bool Less(Graph g, int u, Edge e, Edge f)
 {
     return(e.Other(u) < f.Other(u));
 }
Exemplo n.º 30
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);
        }