renkin 0.1.0 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 kent-tokyo
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,302 +1,623 @@
1
- # RENKIN — Retrosynthesis Engine
1
+ # RENKIN — Retrosynthesis Engine for Knowledge-Informed Navigation
2
2
 
3
3
  > **Computer-Aided Synthesis Planning (CASP) · Pure Rust · WebAssembly · Python**
4
4
  > Named after 錬金 (れんきん, *renkin*) — Japanese for alchemy: just as alchemists transformed base metals into gold, RENKIN transforms target molecules back into cheap starting materials.
5
5
 
6
- [![Crates.io](https://img.shields.io/crates/v/renkin)](https://crates.io/crates/renkin)
7
- [![License: MIT](https://img.shields.io/badge/license-MIT-blue)](LICENSE)
8
- [![WASM](https://img.shields.io/badge/WASM-ready-brightgreen)](https://github.com/kent-tokyo/renkin/tree/master/demo)
9
- [![Pure Rust](https://img.shields.io/badge/Pure-Rust-orange?logo=rust)](https://www.rust-lang.org)
6
+ <p>
7
+ <a href="https://github.com/kent-tokyo/renkin/actions/workflows/ci.yml"><img alt="CI" src="https://github.com/kent-tokyo/renkin/actions/workflows/ci.yml/badge.svg?branch=master"></a>
8
+ <a href="https://github.com/kent-tokyo/renkin/actions/workflows/docs.yml"><img alt="Docs" src="https://github.com/kent-tokyo/renkin/actions/workflows/docs.yml/badge.svg?branch=master"></a>
9
+ </p>
10
10
 
11
- [日本語版 README](./README_ja.md)
11
+ <p>
12
+ <a href="https://crates.io/crates/renkin"><img alt="Crates.io" src="https://img.shields.io/crates/v/renkin.svg"></a>
13
+ <a href="https://docs.rs/renkin"><img alt="docs.rs" src="https://docs.rs/renkin/badge.svg"></a>
14
+ <a href="https://pypi.org/project/renkin/"><img alt="PyPI" src="https://img.shields.io/pypi/v/renkin.svg"></a>
15
+ <a href="https://pypi.org/project/renkin/"><img alt="Python" src="https://img.shields.io/pypi/pyversions/renkin.svg"></a>
16
+ <a href="https://www.npmjs.com/package/renkin"><img alt="npm" src="https://img.shields.io/npm/v/renkin.svg"></a>
17
+ <a href="LICENSE"><img alt="License: MIT" src="https://img.shields.io/badge/license-MIT-blue.svg"></a>
18
+ </p>
19
+
20
+ [日本語版 README](./README_ja.md) · [中文版 README](./README_zh.md) · [**Documentation**](https://kent-tokyo.github.io/renkin/) · [**Live Demo →**](https://kent-tokyo.github.io/renkin/playground/)
12
21
 
13
22
  ---
14
23
 
15
24
  ## What is RENKIN?
16
25
 
17
- RENKIN is an open-source **retrosynthesis engine** for **computer-aided synthesis planning (CASP)** that automatically discovers optimal chemical reaction routes from a target molecule back to cheap, commercially available starting materials — a core problem in **drug discovery** and **medicinal chemistry**.
26
+ RENKIN is an open-source **retrosynthesis engine** for **computer-aided synthesis planning (CASP)** that automatically discovers optimal chemical reaction routes from a target molecule back to cheap, commercially available starting materials.
27
+
28
+ Built entirely in Rust with the [`chematic`](https://docs.rs/chematic/) cheminformatics crate — zero C/C++ dependencies, `#![forbid(unsafe_code)]` throughout. One codebase compiles to a native CLI, a Rust library, Python wheels (PyO3), and a WebAssembly module that runs entirely client-side in the browser.
18
29
 
19
- Built entirely in Rust with the [`chematic`](https://docs.rs/chematic/) cheminformatics crate, RENKIN solves the fundamental speed and dependency problems of existing Python-based CASP tools (AiZynthFinder, ASKCOS, Retro\*, etc.). It ships as:
30
+ ---
20
31
 
21
- - **CLI** — single binary, `cargo build --release`
22
- - **Python package** — `import renkin` via PyO3 + maturin
23
- - **WASM module** — 493 KB bundle, runs in the browser with no server
32
+ ## Installation
24
33
 
25
- All from a single pure-Rust codebase with zero C/C++ dependencies.
34
+ ```bash
35
+ pip install renkin # Python
36
+ cargo add renkin # Rust
37
+ npm install renkin # JavaScript / Node.js
38
+ ```
26
39
 
27
40
  ---
28
41
 
29
- ## Key Features
42
+ ## Live Playground
30
43
 
31
- | Feature | Detail |
32
- |---|---|
33
- | **Pure Rust** | Zero C/C++ dependencies. Cross-platform with `cargo build` alone |
34
- | **A\* / AND-OR Tree Search** | Retro\*-equivalent algorithm proven more efficient than MCTS for retrosynthesis |
35
- | **SA Score heuristic** | `chematic::chem::sa_score` guides search toward synthetically accessible precursors |
36
- | **Beam search** | `--beam-width N` limits heap size for memory-bounded exploration |
37
- | **Graph-based Ar–Ar cleavage** | Bridge-bond detection via DFS — correctly handles biaryl (Suzuki) disconnections |
38
- | **Parallel rule application** | `rayon` parallelises SMIRKS rule evaluation; sequential fallback on WASM |
39
- | **Python bindings** | `maturin` extension — `import renkin; renkin.find_routes(...)` |
40
- | **WASM-ready** | 493 KB bundle via `wasm-pack`; browser demo with 2D structure rendering |
41
- | **~400 building blocks** | Curated commercial starting materials covering esters, amines, halides, heterocycles, amino acids, sulfonyl chlorides, boronic acids and more |
42
- | **Benchmark CLI** | `renkin-bench --input targets.smi` produces a JSON success/timing report |
44
+ **[→ Try it now](https://kent-tokyo.github.io/renkin/playground/)** — runs entirely in WebAssembly: no installation, no server, no network calls.
43
45
 
44
46
  ---
45
47
 
46
- ## Architecture
48
+ ## Quick Start
47
49
 
50
+ ```python
51
+ import json
52
+ import renkin
53
+
54
+ result = json.loads(
55
+ renkin.find_routes(
56
+ target="CC(=O)Oc1ccccc1C(=O)O", # Aspirin
57
+ depth=5,
58
+ max_routes=3,
59
+ )
60
+ )
61
+
62
+ for route in result["routes"]:
63
+ for step in route["steps"]:
64
+ print(f" {step['target']} → {' + '.join(step['precursors'])} [{step['rule']}]")
48
65
  ```
49
- Target SMILES
50
-
51
-
52
- ┌─────────────────────────┐
53
- │ chem_env.rs │ ← chematic wrapper
54
- │ - SMILES parse │ SMARTS VF2 building-block check
55
- │ - SMIRKS retro rules │ fragment sanitization
56
- │ - Building block check │ HashMap O(1) pre-filter
57
- └────────────┬────────────┘
58
- │ par_iter (rayon / sequential on WASM)
59
-
60
- ┌─────────────────────────┐
61
- │ search.rs │ ← A* / AND-OR Tree Search
62
- │ - Priority queue │ SA Score heuristic
63
- │ - Closed list │ beam search pruning
64
- │ - Degenerate filter │
65
- └────────────┬────────────┘
66
-
67
-
68
- ┌─────────────────────────┐
69
- │ score.rs │ ← Heuristic / Cost Function
70
- │ - SA Score (chematic) │ h = Σ(1 + 0.5·(sa−1)/9)
71
- │ - MW step cost │ g = Σ(1 + total_mw/2000)
72
- └────────────┬────────────┘
73
-
74
-
75
- JSON ← CLI / Python / WASM
66
+
67
+ ```javascript
68
+ import init, { find_routes } from './pkg/renkin.js';
69
+ await init();
70
+ const result = JSON.parse(find_routes("CC(=O)Oc1ccccc1C(=O)O", 5, 3, 0));
71
+ ```
72
+
73
+ ```bash
74
+ ./target/release/renkin --target "CC(=O)Oc1ccccc1C(=O)O" --depth 5 \
75
+ --templates data/templates_extracted_5000.smi --format tree
76
76
  ```
77
77
 
78
+ ```text
79
+ Target: CC(=O)Oc1ccccc1C(=O)O
80
+ Routes found: 3
81
+
82
+ Route 1 [score=1.02, depth=1]
83
+ OC(=O)c1ccccc1OC(=O)C
84
+ └── [extracted_169]
85
+ ├── OC(=O)C ✓ BB
86
+ └── [OH]c1ccccc1C(=O)O ✓ BB
87
+
88
+ Route 2 [score=1.02, depth=1]
89
+ OC(=O)c1ccccc1OC(=O)C
90
+ └── [extracted_145]
91
+ ├── CC(=O)Cl ✓ BB
92
+ └── [OH]c1ccccc1C(=O)O ✓ BB
93
+
94
+ Route 3 [score=1.03, depth=1]
95
+ OC(=O)c1ccccc1OC(=O)C
96
+ └── [extracted_238]
97
+ ├── c1cccc(c1O)C(O)=O ✓ BB
98
+ └── C([OH])(=O)C ✓ BB
99
+ ```
100
+
101
+ Use `--format mermaid` for GitHub/Notion-compatible flowcharts.
102
+
103
+ [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/kent-tokyo/renkin/blob/master/examples/renkin_quickstart.ipynb)
104
+
78
105
  ---
79
106
 
80
- ## Technology Stack
107
+ ## Current Limitations
81
108
 
82
- - **Language**: Rust (Edition 2024)
83
- - **Cheminformatics**: [`chematic`](https://crates.io/crates/chematic) v0.4.9+
84
- - `chematic-smiles` SMILES parsing & canonical SMILES
85
- - `chematic-smarts` VF2 substructure matching (building block identity)
86
- - `chematic-rxn` SMIRKS reaction application (`run_reactants`)
87
- - `chematic-chem` SA Score, molecular weight, aromaticity descriptors
88
- - **Search**: A\* + AND/OR Tree (Retro\* equivalent)
89
- - **Parallelism**: [`rayon`](https://crates.io/crates/rayon) parallel SMIRKS rule application
90
- - **Python**: [`PyO3`](https://pyo3.rs) + [`maturin`](https://www.maturin.rs)
91
- - **WASM**: [`wasm-bindgen`](https://rustwasm.github.io/wasm-bindgen/) + [`wasm-pack`](https://rustwasm.github.io/wasm-pack/)
109
+ ⚠️ Benchmark numbers are under active re-measurement after a validator-accuracy
110
+ fix historical 78.0%/95.9%/81.8%(ChEMBL) figures elsewhere in this repo predate
111
+ that fix and are invalidated. RENKIN does not predict yields, calibrated
112
+ experimental success probabilities, or side reactions, and does not search
113
+ the literature automatically (`success_probability` is a template-frequency
114
+ search-ranking score, not a calibrated prediction see
115
+ [Benchmark](https://kent-tokyo.github.io/renkin/benchmark/) for the current
116
+ corrected numbers, full methodology, and known limitations).
92
117
 
93
118
  ---
94
119
 
95
- ## Installation
120
+ ## Why RENKIN?
96
121
 
97
- ### As a library
122
+ RENKIN is designed as a Rust-native synthesis planning stack:
98
123
 
99
- ```toml
100
- # Cargo.toml
101
- [dependencies]
102
- renkin = "0.1"
103
- ```
124
+ | | |
125
+ |---|---|
126
+ | **Fast** | A\* / AND-OR tree search with beam search and template frequency weighting |
127
+ | **Portable** | Native CLI · Python wheels · npm/WASM · browser playground — one codebase |
128
+ | **Explainable** | Per-step `confidence`, `atom_economy`, `route_cost`, and `procedure_hint` |
129
+ | **Verifiable** | `renkin-forward` validates each retrosynthetic step by forward-applying templates |
130
+ | **Benchmarkable** | USPTO-50k, PaRoutes-style evaluation, route diversity, and atom balance checks |
131
+ | **Agent-ready** | MCP server exposes routes and validation to Claude Desktop and AI agents |
132
+
133
+ ---
134
+
135
+ ## Constraint-based Search
136
+
137
+ Restrict routes by the element composition of their building blocks.
104
138
 
105
- ### CLI (from source)
139
+ **Default search** all 5 routes for biphenyl:
106
140
 
107
141
  ```bash
108
- git clone https://github.com/kent-tokyo/renkin
109
- cd renkin
110
- cargo build --release
142
+ renkin --target "c1ccc(-c2ccccc2)cc1" --templates data/templates_extracted_5000.smi --format tree
143
+ ```
144
+
145
+ ```text
146
+ Routes found: 5
147
+ Route 1 [score=1.00, depth=1] c1ccccc1Br + c1c(B(O)O)cccc1
148
+ Route 2 [score=1.03, depth=1] c1ccccc1Br + c1c(B(O)O)cccc1
149
+ Route 3 [score=1.06, depth=1] c1cc(Cl)ccc1 + c1c(B(O)O)cccc1
150
+ Route 4 [score=1.08, depth=1] c1(I)ccccc1 + c1c(B(O)O)cccc1
151
+ Route 5 [score=1.08, depth=1] c1ccccc1Br + c1(B2OC(C(C)(C)O2)(C)C)ccccc1
111
152
  ```
112
153
 
113
- ### Python
154
+ **Constrained search** — boronic-acid coupling, no Br or I starting materials:
114
155
 
115
156
  ```bash
116
- pip install maturin
117
- git clone https://github.com/kent-tokyo/renkin && cd renkin
118
- python -m venv .venv && source .venv/bin/activate
119
- maturin develop --features python
157
+ renkin --target "c1ccc(-c2ccccc2)cc1" --templates data/templates_extracted_5000.smi \
158
+ --require-elements "B" --avoid-elements "Br,I" --format tree
159
+ ```
160
+
161
+ ```text
162
+ Routes found: 1
163
+
164
+ Route 1 [score=1.06, depth=1]
165
+ c1ccccc1-c2ccccc2
166
+ └── [extracted_398]
167
+ ├── c1cc(Cl)ccc1 ✓ BB
168
+ └── c1c(B(O)O)cccc1 ✓ BB
120
169
  ```
121
170
 
171
+ Constraints compose freely and are enforced in two layers:
172
+ - `--avoid-elements` **prunes expansions during search** when a BB precursor contains a forbidden element (no dead-end nodes added to the heap).
173
+ - A final route-level post-filter is still applied for correctness.
174
+ - `--require-elements` is a route-level post-filter only.
175
+
176
+ Add `--verbose` to print search statistics (nodes expanded, elapsed time) to stderr. Performance counters are available in native builds only; disabled in WASM.
177
+
122
178
  ---
123
179
 
124
- ## Getting Started
180
+ ## Template Evidence Metadata
125
181
 
126
- ### CLI
182
+ Extracted templates only have a positional display name (`extracted_{i}`) that
183
+ changes whenever the source `.smi` file is reordered or re-extracted, so
184
+ external knowledge (a DOI, a reported yield, a known side reaction) can't be
185
+ durably attached to one. Every template — hand-crafted and extracted — now
186
+ has a stable `template_id` instead:
127
187
 
128
- ```bash
129
- # Retrosynthesis (Aspirin, depth 3)
130
- ./target/release/renkin --target "CC(=O)Oc1ccccc1C(=O)O" --depth 3
188
+ - Hand-crafted rules: `rule:<rule_name>` (e.g. `rule:suzuki_retro`).
189
+ - Extracted templates: `smirks-sha256:<hex>` — the SHA-256 hex digest of the
190
+ *trimmed* SMIRKS string. Independent of file position, load order, and
191
+ count; purely syntactic (no SMIRKS canonicalization — a semantically
192
+ equivalent SMIRKS written differently gets a different ID).
131
193
 
132
- # With beam search (top-50 nodes)
133
- ./target/release/renkin --target "CC(=O)Oc1ccccc1C(=O)O" --depth 5 --beam-width 50
134
- ```
194
+ Run `renkin template ids <file.smi>` to list every template's `template_id`,
195
+ display name, SMIRKS, and weight (TSV by default, `--format json` for JSON) —
196
+ use this to look up the IDs you need when authoring a sidecar file.
135
197
 
136
- ```
137
- --target / -t Target molecule SMILES
138
- --depth / -d Max retrosynthesis depth (default: 5)
139
- --max-routes / -n Max routes to return (default: 5)
140
- --beam-width / -w Beam search width, 0 = unlimited A* (default: 0)
141
- --building-blocks Path to .smi file of commercial starting materials
198
+ Attach curated evidence with `--template-metadata sidecar.json` (also
199
+ available in Python as `find_routes(..., template_metadata_path=...)`),
200
+ keyed by `template_id`:
201
+
202
+ ```json
203
+ {
204
+ "schema_version": 1,
205
+ "templates": {
206
+ "smirks-sha256:ef8778a2888469d619c52cce7e74f6848e101049050dd1b765b78f32e3c94498": {
207
+ "references": [
208
+ { "id": "ref-1", "kind": "doi", "identifier": "10.xxxx/example" }
209
+ ],
210
+ "condition_candidates": [
211
+ {
212
+ "catalysts": ["Pd(PPh3)4"],
213
+ "bases": ["K2CO3"],
214
+ "solvents": ["EtOH", "water"],
215
+ "temperature_c": { "min": 75.0, "max": 85.0 },
216
+ "source": "literature",
217
+ "scope": "template",
218
+ "reference_ids": ["ref-1"]
219
+ }
220
+ ],
221
+ "reported_yields": [
222
+ {
223
+ "percentage": { "min": 72.0, "max": 81.0 },
224
+ "basis": "isolated",
225
+ "source": "literature",
226
+ "scope": "template",
227
+ "reference_ids": ["ref-1"]
228
+ }
229
+ ],
230
+ "warnings": [
231
+ {
232
+ "code": "possible_protodeboronation",
233
+ "severity": "medium",
234
+ "message": "Protodeboronation has been reported under prolonged aqueous heating.",
235
+ "source": "literature",
236
+ "scope": "template",
237
+ "reference_ids": ["ref-1"]
238
+ }
239
+ ]
240
+ }
241
+ }
242
+ }
142
243
  ```
143
244
 
144
- ### Python
245
+ A matching step gets an `evidence` field with `condition_candidates`,
246
+ `reported_yields`, `references`, and `warnings`; steps whose template has no
247
+ sidecar entry get no `evidence` key at all. The sidecar is loaded and
248
+ validated (schema version, duplicate/dangling reference IDs, yield range,
249
+ range `min <= max`, non-empty DOI/patent identifiers) **before search
250
+ starts** — malformed metadata is a hard error, and a `template_id` in the
251
+ sidecar that matches no loaded rule prints a warning rather than failing
252
+ silently.
253
+
254
+ **What this is not:**
255
+ - `reported_yields` is a curated record of what was reported externally —
256
+ **not a RENKIN prediction**. `step_confidence`/`success_probability` are
257
+ unaffected and keep meaning template-frequency-derived search-ranking
258
+ scores, not experimental success rates.
259
+ - `warnings` reflects only what's explicitly present in the sidecar you
260
+ supply — **not** automatic side-reaction detection.
261
+ - Templates without a matching sidecar entry get no fabricated evidence.
262
+ Nothing is invented for missing data.
263
+
264
+ Yield/success prediction and automatic literature search are explicitly out
265
+ of scope for this phase — tracked as future work in
266
+ [#41](https://github.com/kent-tokyo/renkin/issues/41).
145
267
 
146
- ```python
147
- import renkin, json
148
-
149
- routes = json.loads(renkin.find_routes(
150
- "CC(=O)Oc1ccccc1C(=O)O", # Aspirin
151
- depth=3,
152
- max_routes=5,
153
- ))
154
- print(routes["routes_found"]) # number of routes found
155
- for r in routes["routes"]:
156
- print(r["depth"], [s["rule"] for s in r["steps"]])
157
- ```
268
+ ---
269
+
270
+ ## Key Features
158
271
 
159
- ### WASM
272
+ | Feature | Detail |
273
+ |---|---|
274
+ | **Pure Safe Rust** | `#![forbid(unsafe_code)]` on all crates — compiler-enforced, zero C/C++ dependencies |
275
+ | **A\* / AND-OR Tree Search** | Retro\*-equivalent algorithm with pluggable heuristics (`MoleculeValueEstimator`, `ReactionPrior`) |
276
+ | **Up to 50k reaction templates** | Auto-extracted from USPTO-50k/MIT via rdchiral; frequency-weighted priority; `--templates` for custom sets |
277
+ | **Route scoring** | `confidence`, `step_confidence`, `success_probability` (Retro-prob style), `convergency`, `atom_economy` per step — see caveat below the table |
278
+ | **Step metadata provenance** | Each step reports `metadata_source`/`metadata_scope` (e.g. `handcrafted_default`/`reaction_family`) so it's machine-readable whether `conditions`/`reaction_family` came from a rule-author default vs. something more grounded; absent for extracted templates, since nothing is fabricated for them. |
279
+ | **Stable template IDs + evidence sidecar** | Every template gets a stable `template_id` — `rule:<name>` for hand-crafted rules, `smirks-sha256:<hex>` for extracted templates (independent of file order/position/count). Attach curated DOIs/patents, reported conditions, reported yields, and known side-reaction warnings via a `--template-metadata sidecar.json` file keyed by `template_id`; matching steps get an `evidence` field, everything else stays untouched — see [Template evidence metadata](#template-evidence-metadata) below. Run `renkin template ids <file.smi>` to list stable IDs for authoring a sidecar. Automatic yield/success prediction and literature search remain out of scope ([#41](https://github.com/kent-tokyo/renkin/issues/41)). |
280
+ | **Route cost scoring** | `route_cost = Σ(BB cost) + steps×0.5`; actual prices via `--bb-prices CSV` or `--stock stock.csv` |
281
+ | **Pareto multi-objective search** | `--format pareto` returns a Pareto front across `route_cost`, `success_probability`, `steps`, etc.; objectives configurable via `--objectives cost:min,success_probability:max,steps:min` |
282
+ | **Constraint DSL** | `--constraints constraints.json` — JSON-driven synthesis planning: element filters, step limits, confidence thresholds, preferred reaction families; enables LLM → RENKIN pipeline |
283
+ | **Output formats** | `--format json` · `tree` · `mermaid` · `explain` (human-readable per-route analysis) · `compare` (side-by-side table) · `compare-json` · `pareto` |
284
+ | **Failure diagnostics** | Zero-route JSON output includes `diagnostics` block with `likely_causes` and `suggestions` |
285
+ | **Forward validation** | `renkin-forward validate` verifies each step by applying templates forward; accepts `--route-json` or stdin |
286
+ | **Plausibility report** | `renkin-bench --plausibility` — forward-validates best routes and reports composite plausibility score |
287
+ | **PaRoutes benchmark** | `renkin-bench --input-format paroutes` for multi-step ground-truth evaluation with `depth_delta` and `route_diversity` |
288
+ | **Atom balance check** | `renkin-bench` flags steps where `target_MW > Σ precursor_MW` (CompleteRXN reference) |
289
+ | **Stock CSV management** | `renkin stock stats\|validate\|coverage` — inspect and validate stock CSV files with SMILES, name, vendor, price, hazard fields |
290
+ | **Template quality tools** | `renkin template stats\|validate\|dedup\|explain\|coverage\|ids` — inspect SMIRKS template sets: frequency distribution, validity, duplicates, per-template lookup, coverage rate, stable template IDs |
291
+ | **MCP server** | `renkin-mcp` exposes 6 tools: `find_routes`, `validate_route`, `explain_route`, `find_pareto_routes`, `plan_with_constraints`, `estimate_diversity` |
292
+ | **`renkin-doctor`** | Environment diagnostic binary — checks templates, building blocks, Python import, tool versions, and data integrity |
293
+ | **`renkin-kg`** | Reaction knowledge graph builder — constructs bipartite mol↔reaction graphs from routes; exports to GraphML or Cypher |
294
+ | **Beam search** | `--beam-width N` for memory-bounded exploration; `SmallVec<[FEntry; 6]>` stack-allocated frontier |
295
+ | **Parallel rule application** | `rayon` on non-WASM; sequential fallback on wasm32 |
296
+ | **tract-onnx NN scorer** | Pure Rust ONNX inference (no C++ dep) — optional `--scorer` flag for Phase B template relevance scoring |
297
+ | **`building_blocks` in JSON** | Each route includes the leaf starting-material SMILES — no manual step parsing needed |
298
+ | **Tetrahedral stereo @/@@** | Full stereochemistry support via chematic 0.4.16 |
299
+ | **Python** | `pip install renkin` — pre-built wheels for Linux/macOS/Windows |
300
+ | **WASM** | ~500 KB bundle — runs in the browser at near-native speed |
301
+ | **402 building blocks** | Aryl halides, boronic acids, heterocycles, amines, acids, amino acids (`data/building_blocks.smi`, unique compounds actually loaded — see Benchmark section) |
302
+
303
+ > **`step_confidence`/`success_probability` are not yields or measured success rates.**
304
+ > They're template-frequency-derived search-ranking scores (`rule_weight / max_rule_weight`,
305
+ > multiplied across a route's steps) used to order candidate disconnections during search —
306
+ > not a calibrated probability of experimental success, and not an expected isolated yield.
307
+ > Route-level experimental yield/success-rate reporting is not implemented.
308
+
309
+ ---
310
+
311
+ ## Pipeline Examples
160
312
 
161
313
  ```bash
162
- wasm-pack build --target web --no-default-features
163
- # Output: pkg/ (npm-ready package)
164
- # Browser demo: python3 -m http.server 8080 → http://localhost:8080/demo/
165
- ```
314
+ # Route cost scoring with commercial prices
315
+ renkin -t "Cc1ccc(-c2ccccc2)cc1" --bb-prices data/prices.csv --format json
166
316
 
167
- ```javascript
168
- import init, { find_routes } from './pkg/renkin.js';
169
- await init();
317
+ # Forward validation — pipe find_routes output directly
318
+ renkin -t "CC(=O)Oc1ccccc1C(=O)O" --format json | renkin-forward validate
170
319
 
171
- const result = JSON.parse(find_routes(
172
- "CC(=O)Oc1ccccc1C(=O)O", // target SMILES
173
- 3, // depth
174
- 5, // max_routes
175
- 0, // beam_width (0 = unlimited A*)
176
- ));
177
- console.log(result.routes_found);
320
+ # Faster template retrieval with bond-center index (~24% speedup)
321
+ renkin -t "c1ccc(NC(=O)c2ccccc2)cc1" --templates data/templates_extracted_5000.smi --bond-index
178
322
  ```
179
323
 
180
- ### Benchmark
324
+ ---
325
+
326
+ ## Benchmark
327
+
328
+ USPTO-50k test set (4,907 molecules, full evaluation):
329
+
330
+ > **Evaluation definition**: A molecule is *solved* if `find_routes` returns at least one route whose leaf precursors are all in the building block set, within depth=5 and beam=100. Ground-truth reactants from USPTO-50k are **not** checked — any commercially accessible route counts.
331
+
332
+ ### Corrected baseline (commit `e20dc8c`, 2026-07-22)
333
+
334
+ | Public label | Internal metric | Value |
335
+ |---|---|---|
336
+ | Search-to-stock rate | `raw_solved_rate` | **20.09%** (986/4,907) |
337
+ | Atom-balance-filtered rate | `atom_balanced_solved_rate` | **15.41%** (756/4,907) — subset of search-to-stock |
338
+ | Current-validator-confirmed rate | `provenance_validated_solved_rate` | **0.88%** (43/4,907) — subset of atom-balance-filtered |
339
+
340
+ 402 building blocks (unique compounds actually loaded from `data/building_blocks.smi` — see below), 5,000 extracted templates, 28 handcrafted rules, depth=5, beam=100. These three rates are a nested series over the same 4,907 targets, not independent numbers, and none is an experimentally-verified synthesis success rate or a human-chemist-reviewed route-accuracy figure. `provenance_validated_solved_rate` is not a measured chemical-accuracy rate and not a proven lower bound on correctness — it only counts routes the current validator can positively confirm, and an unknown fraction of "invalid" verdicts may be validator false negatives rather than real chemistry or route errors (the split is unmeasured). Full methodology, per-rule breakdown, and reproduction command: [`tasks/phase31_final_remeasurement_run.md`](https://github.com/kent-tokyo/renkin/blob/master/tasks/phase31_final_remeasurement_run.md) · [Full benchmark details →](https://kent-tokyo.github.io/renkin/benchmark/)
341
+
342
+ ### Historical progression (pre-fix, invalidated — see notice above)
343
+
344
+ ⚠️ The figures in this subsection (78.0% single-pass, 95.9% cascade, 81.8% ChEMBL OOD) predate the 31.11/31.12 fixes, are invalidated, and have not been re-measured. Kept for continuity only — do not cite as current performance.
345
+
346
+ > **Evaluation note**: All numbers use the standard USPTO-50k train/test split (same corpus). Templates are extracted from the training set and evaluated on the test set. Numbers reflect performance within the USPTO-50k domain; out-of-distribution generalization was separately evaluated via ChEMBL approved drugs (**81.8%**, 409/500, also not re-measured).
347
+
348
+ | Config | Solved | Rate | BBs | Templates | depth | beam | ms/mol |
349
+ |---|---|---|---|---|---|---|---|
350
+ | v0.1.0 initial | 366/4907 | 7.5% | 463 | 31 | 3 | 50 | — |
351
+ | + auto templates (top-300) | 1363/4907 | 27.8% | 463 | 222 | 3 | 50 | — |
352
+ | + depth=5, top-500 templates | 2315/4907 | 47.2% | 463 | 314 | 5 | 50 | — |
353
+ | + beam=100 | 2688/4907 | 54.8%* | 463 | 314 | 5 | 100 | — |
354
+ | + Phase A (template freq. weighting) | 3540/4907 | 72.1%† | 463 | 314 | 5 | 100 | — |
355
+ | + 5,000 templates, 480 BBs | 3826/4907 | 78.0% | 480 | 5,000 | 5 | 100 | 2,775 |
356
+ | Phase A unlimited (beam=0) | 3832/4907 | 78.1% | 480 | 5,000 | 5 | 0 | — |
357
+ | Phase B (NN scorer, tract-onnx) | 3826/4907 | 78.0% | 480 | 5,000 | 5 | 100 | 3,394 |
358
+ | **+ diaryl sulfone rule, 509 BBs** | **3826/4907** | **78.0%** | **509** | **5,000** | **5** | **100** | **≈2,800** |
359
+ | Cascade (stage2: depth=7, beam=300 on unsolved) | 4705/4907 | **95.9%** | 509 | 5,000 | 7 | 300 | — |
360
+
361
+ \* 29/50 chunks, previous binary
362
+ † 50/50 chunks — **72.1%** (3,540/4,907) confirmed
363
+ BB counts in this historical table (463/480/509) are as originally documented at each point in time — legacy documentation values, not re-verified against `ChemEnv::bb_count()`. The corrected-baseline section above uses the actually-loaded count (402) for the current `data/building_blocks.smi`.
364
+
365
+ *Note: LocalRetro (53.4%) and GLG (58.0%) report single-step top-1 prediction accuracy — a different metric, not directly comparable.*
366
+
367
+ > **Benchmark scope note**: USPTO-50k is used here as a *standardized sanity benchmark*, not as proof of broad real-world synthesis performance. The corpus covers a narrow slice of reaction space (primarily C–C and C–N bond formations common in pharmaceutical synthesis), and reaction types with sparse USPTO representation are systematically underserved. Out-of-distribution performance on ChEMBL approved drugs (**81.8%**, 409/500, pre-fix, not re-measured) suggested the rule set generalizes beyond the test corpus, but neither historical number should be interpreted as a guarantee of route quality on arbitrary targets.
368
+
369
+ ### PaRoutes compatibility
370
+
371
+ RENKIN is compatible with the [PaRoutes](https://github.com/AstraZeneca/PaRoutes) multi-step benchmark. Download their stock compounds and target molecules, then pass them directly:
181
372
 
182
373
  ```bash
183
- # Input: one SMILES per line, optional name after whitespace
184
- ./scripts/run_benchmark.sh --input data/benchmark_targets.smi --depth 5
374
+ renkin-bench \
375
+ --input paroutes_n1_targets.smi \
376
+ --building-blocks paroutes_stock.smi \
377
+ --templates data/templates_extracted_5000.smi \
378
+ --depth 5 --beam-width 100
185
379
  ```
186
380
 
187
- ```json
188
- {
189
- "total": 42, "solved": 37, "success_rate": 0.88,
190
- "avg_depth": 1.05, "avg_time_ms": 2.5,
191
- "results": [...]
192
- }
193
- ```
381
+ The JSON output includes `avg_nodes_expanded`, `avg_confidence`, `avg_convergency`, and `avg_success_prob` (Retro-prob style) alongside the standard solved/success_rate metrics.
194
382
 
195
383
  ---
196
384
 
197
- ## CLI Output Example
385
+ ## Competitive Landscape
386
+
387
+ ⚠️ RENKIN's row below uses the corrected `raw_solved_rate` (20.09%, see notice near the top of this README) — the 95.9% cascade figure some earlier versions of this table cited is invalidated and not re-measured; it is not included here.
388
+
389
+ | Tool | Language | License | WASM | Zero-dep | Algorithm | Template source | Stock |
390
+ |---|---|---|---|---|---|---|---|
391
+ | **ASKCOS** | Python | CC BY-NC | No | No (Docker, 64 GB) | MCTS + A\* | USPTO (ML) | ZINC |
392
+ | **AiZynthFinder** | Python | MIT | No | No (conda + model) | MCTS | USPTO (ML, ~50k) | eMolecules (~6M) |
393
+ | **SYNTHIA** | Closed | Proprietary | No | No | SMARTS + AND/OR | Manual curated | Sigma-Aldrich |
394
+ | **IBM RXN** | Closed | Cloud SaaS | No | No | Transformer | USPTO | — |
395
+ | **Retro\*** | Python | MIT | No | No (unmaintained) | A\* + AND/OR | USPTO (ML) | eMolecules |
396
+ | **★ RENKIN** | **Rust** | **MIT** | **Yes** | **Yes** | **A\* + AND/OR** | Hand-curated + rdchiral (5k default; 50k via `--templates`) | 402+ |
397
+
398
+ `raw_solved_rate` is the closest available RENKIN metric to the published route-finding success rates of the other planners above, but the figures are not directly comparable — stock size, template library, target set, search budget, and route-quality checks all differ across systems, and this table does not establish RENKIN as better or worse than the alternatives.
399
+
400
+ **RENKIN's goal**: match state-of-the-art accuracy using only curated rules and auto-extracted SMIRKS templates — no GPU, no training data, no black boxes. Under RENKIN's benchmark setting (corrected baseline, commit `e20dc8c`, 2026-07-22), it reaches **20.09%** `raw_solved_rate` (986/4,907) single-pass — see the Benchmark section above for the full nested-metric series and why the stricter `provenance_validated_solved_rate` (0.88%) is not RENKIN's measured or bounded correctness rate. RENKIN runs anywhere: browser, CLI, Python — single `cargo build`.
401
+
402
+ > ⚠️ The table above lists tools under different evaluation conditions. No matched-condition experiment against other tools has been performed.
403
+
404
+ ---
405
+
406
+ ## MCP Server
407
+
408
+ `renkin-mcp` exposes retrosynthesis as an MCP tool so AI agents (Claude, etc.) can call it directly.
409
+
410
+ **Setup** — add to `claude_desktop_config.json`:
198
411
 
199
412
  ```json
200
413
  {
201
- "target": "CC(=O)Oc1ccccc1C(=O)O",
202
- "routes_found": 2,
203
- "routes": [
204
- {
205
- "steps": [
206
- {
207
- "rule": "ester_cleavage",
208
- "target": "CC(=O)Oc1ccccc1C(=O)O",
209
- "precursors": ["CC(=O)O", "Oc1ccccc1C(=O)O"]
210
- }
211
- ],
212
- "depth": 1
213
- }
214
- ]
414
+ "mcpServers": {
415
+ "renkin": { "command": "/path/to/renkin-mcp" }
416
+ }
215
417
  }
216
418
  ```
217
419
 
218
- **depth: 0** means the target itself is a commercially available starting material (buy directly).
420
+ **Tools** (6):
421
+
422
+ | Tool | Description |
423
+ |---|---|
424
+ | `find_routes` | Retrosynthesis: SMILES → routes with scoring |
425
+ | `validate_route` | Forward-validate a retrosynthetic route |
426
+ | `explain_route` | Human-readable strengths/weaknesses per route |
427
+ | `find_pareto_routes` | Pareto-front multi-objective route search |
428
+ | `plan_with_constraints` | Constraint-DSL planning (element filters, step limits, confidence thresholds) |
429
+ | `estimate_diversity` | Route diversity and coverage metrics |
430
+
431
+ The server auto-detects `data/building_blocks.smi` and `data/templates_extracted_5000.smi` in the working directory. Falls back to the embedded `DEFAULT_BUILDING_BLOCKS` / `default_rules()` defaults if not found (152 unique building blocks per `ChemEnv::bb_count()`, 28 handcrafted rules — verified 2026-07-22; a "509-BB / 20-rule" figure was previously documented here without verification).
432
+
433
+ ```bash
434
+ cargo build --release
435
+ # binary: target/release/renkin-mcp
436
+ ```
219
437
 
220
438
  ---
221
439
 
222
- ## Retro-Rules (14 total)
440
+ ## Architecture
223
441
 
224
- | Rule | Reaction type | Strategy |
225
- |---|---|---|
226
- | `ester_cleavage` | Ester → acid + alcohol | SMIRKS |
227
- | `amide_cleavage` | Amide → acid + amine | SMIRKS |
228
- | `friedel_crafts_acylation_retro` | Ar-C(=O)R → Ar-H + acyl chloride | SMIRKS |
229
- | `aryl_carboxylation_retro` | Ar-COOH → Ar-H + CO₂ surrogate | SMIRKS |
230
- | `aryl_amine_retro` | Ar-N → Ar-H + amine | SMIRKS |
231
- | `buchwald_hartwig_retro` | Ar-N → Ar-Br + amine | SMIRKS |
232
- | `aryl_ether_retro` | Ar-O Ar-OH + fragment | SMIRKS |
233
- | `suzuki_retro` | Ar-Ar → Ar-Br + Ar-H | Graph (bridge-bond DFS) |
234
- | `cc_single_cleavage` | C–C two fragments | SMIRKS |
235
- | `wittig_retro` | C=C → C=O + C=O | SMIRKS |
236
- | `reductive_amination_retro` | C–N → C=O + amine | SMIRKS |
237
- | `cn_aliphatic_cleavage` | C–N → two fragments | SMIRKS |
238
- | `co_aliphatic_cleavage` | C–O → two fragments | SMIRKS |
239
- | `alcohol_oxidation_retro` | C–OH → C=O | SMIRKS |
240
-
241
- `suzuki_retro` uses a graph-based bridge-bond algorithm instead of SMIRKS to correctly handle symmetric biaryls (biphenyl, 4-fluorobiphenyl, etc.) without the BFS leakage artifacts that affect SMIRKS-based approaches.
442
+ ### Workspace scope
443
+
444
+ ```
445
+ ┌──────────────────────────────────────────────────────────────────┐
446
+ renkin workspace (this repository)
447
+ │ │
448
+ │ renkin (retrosynthesis) renkin-forward │
449
+ │ ────────────────────── ───────────────────────────── │
450
+ │ target precursors reactantsproducts │
451
+ │ A* / AND-OR search template-based forward │
452
+ │ route scoring & constraints (validates retro routes) │
453
+ │ │ │ │
454
+ │ └──────────────────┬─────────────────┘ │
455
+ │ ▼ │
456
+ │ chematic (molecular representation, │
457
+ │ SMILES, substructure matching, reaction SMARTS) │
458
+ └──────────────────────────────────────────────────────────────────┘
459
+ ```
460
+
461
+ ### Internal data flow (renkin crate)
462
+
463
+ ```
464
+ Target SMILES
465
+
466
+
467
+ ┌─────────────────────────┐
468
+ │ chem_env.rs │ ← chematic wrapper
469
+ │ - SMILES parse │ canonical-SMILES FxHashSet BB lookup (O(1))
470
+ │ - 20 built-in + up to 50k via --templates │ fragment sanitization + ring-leak filter
471
+ │ - Building block check │ apply_retro memoization cache
472
+ └────────────┬────────────┘
473
+ │ par_iter (rayon / sequential on WASM)
474
+
475
+ ┌─────────────────────────┐
476
+ │ search.rs │ ← A* / AND-OR Tree Search
477
+ │ - Priority queue │ SA Score heuristic + memoization
478
+ │ - Closed list │ beam search (SmallVec frontier)
479
+ │ - Arc<PathNode> paths │ O(1) path sharing per child
480
+ └────────────┬────────────┘
481
+
482
+
483
+ ┌─────────────────────────┐
484
+ │ score.rs │ ← Heuristic / Cost Function
485
+ │ - SA Score (chematic) │ h = Σ(1 + 0.5·(sa−1)/9)
486
+ │ - MW step cost │ g = Σ(1 + total_mw/2000)
487
+ └────────────┬────────────┘
488
+
489
+
490
+ ┌─────────────────────────┐ (optional)
491
+ │ scorer.rs │ ← Phase B: NN Template Scorer
492
+ │ - tract-onnx │ Pure Rust ONNX inference
493
+ │ - --scorer flag │ molecule-specific template ranking
494
+ └────────────┬────────────┘
495
+
496
+
497
+ JSON ← CLI / Python / WASM
498
+ ```
242
499
 
243
500
  ---
244
501
 
245
502
  ## Project Structure
246
503
 
247
504
  ```
248
- renkin/
505
+ renkin/ ← Cargo workspace root
249
506
  ├── Cargo.toml
250
- ├── src/
251
- │ ├── lib.rs # public library (DEFAULT_BUILDING_BLOCKS, re-exports)
252
- │ ├── main.rs # CLI binary
253
- │ ├── bin/
254
- │ └── benchmark.rs # renkin-bench binary
255
- │ ├── chem_env.rs # chematic wrapper parse, retro rules, BB check
256
- │ ├── score.rs # SA Score heuristic + step cost
257
- │ ├── search.rs # A* / AND-OR tree engine + beam pruning
258
- │ ├── python.rs # PyO3 bindings (--features python)
259
- └── wasm.rs # wasm-bindgen bindings (cfg = wasm32)
507
+ ├── src/ ← renkin crate (retrosynthesis)
508
+ │ ├── lib.rs # public library
509
+ │ ├── main.rs # CLI binary (--templates, --template-metadata, --scorer, --constraints, --objectives flags)
510
+ │ ├── bin/benchmark.rs # renkin-bench binary (--plausibility flag)
511
+ ├── bin/doctor.rs # renkin-doctor diagnostic binary
512
+ │ ├── bin/fp.rs # renkin-fp ECFP4 fingerprint (nn-scoring feature)
513
+ │ ├── bin/mcp.rs # renkin-mcp MCP server (6 tools)
514
+ │ ├── chem_env.rs # retro rules + BB lookup + template loader
515
+ │ ├── score.rs # SA Score heuristic + step cost
516
+ ├── search.rs # A* / AND-OR tree engine + beam pruning
517
+ │ ├── scorer.rs # Phase B: tract-onnx NN template scorer
518
+ │ ├── python.rs # PyO3 bindings (--features python)
519
+ │ └── wasm.rs # wasm-bindgen bindings (cfg = wasm32)
520
+ ├── crates/ ← sibling crates
521
+ │ ├── renkin-forward/ # forward reaction prediction (reactants → products)
522
+ │ └── renkin-kg/ # reaction knowledge graph builder (GraphML / Cypher export)
260
523
  ├── data/
261
- │ ├── building_blocks.smi # Commercial starting materials (~400 entries)
262
- └── benchmark_targets.smi # 42-molecule benchmark set
263
- ├── demo/
264
- │ └── index.html # Browser WASM demo with 2D structure rendering
265
- └── scripts/
266
- └── run_benchmark.sh # Benchmark runner with human-readable summary
524
+ │ ├── building_blocks.smi # 402 curated commercial starting materials (loaded/deduplicated count)
525
+ ├── templates_extracted_5000.smi # 5,000 auto-extracted SMIRKS templates
526
+ ├── benchmark_targets.smi # internal benchmark set
527
+ │ └── bench_chunks/ # USPTO-50k per-chunk results
528
+ ├── scripts/
529
+ │ ├── extract_templates.py # rdchiral template extraction pipeline
530
+ │ └── run_benchmark_chunks.sh # resumable chunked benchmark runner
531
+ ├── docs/ # MkDocs source → kent-tokyo.github.io/renkin/
532
+ └── mkdocs.yml
267
533
  ```
268
534
 
269
535
  ---
270
536
 
271
537
  ## Roadmap
272
538
 
273
- - [x] **Phase 1** — SMIRKS retro-reaction rules + fragment sanitization
274
- - [x] **Phase 2** — A\* / AND-OR tree search, closed list, degenerate-route filter
275
- - [x] **Phase 3** SA Score heuristic + beam search (`--beam-width`)
276
- - [x] **Phase 4**Parallel rule application (`rayon`; sequential fallback on WASM)
277
- - [x] **Phase 5**Python bindings (PyO3 + maturin)
278
- - [x] **Phase 6**WASM build (493 KB, `pkg/` npm-ready)
279
- - [x] **Phase 7**Benchmark CLI (`renkin-bench`)
280
- - [x] **Phase 8** 21 unit tests, SMIRKS rules 5→14, building blocks ~30→~400
281
- - [x] **Phase 9** Browser WASM demo (SmilesDrawer 2D rendering), benchmark target set
282
- - [x] **Phase 10** — Graph-based biaryl cleavage (suzuki_retro), O(1) BB HashMap index
283
- - [ ] **Phase 11** — Formal benchmark vs. AiZynthFinder / Retro\* on USPTO-50k
284
- - [ ] **Phase 12** — PyPI / npm publish
539
+ ### Recently shipped
540
+
541
+ - [x] Stable `template_id` (`rule:<name>` / `smirks-sha256:<hex>`) + `--template-metadata` evidence sidecar + `renkin template ids` ([#41](https://github.com/kent-tokyo/renkin/issues/41) phase 1)
542
+ - [x] `renkin-bench cascade`multi-stage search (fast defaults hard cases re-run deeper); only unsolved targets propagate to later stages. **78.0% → 95.9%** on USPTO-50k
543
+ - [x] `renkin-bench --failure-taxonomy`classify unsolved targets by cause (beam limit / depth limit / template gap / stock near-miss)
544
+ - [x] Graph-based ester cleavage BFS-leakage-free `R-C(=O)-O-R' RCOOH + R'OH`
545
+ - [x] `--top-templates N`frequency-rank filter: use the top-N most frequent templates for speed / less noise
546
+ - [x] `raw / validated / practical` solved-rate metrics (`--plausibility --practical-max-steps N`)
547
+ - [x] Retro cache hit-rate in `SearchStats` + `--verbose`
548
+
549
+ ### In progress
550
+
551
+ - [ ] Template retrieval index (element bitmask + bond-center prefilter) for the 50k template set
552
+ - [ ] Calibrated route confidence (map `success_probability` to empirical solve rate)
553
+
554
+ ### Next
555
+
556
+ - [ ] Graph rule expansion — sulfonamide / carbamate / urea cleavage (one PR per family, each with benchmark delta)
557
+ - [ ] Stock-aware planning (price / hazard / availability re-ranking)
558
+
559
+ <details>
560
+ <summary>Earlier milestones</summary>
561
+
562
+ - [x] Route cost scoring — `route_cost` field + `--bb-prices path.csv` / `--stock stock.csv`
563
+ - [x] Cargo workspace — `crates/renkin-forward/` + `crates/renkin-kg/`
564
+ - [x] `renkin-forward predict` / `validate` — forward prediction + route validation (stdin-pipe friendly)
565
+ - [x] `renkin-doctor` — environment diagnostic binary (templates, BBs, Python, binaries)
566
+ - [x] Failure diagnostics — zero-route output includes `likely_causes` + `suggestions` JSON block
567
+ - [x] `--format explain|compare|compare-json` — human-readable and tabular route output
568
+ - [x] `renkin stock stats|validate|coverage` — stock CSV management subcommand
569
+ - [x] Pareto multi-objective search — `--format pareto`, `--objectives`, `find_pareto_routes` MCP
570
+ - [x] Constraint DSL — `--constraints JSON`, `plan_with_constraints` MCP tool
571
+ - [x] `renkin template stats|validate|dedup|explain|coverage` — template quality tools
572
+ - [x] `renkin-kg` — reaction knowledge graph (bipartite mol↔reaction, GraphML/Cypher export)
573
+ - [x] MCP server expanded to 6 tools (`explain_route`, `find_pareto_routes`, `plan_with_constraints`)
574
+ - [x] SMIRKS retro-reaction rules + fragment sanitization
575
+ - [x] A\* / AND-OR tree search, closed list, degenerate-route filter
576
+ - [x] SA Score heuristic + beam search
577
+ - [x] Parallel rule application (rayon; sequential fallback on WASM)
578
+ - [x] Python bindings (PyO3 + maturin) · `pip install renkin`
579
+ - [x] WASM build · `npm install renkin`
580
+ - [x] Benchmark CLI (`renkin-bench`) + USPTO-50k evaluation
581
+ - [x] WASM browser playground + i18n (EN/JA/ZH)
582
+ - [x] Graph-based biaryl cleavage · O(1) canonical-SMILES BB index
583
+ - [x] Published to crates.io / PyPI / npm · GitHub Actions CI/CD
584
+ - [x] MkDocs documentation site · GitHub Pages playground
585
+ - [x] Auto template extraction (rdchiral): **27.8%** → **78.0%** USPTO-50k
586
+ - [x] Tetrahedral stereo @/@@ + E/Z double-bond stereo
587
+ - [x] Template frequency weighting (Phase A): **72.1%** USPTO-50k
588
+ - [x] FxHashMap · SmallVec beam frontier · SA Score memoization · Arc<PathNode> path sharing
589
+ - [x] 5,000 extracted templates + 509 BBs: **78.0%** USPTO-50k (3,826/4,907 ✅)
590
+ - [x] NN template scorer via `--scorer` flag (tract-onnx, Pure Rust ONNX)
591
+ - [x] `--format tree|mermaid` route visualization
592
+ - [x] Constraint-based search: `--avoid-elements`, `--require-elements`
593
+ - [x] `--verbose` search statistics to stderr
594
+ - [x] MCP server (`renkin-mcp`) — AI agents call retrosynthesis directly
595
+ - [x] `#![forbid(unsafe_code)]` — compiler-enforced Pure Safe Rust
596
+
597
+ </details>
285
598
 
286
599
  ---
287
600
 
288
- ## Competitive Landscape
601
+ ## Citation
602
+
603
+ If you use RENKIN in academic work, please cite:
604
+
605
+ ```bibtex
606
+ @software{renkin2026,
607
+ author = {kent-tokyo},
608
+ title = {{RENKIN}: Retrosynthesis Engine for Knowledge-Informed Navigation},
609
+ year = {2026},
610
+ url = {https://github.com/kent-tokyo/renkin/releases/tag/v0.17.0},
611
+ version = {0.17.0},
612
+ license = {MIT}
613
+ }
614
+ ```
289
615
 
290
- | Tool | Language | Algorithm | WASM | Zero-dep build |
291
- |---|---|---|---|---|
292
- | **ASKCOS** | Python | MCTS / A\* | No | No (Docker, 64 GB RAM) |
293
- | **AiZynthFinder** | Python | MCTS primary | No | No (conda, model download) |
294
- | **IBM RXN** | Closed | Transformer | No | No (cloud only) |
295
- | **SYNTHIA** | Closed | SMARTS + AND/OR | No | No (proprietary) |
296
- | **Retro\*** | Python | A\* + AND/OR | No | No (unmaintained) |
297
- | **★ RENKIN** | **Rust** | **A\* + AND/OR** | **Yes** | **Yes (`cargo build`)** |
616
+ ---
617
+
618
+ ## Security
298
619
 
299
- All existing open CASP tools are Python-based. RENKIN fills the vacant niche: Rust-native, WASM-deployable, zero-dependency, A\* search.
620
+ Report vulnerabilities via [GitHub Private vulnerability reporting](https://github.com/kent-tokyo/renkin/security/advisories/new). See [SECURITY.md](SECURITY.md).
300
621
 
301
622
  ---
302
623
 
@@ -307,3 +628,7 @@ MIT
307
628
  ---
308
629
 
309
630
  *GitHub Topics: `retrosynthesis` `cheminformatics` `wasm` `rust` `drug-discovery` `casp` `synthesis-planning` `computational-chemistry`*
631
+
632
+ ---
633
+
634
+ If RENKIN saves you time, a GitHub star helps others discover it.
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "renkin",
3
3
  "type": "module",
4
4
  "description": "Ultra-fast retrosynthesis engine for computer-aided synthesis planning (CASP) — pure Rust, WASM-ready, Python bindings via PyO3",
5
- "version": "0.1.0",
5
+ "version": "0.17.0",
6
6
  "license": "MIT",
7
7
  "repository": {
8
8
  "type": "git",
@@ -19,18 +19,11 @@
19
19
  "sideEffects": [
20
20
  "./snippets/*"
21
21
  ],
22
- "bugs": {
23
- "url": "https://github.com/kent-tokyo/renkin/issues"
24
- },
25
22
  "keywords": [
26
23
  "retrosynthesis",
27
24
  "cheminformatics",
28
25
  "chemistry",
29
26
  "wasm",
30
- "webassembly",
31
- "drug-discovery",
32
- "casp",
33
- "smiles",
34
- "synthesis-planning"
27
+ "drug-discovery"
35
28
  ]
36
29
  }
package/renkin_bg.wasm CHANGED
Binary file