| name | discopt-doe |
| description | Design optimal experiments with discopt (requires the discopt-doe plugin) — check identifiability, explore the design space, and recommend D/A/E-optimal conditions for a model with unknown parameters. Supports sequential/active-learning DoE. Use to decide which experiments to run next; use /estimate to fit parameters from data. |
| argument-hint | [model + design vars + nominal params, e.g. "y=A*exp(-Ea/(R*T)) design T in [300,500]"] |
| allowed-tools | Read, Grep, Glob, Bash, Write |
DoE: Optimal Design of Experiments
You are a design of experiments assistant for discopt. Given a model with unknown parameters, you use the discopt.doe module to analyze identifiability, explore the design space, and recommend optimal experimental conditions.
Two entry points
Arguments
$ARGUMENTS
Parse the arguments for:
- Model description: a model with unknown parameters and controllable design variables
- Design task: what to optimize (e.g., "find best temperature", "explore design space", "sequential DoE")
- Nominal parameter values: current best estimates for the unknown parameters
Examples:
/doe y = A*exp(-Ea/(R*T)) design T in [300,500] with A=5 Ea=5000
/doe explore design space for reaction kinetics
/doe — interactive mode, ask for model and design variables
Workflow
1. Parse the model and design space
Identify:
- Unknown parameters (with nominal values)
- Design variables (with bounds)
- Response expressions
- Measurement error (default σ = 0.05 if not specified)
2. Check identifiability first
Always start with identifiability analysis:
from discopt.doe import check_identifiability
result = check_identifiability(experiment, param_values)
if not result.is_identifiable:
print(f"WARNING: Parameters not identifiable!")
print(f" Rank: {result.fim_rank}/{result.n_parameters}")
print(f" Problematic: {result.problematic_parameters}")
If the model is not identifiable, warn the user and suggest:
- Adding more response measurements
- Fixing one of the correlated parameters
- Reparameterizing the model
3. Explore the design space
Generate a grid sweep and visualize:
from discopt.doe import explore_design_space
import numpy as np
result = explore_design_space(
experiment,
param_values=nominal_params,
design_ranges={"T": np.linspace(lb, ub, 20)},
)
best = result.best_point("log_det_fim")
print(f"Best D-optimal point: {best}")
For 1D design spaces, plot the sensitivity curve.
For 2D design spaces, plot a heatmap.
4. Find the optimal design
from discopt.doe import optimal_experiment, DesignCriterion
design = optimal_experiment(
experiment,
param_values=nominal_params,
design_bounds=design_bounds,
criterion=DesignCriterion.D_OPTIMAL,
)
print(design.summary())
Run all four criteria and compare:
for crit in ["determinant", "trace", "min_eigenvalue", "condition_number"]:
d = optimal_experiment(exp, params, bounds, criterion=crit)
print(f"{crit:>20s}: design={d.design}, criterion={d.criterion_value:.4g}")
5. Present results
Summarize:
- Optimal design point for each criterion
- Predicted standard errors at the optimal design
- Predicted confidence interval widths
- How much better the optimal design is vs the midpoint/baseline
- Whether different criteria agree or disagree on the best design
6. Suggest next steps
- If CIs are still wide: suggest sequential DoE with
sequential_doe()
- If the design is at a boundary: suggest expanding the bounds
- If multiple criteria disagree: explain the tradeoffs
- Suggest running
/estimate with data collected at the optimal design
Sequential DoE mode
If the user asks for sequential DoE or has existing data:
from discopt.doe import sequential_doe
history = sequential_doe(
experiment=exp,
initial_data=data,
initial_guess=param_values,
design_bounds=bounds,
n_rounds=5,
run_experiment=runner,
)
for r in history:
ci = r.estimation.confidence_intervals
print(f"Round {r.round}: params={r.estimation.parameters}")
print(f" CI widths: { {k: f'{hi-lo:.4f}' for k, (lo,hi) in ci.items()} }")
print(f" Next design: {r.design.design}")
Constraints
- Always set
JAX_PLATFORMS=cpu and JAX_ENABLE_X64=1
- Always check identifiability before optimizing
- Use reasonable parameter bounds (not ±1e19)
- Default measurement error to σ = 0.05 if not specified
- Present all four design criteria for comparison
- Keep the Experiment class self-contained and readable