yomitoki
Fast, explainable, route-free molecular synthesizability diagnostics.
yomitoki is a fast, explainable, route-free molecular synthesizability diagnostics library built on chematic.
Instead of returning only a synthetic accessibility score, yomitoki reads molecular structure and explains why a molecule appears easy or difficult to synthesize. It identifies the structural evidence behind the assessment and reports how confident that judgment is.
The name comes from the Japanese word yomitoki(読み解き), meaning to carefully examine something and uncover its meaning — that is the library's whole job: not to change the molecule, but to read it and explain what it finds.
yomitoki does not merely estimate synthesizability; it exposes the evidence and reasoning behind the estimate.
Status:
0.1.0-alpha.2is published. All six planned components are implemented, includingfragment_rarity— but it's opt-in: no fragment-frequency corpus ships with yomitoki itself (AGENTS.md §5.4 forbids embedding one directly as a huge binary), so it stays inactive unless you build one (tools/build-fragment-corpus/) and configure it (AnalysisConfig.fragment_model). If you do configure one:fragment_raritywas redesigned (round 17) as a corpus-relative percentile signal, fixing the documented over-penalty on its target cases — aspirin'soverall.difficultymeasures0.273 → 0.095and dodecane's0.068 → 0.000against a real 200k-molecule corpus. It also has a known caveat: some structurally-legitimate molecules (caffeine, bridged/spiro ring systems, stereocenter-dense cores) score harder once a corpus is configured, because ChEMBL is a bioactivity corpus, not a synthesis-focused one — see Limitations for the honest before/after data.fragment_rarityitself is likely to be renamed (fragment_precedent) before a non-alpha0.1.0, since it now argues difficulty both up and down, not just up — "rarity detector" undersells what it does. SeeCHANGELOG.mdfor the full version history. This is a pre-release: the public API may still change before a non-alpha0.1.0. Seedocs/architecture.mdfor the current scope and what's still missing.
Where it sits
chematic Molecular representation and cheminformatics
|
yomitoki Read and explain molecular synthesizability
|
renkin Plan retrosynthetic routes
yomitoki never runs route search — that boundary is permanent, not a v0.1 scoping choice. See "What it does not do" below.
What it does
- Parses a molecule (via
chematic) and returns a structuredSynthesizabilityReport, not a single number. - Breaks the assessment down into independent components (ring topology, size/topology, stereochemical burden, functional-group liabilities, input quality/applicability, and fragment rarity — the last is opt-in, see "Limitations" below).
- Separates score (synthesizability/difficulty), confidence (how reliable the judgment is), and applicability (whether the molecule is even in the model's domain) into distinct fields — a hard-to-make molecule is not automatically a low-confidence one.
- Emits machine-readable finding codes with structured evidence, not just prose.
- Never runs retrosynthesis search. yomitoki evaluates a molecule on its own; it does not plan a route to make it.
- Ships a
yomitokiCLI for single-molecule and batch (.sdf/SMILES-file) analysis — see Command-line interface below. analyze_batch(&[Molecule], &AnalysisConfig) -> Vec<Result<...>>gives library callers the same input-order-preserving batch entry point, without going through the CLI or a file format.
What it does not do
- Retrosynthesis planning, reaction template application, precursor generation, or route ranking — that's RENKIN's job.
- Molecule parsing, ring perception, aromaticity, or stereochemistry assignment — that's chematic's job; yomitoki only consumes it.
- Toxicity, SDS/hazard classification, yield prediction, or cost prediction.
- Full periodic-table or organometallic/polymer coverage in v0.1.
Quick start
use ;
let config = default;
let report = analyze_smiles?; // norbornane
println!;
println!;
println!;
for finding in &report.findings
Run the full example:
Command-line interface
yomitoki analyze "<SMILES>" [--format human|json|jsonl] [--fragment-corpus <dir>]— analyze one molecule from an argument.yomitoki analyze --input <file> [--format human|json|jsonl] [--output <file>] [--fragment-corpus <dir>]— batch mode.<file>may be a.sdffile or a SMILES-per-line file (optionally with a whitespace-separated name column, the standard.smiconvention).- Batch mode preserves input order and never stops on one record's failure —
a failed record becomes an error entry (JSON
"error"field, or anERROR:block in human format), not a skipped one. The process exits non-zero only after every record has been attempted, if any failed. jsonloutput uses the same{"input", "report"|"error"}wrapper shape in both single-molecule and batch mode, so a downstream line-by-line parser sees one schema regardless of which invocation form produced it.- Exit codes:
0success,1a molecule failed to parse/analyze (single mode) or at least one batch record failed,2a usage error (bad arguments). --fragment-corpus <dir>loads atools/build-fragment-corpusoutput directory and enablesfragment_rarityfor the run (loaded once, before any molecule is analyzed). Without it, reports havefragment_rarity: null, same as before this flag existed — no corpus ships with yomitoki itself, see Limitations below.
Report shape
Actual output of cargo run --example basic, current as of this component
set. Norbornane (C1CC2CCC1C2) exercises ring topology, and its bridged
ring produces a simplification suggestion:
Verdict: ModeratelyAccessible
Synthesizability: 0.66
Confidence: 1.00
Dominant penalties:
1. Bridged ring system spanning 7 atoms — bridgehead connectivity typically increases synthetic difficulty.
Simplification suggestions (heuristic, not a guarantee):
1. ReplaceBridgedRingWithMonocyclicAnalog: Bridgehead connectivity in this ring system is a direct driver of the ring_topology contribution to difficulty. A monocyclic (or less-fused) analog, if the target application allows one, would remove this specific burden — this is a structural heuristic, not a guarantee the replacement is chemically equivalent or that synthesis actually becomes easier.
A stereocenter-dense fragment (CC(O)C(N)C(C)C(O)C(N)C) exercises
stereochemical_burden and functional_group_liability (difficulty) plus
applicability's independent confidence penalty for unspecified
stereochemistry — note that difficulty and confidence move separately, not
together:
Verdict: ModeratelyAccessible
Synthesizability: 0.74
Confidence: 0.85
Dominant penalties:
1. 4 tetrahedral stereocenter(s) (specified or unspecified) requiring synthetic control.
2. Stereocenter density 0.33 is above the 0.25 threshold — stereocenters are concentrated in a compact region, leaving little room for staged, orthogonal control.
3. Reactive/unstable functional group detected: primary amine (Brenk et al. 2008 structural alert).
Simplification suggestions (heuristic, not a guarantee):
1. ReduceStereocenterDensity: Stereocenters are concentrated in a compact region, leaving little room for staged, orthogonal stereocontrol. Reducing the number of stereocenters, or spreading them further apart in the structure, would lower this contribution to difficulty — this is a structural heuristic, not a guarantee.
An epoxide (C1CO1) exercises functional_group_liability on its own —
it wraps chematic's Brenk et al. (2008) structural-alert set directly:
Verdict: LikelyAccessible
Synthesizability: 0.87
Confidence: 1.00
Dominant penalties:
1. Reactive/unstable functional group detected: epoxide (Brenk et al. 2008 structural alert).
A 9-membered ring (C1CCCCCCCC1) exercises the macrocycle branch of
ring_topology, and its own simplification suggestion:
Verdict: LikelyAccessible
Synthesizability: 0.75
Confidence: 1.00
Dominant penalties:
1. Macrocyclic ring of 9 atoms (at or above the 9-atom macrocycle threshold).
Simplification suggestions (heuristic, not a guarantee):
1. SimplifyMacrocyclicClosure: Macrocyclic ring closure is a direct driver of the ring_topology contribution to difficulty (large-ring closures often need high-dilution or specialized macrocyclization methods). A smaller ring or acyclic analog, if chemically acceptable, would remove this burden — this is a structural heuristic, not a guarantee.
Pentaerythritol tetraacetate (CC(=O)OCC(COC(C)=O)(COC(C)=O)COC(C)=O) has 4
distinct, non-adjacent ester environments and exercises
functional_group_liability's "dense functionalization" signal
(chematic::chem::identify_functional_groups, Ertl 2017 clustering) on top
of its Brenk alerts:
Verdict: LikelyAccessible
Synthesizability: 0.81
Confidence: 1.00
Dominant penalties:
1. 4 distinct functional-group environments (Ertl 2017 clustering), above the 3 threshold — multiple independent reactive/functional regions can compete for reagent selectivity and complicate protecting-group strategy.
2. Reactive/unstable functional group detected: ketone alpha (Brenk et al. 2008 structural alert).
3. Reactive/unstable functional group detected: acetal ketal (Brenk et al. 2008 structural alert).
Alaninate (C[C@@H](N)C(=O)[O-], deprotonated alanine) has a specified
stereocenter and a negatively charged atom — the latter is a known
chematic bug (#267):
stereo analysis is safely skipped rather than crashing or guessing, and
confidence drops accordingly, distinctly from the ordinary "unspecified
stereocenter" case:
Verdict: LikelyAccessible
Synthesizability: 0.92
Confidence: 0.60
Dominant penalties:
1. Reactive/unstable functional group detected: primary amine (Brenk et al. 2008 structural alert).
2. Reactive/unstable functional group detected: acetal ketal (Brenk et al. 2008 structural alert).
3. Stereo analysis could not be run for this molecule: it contains a negatively charged atom, which triggers an arithmetic-overflow bug in chematic's stereo perception (panics in debug builds, produces an unverified result in release builds — see chematic issue #267). Stereocenter count/density and stereo completeness are unavailable, not verified to be zero/complete.
With no fragment corpus configured (the default — see below), scores overall remain lower than a corpus-backed analysis would produce.
Every report also carries a Provenance block (schema version, yomitoki
version, chematic version, ruleset version, fragment-corpus model version,
config hash) so results are comparable across versions — see
docs/architecture.md.
Component status (v0.1)
| Component | Status |
|---|---|
input_quality / applicability |
implemented |
ring_topology |
implemented |
size_topology |
implemented |
stereochemical_burden |
implemented (tetrahedral centers only — see Limitations) |
functional_group_liability |
implemented (reactive/unstable groups + dense functionalization — see Limitations) |
fragment_rarity |
implemented, opt-in — None unless AnalysisConfig.fragment_model has a corpus configured; corpus-relative percentile signal with a known corpus-domain-bias caveat, see Limitations |
Components stay None in ComponentScores when genuinely not evaluated
(unconfigured fragment_rarity), never as fabricated zero scores.
suggestions: Vec<SimplificationSuggestion> is populated for 4 of its 6
possible codes (ReplaceBridgedRingWithMonocyclicAnalog,
SimplifyMacrocyclicClosure, ReduceStereocenterDensity,
IncreaseFragmentPrecedent) — see Limitations. Every suggestion is
diagnostic-only, heuristic, and never
claims certainty (expected_effect is always MayReduceDifficulty, never
LikelyReducesDifficulty).
How this differs from existing tools
- SAscore returns fragment-frequency and complexity penalties as a single number. yomitoki returns component-wise diagnostics, confidence, applicability, evidence, and simplification suggestions.
- SYBA is an easy/hard classifier. yomitoki is a diagnostic and explanation tool.
- SCScore is a learned synthetic-complexity score. yomitoki decomposes transparent, chemically-named factors instead.
- RAscore approximates retrosynthesis success. yomitoki is route-free and explains the structural reasons behind its assessment.
- AiZynthFinder, ASKCOS, RENKIN are route planners. yomitoki never generates a route.
Comparison with SAscore
A minimum in-process comparison against chematic::chem::sa_score (Ertl &
Schuffenhauer 2009) — the completion criterion in AGENTS.md §27. Not a
calibration or accuracy claim: the two scores aren't fit against each other
and measure different things (SAscore: fragment frequency + complexity
penalty; yomitoki: structural burden, decomposed by component). Scales run
in opposite directions and aren't rescaled onto a shared axis here — SAscore
is 1 (easy) to 10 (hard); yomitoki's difficulty is 0.0 to 1.0.
Real output of cargo run --example sa_score_comparison:
molecule sa_score yomitoki_diff verdict
ethanol 3.45 0.01 LikelyAccessible
benzene 2.40 0.10 LikelyAccessible
norbornane (bridged) 8.20 0.34 ModeratelyAccessible
stereocenter-dense fragment 8.32 0.27 ModeratelyAccessible
epoxide 6.23 0.13 LikelyAccessible
aspirin 4.67 0.27 ModeratelyAccessible
paracetamol 4.56 0.24 LikelyAccessible
caffeine (fused heterocycle) 4.94 0.29 ModeratelyAccessible
acyl halide 6.62 0.09 LikelyAccessible
cyclopropane (strained) 3.94 0.13 LikelyAccessible
nitrile 4.97 0.04 LikelyAccessible
alanine (specified stereocenter) 3.55 0.14 LikelyAccessible
bridged ring + several stereocenters 10.00 0.69 Challenging
spiro ring system 5.52 0.20 LikelyAccessible
The interesting rows are where the two diverge, not where they agree — a
divergence isn't automatically a yomitoki bug. Acyl halide is the sharpest
case: SAscore rates it 6.62 (fragment-uncommon), yomitoki rates it 0.09
(LikelyAccessible) — a small, cheap, extremely common acylating reagent
with essentially no structural burden by yomitoki's own model. Aspirin
(4.67 vs. 0.27) is the same shape as the Brenk-validity gap already
described in Limitations. Where they broadly agree (caffeine, spiro,
bridged-plus-stereo), that's not evidence either one is "correct" — neither
has been validated against real synthesis outcomes yet.
Limitations
- All six planned components are implemented (see table above), but
fragment_rarityonly contributes tooverall.difficulty/overall.synthesizabilitywhen a corpus is configured (AnalysisConfig.fragment_model) — no corpus ships with yomitoki itself (AGENTS.md §5.4). Without one, both fields reflect the other five components only, same as before. - Stereo analysis (both
stereo_completeand all ofstereochemical_burden) cannot run at all for a molecule containing a negatively charged atom (any carboxylate, sulfonate, phosphate, or other anion) — a real chematic bug (#267), not a design choice. yomitoki never crashes or guesses on this (seeApplicabilityReport.stereo_uncheckableand theStereoAnalysisSkippedfinding), but genuinely has no stereo signal for such molecules until it's fixed upstream. size_topology's rotatable-bond term over-penalizes simple, commercially available long unbranched chains (many rotatable bonds, essentially no synthetic difficulty) —fragment_rarityis meant to correct this by recognizing such fragments as common/precedented. Round 17 redesigned it as a corpus-relative percentile signal (rather than a naive1 - document_frequencyterm, which round 16 found made the problem worse, not better) and confirmed the fix end-to-end against a real 200k-molecule ChEMBL corpus: dodecane'soverall.difficultymeasures0.068(no corpus) →0.000(corpus configured), and aspirin's0.273→0.095. This is not a general calibration claim, and it has a known caveat — see the next point andrules.rs's "Fragment rarity" section for the full formula and its corpus-domain-bias discussion.fragment_rarity's corpus-relative signal is only as good as the corpus it's given. Configured against ChEMBL (a bioactivity-screening corpus, not a synthesis-focused one), some structurally-legitimate molecules score harder, not easier, once the corpus is on — reported honestly, not tuned away, since these numbers are real measurements, not a formula bug (independently re-derived from the corpus's own frequency table and reproduced exactly): caffeine0.287 → 0.516, a bridged bicyclic (norbornane)0.341 → 0.985, a spiro ring system0.199 → 1.000, and a stereocenter-dense molecule0.275 → 1.000. The likely cause is that ChEMBL's fragment-frequency table reflects what shows up in bioassay-tested compounds, not what's a common synthetic building block — "rare in ChEMBL" and "hard to synthesize" are not the same claim. A synthesis-focused reference corpus would be the natural fix, not a further formula change.stereochemical_burdenonly covers tetrahedral stereocenter count and density. Investigated and still not implemented, each for a different reason (seedocs/architecture.mdfor the full evidence):- E/Z double-bond stereo — chematic can assign E/Z directly from SMILES
//\bond markers (no 2D coordinates needed, correcting an earlier, inaccurate note here), but only for bonds the input SMILES already marked. There's no detector for a stereogenic-but-unspecified double bond the way tetrahedral centers have one, so a specified-only count would measure how carefully the SMILES was written, not how many E/Z centers exist — the same class of problem atropisomerism was rejected for below, arriving a different way. - Atropisomerism — chematic's
detect_atropisomerswas tested directly and disqualified: it rates unsubstituted biphenyl as an atropisomer when writtenc1ccccc1-c2ccccc2but not when writtenc1ccccc1c2ccccc2(same molecule), and rates para-substituted biphenyl identically to genuinely hindered ortho-substituted biphenyl. Wrapping it would violate yomitoki's own atom-order/representation invariance guarantee. - Contiguous stereocenter runs, quaternary-carbon adjacency — both need an atom-level list of stereocenter candidates (specified and unspecified), which chematic doesn't expose (only aggregate counts). Building that inside yomitoki would make this crate the owner of stereocenter perception instead of a consumer of a validated chematic primitive — a line every implemented component has stayed on the other side of so far.
- Meso compound detection — needs graph automorphism / topological
symmetry classes; chematic has this internally
(
chematic-smiles::canonical_automorphism) but doesn't expose it.
- E/Z double-bond stereo — chematic can assign E/Z directly from SMILES
functional_group_liabilitycovers reactive/unstable functional groups (chematic's Brenk et al. 2008 structural-alert set directly) and dense functionalization (distinct functional-group cluster count, via chematic's Ertl 2017identify_functional_groups). Mutually incompatible functional-group combinations and protecting-group pressure are not implemented — unlike the two liabilities above, neither has a citable, validated primitive to build on (chematic exposes none), and hand-curating either would be exactly the "chemically weak rules, over-generalized" AGENTS.md warns against. Chemoselectivity burden, polyfunctional symmetry breaking, and difficult oxidation-state combinations are also not implemented — chematic exposes no oxidation-state API to build the last one on. Brenk's set was validated as a med-chem screening-library desirability filter, not a synthetic-difficulty signal, so several of its alerts fire on common, cheaply-precedented groups — aspirin, for example, trips four Brenk alerts and, without a corpus configured, lands atModeratelyAccessibledespite being trivially synthesizable. This is a known gap with the same shape and intended fix as the rotatable-bond one above:fragment_rarity's round-17 redesign confirms it end-to-end — aspirin'soverall.difficultymeasures0.273→0.095once a corpus is configured,LikelyAccessible. See the corpus-domain-bias caveat two points above; the same caveat applies here. Dense functionalization has its own known gap: it counts topologically disconnected functional-group clusters, so a single densely interconnected polyfunctional system (e.g. glucose's ring of hydroxyls, or a fused β-lactam) collapses to one cluster — identical in count to a molecule with a single, ordinary functional group.- No fragment corpus ships with yomitoki (AGENTS.md §5.4), so out of the
box, novel/rare substructures are not detected —
fragment_raritystaysNoneuntil you build one (tools/build-fragment-corpus) and configure it. No decision has been made yet about shipping one by default (theyomitoki-core/yomitoki-models/yomitoki-datasplit §5.4 sketches, or a feature-flagged external file). - Simplification suggestions cover 4 of
SuggestionCode's 6 variants (bridged ring, macrocycle, stereocenter density, and — when a fragment corpus is configured — increase fragment precedent) — the other 2 need signals that don't exist yet: quaternary-carbon adjacency isn't computed anywhere, andbrenk_matches_detailedunions atoms per pattern rather than per occurrence (so "remove one of several similar reactive groups" can't identify which occurrence to point at). Every suggestion's confidence is a flat, named constant (0.5), not per-suggestion-code, since none are calibrated against real synthesis outcomes. ApplicabilityReport.domain_distanceis alwaysNoneuntil a calibration corpus exists (Phase 2+).- Coverage is limited to a curated organic-element subset — no attempt at full periodic-table or organometallic support.
- Scores and thresholds are rule-based and unvalidated against external benchmarks so far; no calibration or comparison results exist yet.
Reproducibility
Given the same input, AnalysisConfig, and yomitoki/chematic/ruleset
versions, analyze/analyze_smiles always return the same report — no
randomness is used in the core evaluation path.
License
Licensed under either of Apache License, Version 2.0 or MIT license at your option.
Citation
No paper or citable release exists yet.
Roadmap
Remaining planned work: a shipped fragment corpus (fragment_rarity itself
is implemented but opt-in — see Limitations), calibration against
SAscore/RAscore/route-search outcomes (a minimum comparison against
SAscore, not calibration, now exists — see above), and eventually Python
bindings.