Migration guide: see docs/user_guide/migration.rst.
Priority rules concept page: see docs/methods/priority_rules.rst.
⚠️ Backwards-incompatible
apply_reaction_ruledefaulttop_reactions_numraised from 3 → 5;
pin the old behaviour withapply_reaction_rule(..., top_reactions_num=3).- Per-node state moved from nine
Tree.nodes_*parallel dicts onto
Nodeattributes (e.g.tree.nodes_depth[nid]→tree.nodes[nid].depth).
Old reads raiseAttributeErrorwith a migration hint. Tree.statsis now aTreeStatsdataclass — use attribute access,
not subscript or.get().Tree.to_stats_dict()is unchanged.EvaluationStrategy.evaluate_nodesignature collapses
(node, node_id, nodes_depth, nodes_prob)into
(node, node_id, nodes: dict[int, Node]).- Pickled
Treeinstances from 1.4.x partially fail on the migrated
surfaces (tree.stats.*, newNodeprovenance fields). Re-run the
search to recover full functionality. - YAML
key:(null) for nested standardization / filtering configs now
enables the step with defaults instead of silently disabling it. To
disable, omit the key entirely. ReactorConfigno longer exposesfix_aromatic_ringsor
fix_tautomers.CanonicalRetroReactoralways forces
fix_aromatic_rings=Falseand runs the inline kekule + thiele +
tautomer-fix pipeline in its_patcher; tautomer fixing inside
that inline call relies on chython's defaultfix_tautomers=True.load_reaction_rulesnow defaults tocheck_atom_mapping="reject_unmapped":
SMARTS rules without atom maps are rejected with an error naming the
offending TSV row. Passcheck_atom_mapping="off"to restore the old
behaviour.
Added
-
Atom-mapping validator wired into the reader chokepoint
(synplan.utils.files.parse_reaction) and the SMARTS rule loader
(synplan.utils.loading.load_reaction_rules), with helpers in
synplan.chem.utils:
reaction_mapping_status,reaction_string_mapping_status,
is_reaction_atom_mapped,assert_reaction_atom_mapped, and the
AtomMappingCheckliteral type ("off" | "reject_unmapped" | "reject_partial").
Tagged reactions getmeta["mapping_status"]for downstream routing. -
Priority-rule support for MCTS expansion: a mapping of named SMARTS
rule sets passed toTree(..., priority_rules={"ugi": ..., ...}),
tried ahead of the learned policy on every node. Each set gets its
own counter pair intree.stats.per_priority_source[<name>].
Reserved name"policy"is rejected;use_priority=Truewithout
priority_rulesraises. -
Optional iterated rule application via
TreeConfig.priority_rule_multiapplicationand the new
apply_reaction_rule(multirule=True, rm_dup=True)kwargs — useful
for stripping every protective group of a given kind in one step. -
Source-specific rule counters in
tree.stats/
tree.to_stats_dict():policy_rules_tried/succeeded,
priority_rules_tried/succeeded(aggregate), and the per-set
per_priority_source[<set_name>]breakdown. -
Rule provenance on tree nodes and route outputs:
rule_source,
collision-saferule_key(formatted as<source>:<id>), and exact
1-indexedpolicy_rank. -
Route SVG labels for rule keys and policy ranks, opt-in
partial-route rendering withallow_unsolved, and JSON-route SVG
rendering that can display stored rule metadata. -
Tutorial 13 for the priority-rule workflow.
-
reactor_validationknob onRuleExtractionConfig(defaultTrue): skip
rules whose reactor cannot reconstruct the original products. The flag is
tagged on each rule and counted in the extraction summary. -
single_product_only,ignore_stereo, andworker_timeout_per_reaction
exposed onRuleExtractionConfigandconfigs/rules_extraction.yaml.
Changed
- Bumped
chython-synplanfloor to>=1.95, which carries upstream fixes
for: multi-component query mapping against single-component targets (Bug
#3),[C]uppercase aliphatic strictening against aromatic carbons (Bug
#4), and aromatic snapshot/restore protection in the reactor (Bug #6). - Tree expansion now tracks exact policy Top-N rank from the expansion function
and enforces the configured top-rules limit during rule iteration. - Policy rule selection in
expansion.py:_predict_rules_commonuses
torch.topkinstead of fulltorch.sortover the rule-probability
tensor. Same Top-K output; ~10% per-iter speed-up in MCTS on 17k-rule
rule sets. apply_reaction_rulenow skips computing the canonical-SMILES dedup
key when neitherrm_dupnormultiruleis enabled — a no-op for
performance (chython caches the SMILES anyway) but cleaner control flow.- Route, RDKit, JSON, SVG, and tree-stat exports now carry source-aware rule
metadata through serialized and rendered route outputs. - Multi-product reactions and rules-all-filtered-out are now traceable
through the per-reaction audit TSV (<rules_path_base>.audit.tsv) in
addition to the summary counters.
Fixed
- Winning rule rank reporting now uses stored policy ranks when available instead
of approximating ranks from sibling probabilities. - Route JSON export now attaches rule metadata to the matching retrosynthetic
step order and avoids closure state leakage while building nested route nodes. - Route SVG and RDKit route extraction now derive paths from node IDs, preserving
priority/policy metadata and respectingmin_mol_sizeduring building-block
checks. - Repeated route SVG renders now clear stale molecule labels and statuses before
applying route-specific annotations. - Worked around chython's SMARTS writer emitting CXSMILES extension
blocks (|...|) mid-string between disconnected fragments by
stripping any CXSMILES block before tokenisation in the mapping
validator. - Regression tests now exercise the canonical-key invariant via two
SMILES with different mapping offsets instead of
QueryCGRContainer.remap, which was broken in chython ≤1.94 (its
override forwarded an unsupportedcopy=kwarg toGraph.remap).