1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
//! JSON Model Definition and Code Generation
//!
//! This module provides functionality for defining pharmacometric models using JSON
//! and generating Rust code that can be compiled by the `exa` module.
//!
//! # Overview
//!
//! The JSON model system provides a declarative way to define pharmacometric models
//! without writing Rust code directly. Models are defined in JSON following a
//! structured schema, then validated and compiled to native code.
//!
//! The parser accepts canonical `2.0` source documents only. Validation
//! produces a normalized [`ExecutableModel`] that callers can compile, hash,
//! or inspect without depending on authoring-only metadata.
//!
//! The system supports three equation types:
//! - **Analytical**: Built-in closed-form solutions (fastest execution)
//! - **ODE**: Custom ordinary differential equations
//! - **SDE**: Stochastic differential equations with particle filtering
//!
//! # Quick Start
//!
//! ```ignore
//! use pharmsol::json::{generate_code, normalize_json, validate_json};
//!
//! // Define a model in JSON
//! let json = r#"{
//! "schema": "2.0",
//! "id": "pk/1cmt-oral",
//! "type": "analytical",
//! "compartments": ["depot", "central"],
//! "analytical": "one_compartment_with_absorption",
//! "parameters": ["ka", "ke", "V"],
//! "outputs": [
//! { "id": "cp", "equation": "central / V" }
//! ]
//! }"#;
//!
//! // Parse and validate
//! let validated = validate_json(json)?;
//! let executable = normalize_json(json)?;
//! assert_eq!(executable.outputs[0].id, "cp");
//!
//! // Generate Rust code
//! let code = generate_code(json)?;
//! println!("Generated: {}", code.equation_code);
//! ```
//!
//! # Using the Model Library
//!
//! The library provides pre-built standard PK models:
//!
//! ```ignore
//! use pharmsol::json::ModelLibrary;
//!
//! let library = ModelLibrary::builtin();
//!
//! // List available models
//! for id in library.list() {
//! println!("Available: {}", id);
//! }
//!
//! // Get a specific model
//! let model = library.get("pk/1cmt-oral").unwrap();
//!
//! // Search by keyword
//! let oral_models = library.search("oral");
//!
//! // Filter by type
//! let ode_models = library.filter_by_type(ModelType::Ode);
//! ```
//!
//! # Model Inheritance
//!
//! Models can extend base models to add customizations:
//!
//! ```ignore
//! use pharmsol::json::{JsonModel, ModelLibrary};
//!
//! let mut library = ModelLibrary::builtin();
//!
//! // Define a model that extends a library model
//! let derived = JsonModel::from_str(r#"{
//! "schema": "2.0",
//! "id": "pk/1cmt-wt",
//! "extends": "pk/1cmt-oral",
//! "type": "analytical",
//! "analytical": "one_compartment_with_absorption",
//! "parameters": ["ka", "ke", "V"],
//! "covariates": [{ "id": "WT", "reference": 70.0 }],
//! "secondary": [
//! { "id": "WT_ratio", "equation": "WT / 70.0" }
//! ]
//! }"#)?;
//!
//! // Resolve inherits the base model's executable structure
//! let resolved = library.resolve(&derived)?;
//! ```
//!
//! # Source Contract
//!
//! [`JsonModel`] accepts canonical `schema: "2.0"` documents. Use
//! [`normalize_json`] or [`ValidatedModel::executable`] when callers need the
//! canonical compile-time shape.
//!
//! ## Required Fields
//!
//! | Field | Description |
//! |-------|-------------|
//! | `schema` | Supported schema version (`"2.0"`) |
//! | `id` | Unique model identifier |
//! | `type` | Equation type: `"analytical"`, `"ode"`, or `"sde"` |
//!
//! ## Model Type Specific Fields
//!
//! ### Analytical Models
//! - `analytical`: One of the built-in functions (e.g., `"one_compartment_with_absorption"`)
//! - `compartments`: List of named states used by outputs and editor projections
//! - `parameters`: Parameter names in order expected by the analytical function
//! - `outputs`: output expressions
//!
//! ### ODE Models
//! - `compartments`: List of compartment names
//! - `diffeq`: Differential equations keyed by compartment name
//! - `parameters`: Parameter names
//! - `outputs`: output expressions
//!
//! ### SDE Models
//! - `states`: List of state variable names
//! - `drift`: Drift equations keyed by state name
//! - `diffusion`: Diffusion coefficients
//! - `particles`: Number of particles for simulation
//!
//! ## Optional Features
//!
//! - `lag`: Lag times per compartment
//! - `fa`: Bioavailability factors
//! - `init`: Initial conditions
//! - `secondary`: Ordered named calculations used by equations and outputs
//! - `covariates`: Covariate definitions
//! - `editor`: Container for display, layout, and documentation metadata
//!
//! Residual error configuration is not currently part of [`JsonModel`].
//!
//! # Available Analytical Functions
//!
//! | Function | Parameters | States |
//! |----------|------------|--------|
//! | `one_compartment` | ke | 1 |
//! | `one_compartment_with_absorption` | ka, ke | 2 |
//! | `two_compartments` | ke, kcp, kpc | 2 |
//! | `two_compartments_with_absorption` | ke, ka, kcp, kpc | 3 |
//! | `three_compartments` | k10, k12, k13, k21, k31 | 3 |
//! | `three_compartments_with_absorption` | ka, k10, k12, k13, k21, k31 | 4 |
//!
//! # Error Handling
//!
//! All functions return `Result<T, JsonModelError>` with descriptive errors:
//!
//! ```ignore
//! match validate_json(json) {
//! Ok(model) => println!("Valid model: {}", model.inner().id),
//! Err(JsonModelError::MissingField { field, model_type }) => {
//! eprintln!("Missing {} for {} model", field, model_type);
//! }
//! Err(JsonModelError::UnsupportedSchema { version, .. }) => {
//! eprintln!("Schema {} not supported", version);
//! }
//! Err(e) => eprintln!("Error: {}", e),
//! }
//! ```
pub use ;
pub use JsonModelError;
pub use ModelLibrary;
pub use JsonModel;
pub use *;
pub use ;
/// Parse a JSON string into a JsonModel
/// Parse and validate a JSON model
/// Parse, validate, and normalize a JSON model into executable form.
/// Parse, validate, and generate code from a JSON model
/// Compile a JSON model to a dynamic library
///
/// This is the high-level API that combines parsing, validation,
/// code generation, and compilation into a single call.
///
/// Requires the `exa` feature to be enabled.