renkin 0.1.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/README.md +309 -0
- package/package.json +36 -0
- package/renkin.d.ts +63 -0
- package/renkin.js +246 -0
- package/renkin_bg.wasm +0 -0
package/README.md
ADDED
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
# RENKIN — Retrosynthesis Engine
|
|
2
|
+
|
|
3
|
+
> **Computer-Aided Synthesis Planning (CASP) · Pure Rust · WebAssembly · Python**
|
|
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
|
+
|
|
6
|
+
[](https://crates.io/crates/renkin)
|
|
7
|
+
[](LICENSE)
|
|
8
|
+
[](https://github.com/kent-tokyo/renkin/tree/master/demo)
|
|
9
|
+
[](https://www.rust-lang.org)
|
|
10
|
+
|
|
11
|
+
[日本語版 README](./README_ja.md)
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## What is RENKIN?
|
|
16
|
+
|
|
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**.
|
|
18
|
+
|
|
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:
|
|
20
|
+
|
|
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
|
|
24
|
+
|
|
25
|
+
All from a single pure-Rust codebase with zero C/C++ dependencies.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Key Features
|
|
30
|
+
|
|
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 |
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Architecture
|
|
47
|
+
|
|
48
|
+
```
|
|
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
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## Technology Stack
|
|
81
|
+
|
|
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/)
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## Installation
|
|
96
|
+
|
|
97
|
+
### As a library
|
|
98
|
+
|
|
99
|
+
```toml
|
|
100
|
+
# Cargo.toml
|
|
101
|
+
[dependencies]
|
|
102
|
+
renkin = "0.1"
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### CLI (from source)
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
git clone https://github.com/kent-tokyo/renkin
|
|
109
|
+
cd renkin
|
|
110
|
+
cargo build --release
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Python
|
|
114
|
+
|
|
115
|
+
```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
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## Getting Started
|
|
125
|
+
|
|
126
|
+
### CLI
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
# Retrosynthesis (Aspirin, depth 3)
|
|
130
|
+
./target/release/renkin --target "CC(=O)Oc1ccccc1C(=O)O" --depth 3
|
|
131
|
+
|
|
132
|
+
# With beam search (top-50 nodes)
|
|
133
|
+
./target/release/renkin --target "CC(=O)Oc1ccccc1C(=O)O" --depth 5 --beam-width 50
|
|
134
|
+
```
|
|
135
|
+
|
|
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
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Python
|
|
145
|
+
|
|
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
|
+
```
|
|
158
|
+
|
|
159
|
+
### WASM
|
|
160
|
+
|
|
161
|
+
```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
|
+
```
|
|
166
|
+
|
|
167
|
+
```javascript
|
|
168
|
+
import init, { find_routes } from './pkg/renkin.js';
|
|
169
|
+
await init();
|
|
170
|
+
|
|
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);
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### Benchmark
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
# Input: one SMILES per line, optional name after whitespace
|
|
184
|
+
./scripts/run_benchmark.sh --input data/benchmark_targets.smi --depth 5
|
|
185
|
+
```
|
|
186
|
+
|
|
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
|
+
```
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
## CLI Output Example
|
|
198
|
+
|
|
199
|
+
```json
|
|
200
|
+
{
|
|
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
|
+
]
|
|
215
|
+
}
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
**depth: 0** means the target itself is a commercially available starting material (buy directly).
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## Retro-Rules (14 total)
|
|
223
|
+
|
|
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.
|
|
242
|
+
|
|
243
|
+
---
|
|
244
|
+
|
|
245
|
+
## Project Structure
|
|
246
|
+
|
|
247
|
+
```
|
|
248
|
+
renkin/
|
|
249
|
+
├── 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)
|
|
260
|
+
├── 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
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
---
|
|
270
|
+
|
|
271
|
+
## Roadmap
|
|
272
|
+
|
|
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
|
|
285
|
+
|
|
286
|
+
---
|
|
287
|
+
|
|
288
|
+
## Competitive Landscape
|
|
289
|
+
|
|
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`)** |
|
|
298
|
+
|
|
299
|
+
All existing open CASP tools are Python-based. RENKIN fills the vacant niche: Rust-native, WASM-deployable, zero-dependency, A\* search.
|
|
300
|
+
|
|
301
|
+
---
|
|
302
|
+
|
|
303
|
+
## License
|
|
304
|
+
|
|
305
|
+
MIT
|
|
306
|
+
|
|
307
|
+
---
|
|
308
|
+
|
|
309
|
+
*GitHub Topics: `retrosynthesis` `cheminformatics` `wasm` `rust` `drug-discovery` `casp` `synthesis-planning` `computational-chemistry`*
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "renkin",
|
|
3
|
+
"type": "module",
|
|
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",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/kent-tokyo/renkin"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"renkin_bg.wasm",
|
|
13
|
+
"renkin.js",
|
|
14
|
+
"renkin.d.ts"
|
|
15
|
+
],
|
|
16
|
+
"main": "renkin.js",
|
|
17
|
+
"homepage": "https://github.com/kent-tokyo/renkin",
|
|
18
|
+
"types": "renkin.d.ts",
|
|
19
|
+
"sideEffects": [
|
|
20
|
+
"./snippets/*"
|
|
21
|
+
],
|
|
22
|
+
"bugs": {
|
|
23
|
+
"url": "https://github.com/kent-tokyo/renkin/issues"
|
|
24
|
+
},
|
|
25
|
+
"keywords": [
|
|
26
|
+
"retrosynthesis",
|
|
27
|
+
"cheminformatics",
|
|
28
|
+
"chemistry",
|
|
29
|
+
"wasm",
|
|
30
|
+
"webassembly",
|
|
31
|
+
"drug-discovery",
|
|
32
|
+
"casp",
|
|
33
|
+
"smiles",
|
|
34
|
+
"synthesis-planning"
|
|
35
|
+
]
|
|
36
|
+
}
|
package/renkin.d.ts
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/* tslint:disable */
|
|
2
|
+
/* eslint-disable */
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Find retrosynthetic routes for a target molecule (WASM entry point).
|
|
6
|
+
*
|
|
7
|
+
* Returns a JSON string with the retrosynthesis result.
|
|
8
|
+
*
|
|
9
|
+
* # Arguments
|
|
10
|
+
* * `target` - Target molecule SMILES
|
|
11
|
+
* * `depth` - Maximum retrosynthesis depth
|
|
12
|
+
* * `max_routes` - Maximum number of routes
|
|
13
|
+
* * `beam_width` - Beam search width; 0 = unlimited A*
|
|
14
|
+
*
|
|
15
|
+
* # Example (JavaScript)
|
|
16
|
+
* ```js
|
|
17
|
+
* import init, { find_routes } from '@renkin/wasm';
|
|
18
|
+
* await init();
|
|
19
|
+
* const result = JSON.parse(find_routes("CC(=O)Oc1ccccc1C(=O)O", 3, 5, 0));
|
|
20
|
+
* console.log(result.routes_found);
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export function find_routes(target: string, depth: number, max_routes: number, beam_width: number): string;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Return the crate version string.
|
|
27
|
+
*/
|
|
28
|
+
export function version(): string;
|
|
29
|
+
|
|
30
|
+
export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
|
|
31
|
+
|
|
32
|
+
export interface InitOutput {
|
|
33
|
+
readonly memory: WebAssembly.Memory;
|
|
34
|
+
readonly find_routes: (a: number, b: number, c: number, d: number, e: number) => [number, number];
|
|
35
|
+
readonly version: () => [number, number];
|
|
36
|
+
readonly __wbindgen_externrefs: WebAssembly.Table;
|
|
37
|
+
readonly __wbindgen_malloc: (a: number, b: number) => number;
|
|
38
|
+
readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
|
|
39
|
+
readonly __wbindgen_free: (a: number, b: number, c: number) => void;
|
|
40
|
+
readonly __wbindgen_start: () => void;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export type SyncInitInput = BufferSource | WebAssembly.Module;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Instantiates the given `module`, which can either be bytes or
|
|
47
|
+
* a precompiled `WebAssembly.Module`.
|
|
48
|
+
*
|
|
49
|
+
* @param {{ module: SyncInitInput }} module - Passing `SyncInitInput` directly is deprecated.
|
|
50
|
+
*
|
|
51
|
+
* @returns {InitOutput}
|
|
52
|
+
*/
|
|
53
|
+
export function initSync(module: { module: SyncInitInput } | SyncInitInput): InitOutput;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* If `module_or_path` is {RequestInfo} or {URL}, makes a request and
|
|
57
|
+
* for everything else, calls `WebAssembly.instantiate` directly.
|
|
58
|
+
*
|
|
59
|
+
* @param {{ module_or_path: InitInput | Promise<InitInput> }} module_or_path - Passing `InitInput` directly is deprecated.
|
|
60
|
+
*
|
|
61
|
+
* @returns {Promise<InitOutput>}
|
|
62
|
+
*/
|
|
63
|
+
export default function __wbg_init (module_or_path?: { module_or_path: InitInput | Promise<InitInput> } | InitInput | Promise<InitInput>): Promise<InitOutput>;
|
package/renkin.js
ADDED
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
/* @ts-self-types="./renkin.d.ts" */
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Find retrosynthetic routes for a target molecule (WASM entry point).
|
|
5
|
+
*
|
|
6
|
+
* Returns a JSON string with the retrosynthesis result.
|
|
7
|
+
*
|
|
8
|
+
* # Arguments
|
|
9
|
+
* * `target` - Target molecule SMILES
|
|
10
|
+
* * `depth` - Maximum retrosynthesis depth
|
|
11
|
+
* * `max_routes` - Maximum number of routes
|
|
12
|
+
* * `beam_width` - Beam search width; 0 = unlimited A*
|
|
13
|
+
*
|
|
14
|
+
* # Example (JavaScript)
|
|
15
|
+
* ```js
|
|
16
|
+
* import init, { find_routes } from '@renkin/wasm';
|
|
17
|
+
* await init();
|
|
18
|
+
* const result = JSON.parse(find_routes("CC(=O)Oc1ccccc1C(=O)O", 3, 5, 0));
|
|
19
|
+
* console.log(result.routes_found);
|
|
20
|
+
* ```
|
|
21
|
+
* @param {string} target
|
|
22
|
+
* @param {number} depth
|
|
23
|
+
* @param {number} max_routes
|
|
24
|
+
* @param {number} beam_width
|
|
25
|
+
* @returns {string}
|
|
26
|
+
*/
|
|
27
|
+
export function find_routes(target, depth, max_routes, beam_width) {
|
|
28
|
+
let deferred2_0;
|
|
29
|
+
let deferred2_1;
|
|
30
|
+
try {
|
|
31
|
+
const ptr0 = passStringToWasm0(target, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
32
|
+
const len0 = WASM_VECTOR_LEN;
|
|
33
|
+
const ret = wasm.find_routes(ptr0, len0, depth, max_routes, beam_width);
|
|
34
|
+
deferred2_0 = ret[0];
|
|
35
|
+
deferred2_1 = ret[1];
|
|
36
|
+
return getStringFromWasm0(ret[0], ret[1]);
|
|
37
|
+
} finally {
|
|
38
|
+
wasm.__wbindgen_free(deferred2_0, deferred2_1, 1);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Return the crate version string.
|
|
44
|
+
* @returns {string}
|
|
45
|
+
*/
|
|
46
|
+
export function version() {
|
|
47
|
+
let deferred1_0;
|
|
48
|
+
let deferred1_1;
|
|
49
|
+
try {
|
|
50
|
+
const ret = wasm.version();
|
|
51
|
+
deferred1_0 = ret[0];
|
|
52
|
+
deferred1_1 = ret[1];
|
|
53
|
+
return getStringFromWasm0(ret[0], ret[1]);
|
|
54
|
+
} finally {
|
|
55
|
+
wasm.__wbindgen_free(deferred1_0, deferred1_1, 1);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function __wbg_get_imports() {
|
|
59
|
+
const import0 = {
|
|
60
|
+
__proto__: null,
|
|
61
|
+
__wbindgen_init_externref_table: function() {
|
|
62
|
+
const table = wasm.__wbindgen_externrefs;
|
|
63
|
+
const offset = table.grow(4);
|
|
64
|
+
table.set(0, undefined);
|
|
65
|
+
table.set(offset + 0, undefined);
|
|
66
|
+
table.set(offset + 1, null);
|
|
67
|
+
table.set(offset + 2, true);
|
|
68
|
+
table.set(offset + 3, false);
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
return {
|
|
72
|
+
__proto__: null,
|
|
73
|
+
"./renkin_bg.js": import0,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function getStringFromWasm0(ptr, len) {
|
|
78
|
+
return decodeText(ptr >>> 0, len);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
let cachedUint8ArrayMemory0 = null;
|
|
82
|
+
function getUint8ArrayMemory0() {
|
|
83
|
+
if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) {
|
|
84
|
+
cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer);
|
|
85
|
+
}
|
|
86
|
+
return cachedUint8ArrayMemory0;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function passStringToWasm0(arg, malloc, realloc) {
|
|
90
|
+
if (realloc === undefined) {
|
|
91
|
+
const buf = cachedTextEncoder.encode(arg);
|
|
92
|
+
const ptr = malloc(buf.length, 1) >>> 0;
|
|
93
|
+
getUint8ArrayMemory0().subarray(ptr, ptr + buf.length).set(buf);
|
|
94
|
+
WASM_VECTOR_LEN = buf.length;
|
|
95
|
+
return ptr;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
let len = arg.length;
|
|
99
|
+
let ptr = malloc(len, 1) >>> 0;
|
|
100
|
+
|
|
101
|
+
const mem = getUint8ArrayMemory0();
|
|
102
|
+
|
|
103
|
+
let offset = 0;
|
|
104
|
+
|
|
105
|
+
for (; offset < len; offset++) {
|
|
106
|
+
const code = arg.charCodeAt(offset);
|
|
107
|
+
if (code > 0x7F) break;
|
|
108
|
+
mem[ptr + offset] = code;
|
|
109
|
+
}
|
|
110
|
+
if (offset !== len) {
|
|
111
|
+
if (offset !== 0) {
|
|
112
|
+
arg = arg.slice(offset);
|
|
113
|
+
}
|
|
114
|
+
ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0;
|
|
115
|
+
const view = getUint8ArrayMemory0().subarray(ptr + offset, ptr + len);
|
|
116
|
+
const ret = cachedTextEncoder.encodeInto(arg, view);
|
|
117
|
+
|
|
118
|
+
offset += ret.written;
|
|
119
|
+
ptr = realloc(ptr, len, offset, 1) >>> 0;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
WASM_VECTOR_LEN = offset;
|
|
123
|
+
return ptr;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
let cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
|
|
127
|
+
cachedTextDecoder.decode();
|
|
128
|
+
const MAX_SAFARI_DECODE_BYTES = 2146435072;
|
|
129
|
+
let numBytesDecoded = 0;
|
|
130
|
+
function decodeText(ptr, len) {
|
|
131
|
+
numBytesDecoded += len;
|
|
132
|
+
if (numBytesDecoded >= MAX_SAFARI_DECODE_BYTES) {
|
|
133
|
+
cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
|
|
134
|
+
cachedTextDecoder.decode();
|
|
135
|
+
numBytesDecoded = len;
|
|
136
|
+
}
|
|
137
|
+
return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len));
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const cachedTextEncoder = new TextEncoder();
|
|
141
|
+
|
|
142
|
+
if (!('encodeInto' in cachedTextEncoder)) {
|
|
143
|
+
cachedTextEncoder.encodeInto = function (arg, view) {
|
|
144
|
+
const buf = cachedTextEncoder.encode(arg);
|
|
145
|
+
view.set(buf);
|
|
146
|
+
return {
|
|
147
|
+
read: arg.length,
|
|
148
|
+
written: buf.length
|
|
149
|
+
};
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
let WASM_VECTOR_LEN = 0;
|
|
154
|
+
|
|
155
|
+
let wasmModule, wasmInstance, wasm;
|
|
156
|
+
function __wbg_finalize_init(instance, module) {
|
|
157
|
+
wasmInstance = instance;
|
|
158
|
+
wasm = instance.exports;
|
|
159
|
+
wasmModule = module;
|
|
160
|
+
cachedUint8ArrayMemory0 = null;
|
|
161
|
+
wasm.__wbindgen_start();
|
|
162
|
+
return wasm;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
async function __wbg_load(module, imports) {
|
|
166
|
+
if (typeof Response === 'function' && module instanceof Response) {
|
|
167
|
+
if (typeof WebAssembly.instantiateStreaming === 'function') {
|
|
168
|
+
try {
|
|
169
|
+
return await WebAssembly.instantiateStreaming(module, imports);
|
|
170
|
+
} catch (e) {
|
|
171
|
+
const validResponse = module.ok && expectedResponseType(module.type);
|
|
172
|
+
|
|
173
|
+
if (validResponse && module.headers.get('Content-Type') !== 'application/wasm') {
|
|
174
|
+
console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve Wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e);
|
|
175
|
+
|
|
176
|
+
} else { throw e; }
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const bytes = await module.arrayBuffer();
|
|
181
|
+
return await WebAssembly.instantiate(bytes, imports);
|
|
182
|
+
} else {
|
|
183
|
+
const instance = await WebAssembly.instantiate(module, imports);
|
|
184
|
+
|
|
185
|
+
if (instance instanceof WebAssembly.Instance) {
|
|
186
|
+
return { instance, module };
|
|
187
|
+
} else {
|
|
188
|
+
return instance;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function expectedResponseType(type) {
|
|
193
|
+
switch (type) {
|
|
194
|
+
case 'basic': case 'cors': case 'default': return true;
|
|
195
|
+
}
|
|
196
|
+
return false;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function initSync(module) {
|
|
201
|
+
if (wasm !== undefined) return wasm;
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
if (module !== undefined) {
|
|
205
|
+
if (Object.getPrototypeOf(module) === Object.prototype) {
|
|
206
|
+
({module} = module)
|
|
207
|
+
} else {
|
|
208
|
+
console.warn('using deprecated parameters for `initSync()`; pass a single object instead')
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
const imports = __wbg_get_imports();
|
|
213
|
+
if (!(module instanceof WebAssembly.Module)) {
|
|
214
|
+
module = new WebAssembly.Module(module);
|
|
215
|
+
}
|
|
216
|
+
const instance = new WebAssembly.Instance(module, imports);
|
|
217
|
+
return __wbg_finalize_init(instance, module);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
async function __wbg_init(module_or_path) {
|
|
221
|
+
if (wasm !== undefined) return wasm;
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
if (module_or_path !== undefined) {
|
|
225
|
+
if (Object.getPrototypeOf(module_or_path) === Object.prototype) {
|
|
226
|
+
({module_or_path} = module_or_path)
|
|
227
|
+
} else {
|
|
228
|
+
console.warn('using deprecated parameters for the initialization function; pass a single object instead')
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
if (module_or_path === undefined) {
|
|
233
|
+
module_or_path = new URL('renkin_bg.wasm', import.meta.url);
|
|
234
|
+
}
|
|
235
|
+
const imports = __wbg_get_imports();
|
|
236
|
+
|
|
237
|
+
if (typeof module_or_path === 'string' || (typeof Request === 'function' && module_or_path instanceof Request) || (typeof URL === 'function' && module_or_path instanceof URL)) {
|
|
238
|
+
module_or_path = fetch(module_or_path);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
const { instance, module } = await __wbg_load(await module_or_path, imports);
|
|
242
|
+
|
|
243
|
+
return __wbg_finalize_init(instance, module);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
export { initSync, __wbg_init as default };
|
package/renkin_bg.wasm
ADDED
|
Binary file
|