@@ -2466,24 +2466,32 @@ def _ghost_in_cycle(atom_idx, adj):
24662466 Return True if ``atom_idx`` lies on a cycle in the ghost subgraph described
24672467 by ``adj`` (an integer-keyed adjacency dict).
24682468
2469- Removes the atom from the graph and does a BFS from the first neighbour.
2470- If any other neighbour is reachable without passing through the atom,
2471- they form a cycle.
2469+ Removes the atom from the graph and does a BFS from each neighbour in turn.
2470+ If any neighbour can reach another neighbour of the atom without passing
2471+ through the atom itself, they lie on a cycle together.
2472+
2473+ We must try each neighbour as a start rather than only ``neighbors[0]``
2474+ because pendant neighbours (bonded only to ``atom_idx`` within the ghost
2475+ subgraph) cannot reach the cycle members — e.g. a methyl substituent on a
2476+ cyclopropyl carbon would cause a false-negative if picked first.
24722477 """
24732478 neighbors = adj .get (atom_idx , [])
24742479 if len (neighbors ) < 2 :
24752480 return False
24762481
2477- visited = {neighbors [0 ]}
2478- queue = [neighbors [0 ]]
2479- while queue :
2480- node = queue .pop (0 )
2481- for n in adj .get (node , []):
2482- if n != atom_idx and n not in visited :
2483- visited .add (n )
2484- queue .append (n )
2485-
2486- return any (n in visited for n in neighbors [1 :])
2482+ for start in neighbors :
2483+ visited = {start }
2484+ queue = [start ]
2485+ while queue :
2486+ node = queue .pop (0 )
2487+ for n in adj .get (node , []):
2488+ if n != atom_idx and n not in visited :
2489+ visited .add (n )
2490+ queue .append (n )
2491+ if any (n in visited for n in neighbors if n != start ):
2492+ return True
2493+
2494+ return False
24872495
24882496
24892497def _ring_constrained_ghosts (bridges , ghosts , connectivity ):
0 commit comments