fzd - Design of Experiments
The fzd function (or fz design command) runs iterative design of experiments with adaptive algorithms. Unlike fzr which runs a fixed grid of parameter combinations, fzd lets algorithms intelligently choose which points to evaluate next based on previous results.
When to Use fzd vs fzr
| Feature | fzr |
fzd |
|---|---|---|
| Parameter values | You specify exact values | Algorithm chooses from ranges |
| Design type | Fixed factorial/custom grid | Adaptive, iterative |
| Use case | Parameter sweeps, sensitivity analysis | Optimization, uncertainty quantification |
| Input format | {"x": [1, 2, 3]} (values) |
{"x": "[0;10]"} (ranges) |
Python API
Function Signature
import fz
result = fz.fzd(
input_path,
input_variables,
model,
output_expression,
algorithm,
calculators=None,
algorithm_options=None,
analysis_dir="analysis"
)
Parameters
| Parameter | Type | Description |
|---|---|---|
input_path |
str |
Path to input file or directory |
input_variables |
dict |
Variable ranges: {"var": "[min;max]"} or fixed: {"var": "value"} |
model |
dict or str |
Model definition or alias |
output_expression |
str |
Expression to evaluate (e.g., "pressure" or "r1 + r2 * 2") |
algorithm |
str |
Path to algorithm Python file |
calculators |
str or list |
Calculator URI(s) (default: ["sh://"]) |
algorithm_options |
dict, str, or None |
Algorithm options as dict, JSON string, or JSON file path |
analysis_dir |
str |
Analysis results directory (default: "analysis") |
Return Value
Returns a dictionary with:
| Key | Type | Description |
|---|---|---|
XY |
DataFrame |
All sampled input/output values |
analysis |
varies | Algorithm analysis results (HTML, plots, metrics) |
algorithm |
str |
Algorithm file path used |
iterations |
int |
Number of algorithm iterations completed |
total_evaluations |
int |
Total number of function evaluations |
summary |
str |
Human-readable summary text |
CLI Usage
Command Signature
fzd --input_path DIR --input_variables VARS --model MODEL \
--output_expression EXPR --algorithm ALGO \
[--results_dir DIR] [--calculators CALC] [--options OPTS]
Or using the main fz command:
fz design --input_path DIR --input_variables VARS --model MODEL \
--output_expression EXPR --algorithm ALGO [...]
CLI Options
| Option | Short | Required | Description |
|---|---|---|---|
--input_path / --input_dir |
-i |
Yes | Input file or directory path |
--input_variables / --input_vars / --variables |
-v |
Yes | Variable ranges (JSON file or inline JSON) |
--model |
-m |
Yes | Model definition (JSON file, inline JSON, or alias) |
--output_expression |
-e |
Yes | Output expression to optimize |
--algorithm |
-a |
Yes | Algorithm name (randomsampling, brent, bfgs, ...) or file path |
--results_dir |
-r |
No | Results directory (default: results_fzd) |
--calculators |
-c |
No | Calculator specifications (URI, alias, or JSON list) |
--options |
-o |
No | Algorithm options (JSON file or inline JSON) |
Flag aliases (since 1.1)
--input_path and --input_variables are the preferred names, consistent with fzi, fzc, and fzr.
The old --input_dir and --input_vars names remain accepted for backward compatibility.
Examples
Example 1: Random Sampling
Explore the parameter space with random sampling:
import fz
model = {
"varprefix": "$",
"delim": "()",
"run": "bash -c 'source input.txt && result=$(echo \"scale=6; $x * $x + $y * $y\" | bc) && echo \"result = $result\" > output.txt'",
"output": {
"result": "grep 'result = ' output.txt | cut -d '=' -f2 | tr -d ' '"
}
}
result = fz.fzd(
input_path="input/",
input_variables={"x": "[-2;2]", "y": "[-2;2]"},
model=model,
output_expression="result",
algorithm="examples/algorithms/randomsampling.py",
algorithm_options={"nvalues": 20, "seed": 42}
)
print(f"Total evaluations: {result['total_evaluations']}")
df = result['XY']
best = df.loc[df['result'].idxmin()]
print(f"Best: x={best['x']:.4f}, y={best['y']:.4f}, result={best['result']:.6f}")
Example 2: 1D Optimization (Brent's Method)
Find the minimum of a 1D function:
result = fz.fzd(
input_path="input/",
input_variables={"x": "[0;2]"},
model=model_1d,
output_expression="result",
algorithm="examples/algorithms/brent.py",
algorithm_options={"max_iter": 20, "tol": 1e-3}
)
df = result['XY']
best = df.loc[df['result'].idxmin()]
print(f"Optimal x = {best['x']:.6f} (expected: 0.7)")
Example 3: Multi-dimensional Optimization (BFGS)
Find the minimum of a multi-dimensional function with parallel evaluations:
result = fz.fzd(
input_path="input/",
input_variables={"x": "[-2;2]", "y": "[-2;2]"},
model=model,
output_expression="result",
algorithm="examples/algorithms/bfgs.py",
algorithm_options={"max_iter": 20, "tol": 1e-4},
calculators=["sh://bash calc.sh"] * 4 # 4 parallel evaluators
)
Example 4: Monte Carlo with Convergence
Run Monte Carlo sampling until a confidence interval target is reached:
result = fz.fzd(
input_path="input.txt",
input_variables={
"n_mol": "[0;10]",
"T_celsius": "[0;100]",
"V_L": "[1;5]"
},
model=perfectgas_model,
output_expression="pressure + 1",
algorithm="examples/algorithms/montecarlo_uniform.py",
calculators=["sh://bash PerfectGazPressure.sh"] * 10,
algorithm_options={
"batch_sample_size": 20,
"max_iterations": 50,
"confidence": 0.90,
"target_confidence_range": 1000000,
"seed": 123
},
analysis_dir="fzd_analysis"
)
Example 5: Custom Output Expression
Combine multiple model outputs in an expression:
result = fz.fzd(
input_path="input/",
input_variables={"x": "[-2;2]", "y": "[-2;2]"},
model=model_multi_output,
output_expression="r1 + r2 * 2", # Custom expression
algorithm="examples/algorithms/randomsampling.py",
algorithm_options={"nvalues": 20, "seed": 42}
)
Available expression operators: +, -, *, /, **, abs(), min(), max(), sqrt(), exp(), log(), pi, e.
Example 6: CLI Usage
# Random sampling
fzd --input_path input/ --model perfectgas \
--input_variables '{"x": "[-2;2]", "y": "[-2;2]"}' \
--output_expression "result" \
--algorithm examples/algorithms/randomsampling.py \
--options '{"nvalues": 20, "seed": 42}'
# Algorithm options from a JSON file
fzd --input_path input/ --model perfectgas \
--input_variables '{"x": "[-2;2]"}' \
--output_expression "result" \
--algorithm examples/algorithms/brent.py \
--options algo_config.json \
--results_dir optimization_results/
# As fz subcommand (short flags)
fz design -i input/ -m perfectgas \
-v '{"x": "[-2;2]", "y": "[-2;2]"}' \
-e "result" \
-a examples/algorithms/bfgs.py
Algorithm Options Formats
Algorithm options can be provided in three formats:
Input Variables: Ranges vs Fixed Values
input_variables accepts two kinds of entries:
| Format | Example | Behaviour |
|---|---|---|
| Range | "[min;max]" or "[min,max]" |
Handed to the algorithm; it decides which values to sample |
| Fixed | "5.0" (a plain number string) |
Constant — merged into every design point unchanged, never varied |
# x and y are explored; z is fixed at 1.5 for every evaluation
result = fz.fzd(
input_path="input/",
input_variables={"x": "[-2;2]", "y": "[-2;2]", "z": "1.5"},
...
)
Automatic Behaviors
Batch Deduplication
Within each iteration, duplicate design points proposed by the algorithm are evaluated only once. The results are re-mapped so the algorithm receives the correct output for every point it requested, including duplicates. This prevents redundant expensive evaluations when an algorithm proposes the same point twice.
Cross-Iteration Caching
Results from previous iterations are automatically reused — a point evaluated in iteration 2 is never re-run in iteration 5. No extra configuration is required.
Re-Run Resume
If analysis_dir already exists when fzd starts, it is renamed with a timestamp suffix (e.g., analysis_2026-04-27_10-30-00) and the original path is used for the new run. The renamed directory's iteration subdirectories are still added to the cache, so a re-run with different algorithm options benefits from all prior computations automatically.
# Re-run after an interrupted or exploratory first run — prior results reused as cache
result = fz.fzd(
input_path="input/",
input_variables={"x": "[-2;2]"},
algorithm="examples/algorithms/bfgs.py",
analysis_dir="my_analysis" # if exists → renamed; its cache still consulted
)
Available Algorithms
FZ ships with example algorithms in examples/algorithms/:
| Algorithm | File | Type | Best For |
|---|---|---|---|
| Random Sampling | randomsampling.py |
Exploration | Initial exploration, baselines |
| Brent's Method | brent.py |
1D optimization | Precise 1D root finding/optimization |
| BFGS | bfgs.py |
Multi-D optimization | Smooth multi-dimensional optimization |
| Monte Carlo | montecarlo_uniform.py |
Integration | Uncertainty quantification |
Choosing an Algorithm
- 1D problems: Use Brent's method
- 2-10D smooth problems: Use BFGS
- Exploratory / non-smooth: Use random sampling
- Uncertainty quantification: Use Monte Carlo
Writing Custom Algorithms
Custom algorithms must implement a Python class with the following interface:
class MyAlgorithm:
def __init__(self, options):
"""Initialize with algorithm-specific options dict."""
self.batch_size = int(options.get("batch_size", 10))
def get_initial_design(self, input_variables, output_variables):
"""Return initial list of sample points.
Args:
input_variables: dict of {"var_name": "[min;max]"} ranges
output_variables: list of output variable names
Returns:
List of dicts, each dict is one sample point:
[{"x": 1.0, "y": 2.0}, {"x": 3.0, "y": 4.0}, ...]
"""
pass
def get_next_design(self, X, Y):
"""Return next sample points or None to stop.
Args:
X: list of input dicts evaluated so far
Y: list of output values evaluated so far
Returns:
List of dicts for next batch, or None to stop iteration.
"""
pass
def get_analysis(self, X, Y):
"""Return analysis results (called at end).
Args:
X: all input dicts
Y: all output values
Returns:
HTML string, dict, or any serializable result.
"""
pass
Algorithm File Header
Algorithm files should include metadata in comments:
#title: My Algorithm Name
#author: Author Name
#type: sampling|optimization
#options: batch_size=10;max_iterations=100;seed=42
#require: numpy;scipy
See Also
- fzr - Run fixed parametric studies
- fzi - Parse input variables
- fzl - List available models/calculators
- Algorithm Options Example
- FZD Examples