orthonym.rules.p44_scorer#

Note

Internal API. Names and behaviour may change between releases.

: unified Blue Book parent-structure scorer.

ONE deterministic comparator over a POOLED ring+chain candidate list, replacing the staged class-specific select_parent cascade (the root-cause coverage gap: staged branches + fail-open default-to-ring).

Rule grounding (the Blue Book Blue Book, verified 2026-07-19): - (~18850): max count of principal characteristic group as suffix. - (18917): class order N>P>As>Sb>Bi>Si>Ge>Sn>Pb>B>Al>Ga>In>Tl>

O>S>Se>Te>C; chooses between rings and chains, NOT among rings/’a’-chains.

  • (1) (19340): same class -> ring senior to chain, regardless of hydrogenation (heptylbenzene PIN) or chain length (BB 35011: 2-(7-oxoheptyl)cyclopentane-1-carbaldehyde PIN, ring 5 beats chain 7 on a PG tie).

  • (19408): among rings (a) heterocycle (b) has-N (c) earliest heteroatom F>Cl>Br>I>O>S>Se>Te>P>… (d) more rings (e) more skeletal atoms (f) more heteroatoms (g) more of the earliest heteroatom.

  • (20926): among chains (a) more skeletal heteroatoms (b) more skeletal atoms (c) more of the senior heteroatom O>S>Se>Te>N>P>…

  • (21016): shared tiebreaks (a) multiple bonds (b) double bonds (h) lower suffix locants (j) lower ene/yne locants; mancude rings count as noncumulative double bonds.

-: chain skeletal-replacement nomenclature admitted at >= 4

bridging hetero units (candidate ADMISSION gate, not a comparison rule).

Expressibility principle (class rank + hetero criteria): a chain heteroatom only counts as SKELETON when the name can express it as such – a pure non-carbon hydride chain (silane, phosphane, hydrazine: or a

replacement-admissible mixed chain. Below that, a mixed C/het chain

is a carbon parent with functionalized bridges (a phase semantics) and ranks as carbon. Principal-group match atoms are suffix, never skeleton.

class orthonym.rules.p44_scorer.ParentCandidate(kind, atoms, pg_count)#

Bases: object

One pooled parent-structure candidate.

kind: ‘ring’ | ‘chain’. atoms: ring -> sorted ring-system atom indices; chain -> chain order. pg_count: count of principal-characteristic-group instances

expressible as suffix on THIS candidate.

kind: str#
atoms: Tuple[int, ...]#
pg_count: int#
orthonym.rules.p44_scorer.pool_candidates(mol, ring_systems, principal_chain, principal_group, principal_group_atoms)#

Pool ALL admissible ring + chain parent candidates.

Admission gates (these are NOT seniority rules - they decide which skeletons are legal parents at all): - every connected ring system is a candidate; - the carbon principal chain (if any) is a candidate; - a longer PG-bearing skeletal hetero chain is admitted ONLY in the

tied-PG context (PG on BOTH the ring system and the carbon principal chain) with a bridging heteroatom - exactly the branch where the legacy staged cascade considered it (a phase / (b)). Outside that context the skeletal chain must not displace the carbon-chain parent (e.g. the secondary-amine C-N-C shape);

  • with no principal group, a longer skeletal chain is admitted at >= 4 bridging hetero units replacement admission).

orthonym.rules.p44_scorer.compare_with_reason(mol, a, b, *, principal_group=None, principal_group_atoms=None, ring_info=None)#

Blue Book seniority with the deciding criterion.

Returns (sign, label): sign >0 a senior, <0 b senior, 0 tie; label names the rule that decided.

orthonym.rules.p44_scorer.compare_parent_candidates(mol, a, b, *, principal_group=None, principal_group_atoms=None, ring_info=None)#

Blue Book seniority: >0 a senior, <0 b senior, 0 tie.

orthonym.rules.p44_scorer.select_parent_unified(mol, ring_systems, principal_chain, principal_group, principal_group_atoms, ring_info=None, _offer_rank=0)#

Drop-in unified replacement for parent_selection.select_parent.

Pre-empts (admission/priority rules) are preserved from the staged implementation; everything else is ONE pooled comparator sort.

(offer-not-return, a project rule): _offer_rank selects WHICH

member of the -ranked pool becomes the parent. _offer_rank == 0 (the default at every normal call site) commits to ranked[0] — byte-identical to the pre-SP1.3 behaviour for every molecule. A best-effort retry may pass _offer_rank == k to force the k-th-ranked candidate ONLY after ranked[0] has already abstained; the ranking is NEVER reordered and an out-of-range rank clamps back to ranked[0]. Every returned result carries parent_pool_size so the caller can bound its retry.