Build a surrogate model with TRIM¶
Advanced tutorial
This walkthrough assumes you are comfortable with the core ado workflow — custom experiments, discovery spaces, and operations — and that you have already run at least one operation end-to-end. If you are new to ado, work through Your first ado experiment first.
When evaluating points in a parameter space is expensive — a scientific simulation, a machine learning training run, or a physical experiment — you often cannot afford to measure every configuration. The trim operator (Transfer Refined Iterative Modeling) solves this by building a predictive model that can estimate outcomes at unmeasured points. It gathers data intelligently, training and refining its model at each step, and halts once further sampling stops improving model accuracy.
This walkthrough uses the calculate_pressure_ideal_gas custom experiment — a simple Ideal Gas Law calculation — so the focus stays on ado and TRIM mechanics rather than the domain.
We will:
- Install the
trimoperator and the example custom experiment - Inspect the experiment interface
- Define a discovery space for pressure across temperature, volume, and moles
- Run TRIM to build a surrogate model
- Inspect the sampled measurements and the saved model
Prerequisites
ado-coreinstalled (pip install ado-core)- The example package cloned from GitHub (the wheel is not published to PyPI)
Clone the repository if you have not already done so:
git clone https://github.com/ibm/ado.git
cd ado
Then install the operator and experiment packages:
pip install ado-trim
pip install -e examples/trim/custom_experiments/
Python version compatibility
The trim operator is not available on Python 3.14 due to a dependency on autogluon==1.5.0, which requires pyarrow==20.0.0 (incompatible with Python 3.14). Use Python 3.10–3.13.
All commands in this walkthrough are run from the repository root (ado/).
TL;DR
Once the packages are installed:
ado create space -f examples/trim/example_yamls/space_pressure.yaml --new-sample-store
ado create operation -f examples/trim/example_yamls/op_pressure.yaml --use-latest space
ado show related space --use-latest
ado show measurements space --use-latest
Step 1 — Install the required packages¶
The trim operator¶
The trim operator is distributed as a separate package:
pip install ado-trim
Confirm it is registered:
ado get operators
You should see trim listed:
Available operators by type:
┌───────┬─────────────┬─────────┬────────────┐
│ INDEX │ OPERATOR │ VERSION │ TYPE │
├───────┼─────────────┼─────────┼────────────┤
│ 0 │ random_walk │ 2.0.0 │ explore │
│ 1 │ ray_tune │ 2.0.0 │ explore │
│ 2 │ rifferla │ 2.0.0 │ modify │
│ 3 │ trim │ 2.0.3 │ characterize│
└───────┴─────────────┴─────────┴────────────┘
The calculate_pressure_ideal_gas custom experiment¶
The example ships a custom experiment that computes gas pressure from the Ideal Gas Law: P = nRT/V.
Install it from the example directory:
pip install -e examples/trim/custom_experiments/
Confirm ado can see it:
ado get experiments
You should see calculate_pressure_ideal_gas listed under custom_experiments.
Inspect the experiment interface:
ado describe experiment calculate_pressure_ideal_gas
Identifier: custom_experiments.calculate_pressure_ideal_gas@1.0.0
Version: 1.0.0
Required Inputs:
Constitutive Properties:
─────────────────────────────────────────────────────────────────
Identifier: mol
Domain:
Type: CONTINUOUS_VARIABLE_TYPE
Range: [0.01, 10]
─────────────────────────────────────────────────────────────────
─────────────────────────────────────────────────────────────────
Identifier: temperature
Domain:
Type: CONTINUOUS_VARIABLE_TYPE
Range: [1, 400]
─────────────────────────────────────────────────────────────────
─────────────────────────────────────────────────────────────────
Identifier: volume
Domain:
Type: CONTINUOUS_VARIABLE_TYPE
Range: [1, 100]
─────────────────────────────────────────────────────────────────
Outputs:
──────────────────────────────────────────────────────────────────────
calculate_pressure_ideal_gas@v1-pressure
──────────────────────────────────────────────────────────────────────
The three required inputs (mol, temperature, volume) map to entity-space dimensions. The single output, pressure, is the target property TRIM will model.
Step 2 — Define a discovery space¶
The file examples/trim/example_yamls/space_pressure.yaml defines a three-dimensional discrete space spanning temperature (270–300 K), volume (1–10 m³), and moles (0.1–1.0 mol), with calculate_pressure_ideal_gas as the measurement:
ado create space -f examples/trim/example_yamls/space_pressure.yaml --new-sample-store
Success! Created space with identifier: space-bfed2d-19b49a
Inspect the space to confirm the entity and measurement spaces are correct:
ado describe space --use-latest
Identifier: 'space-bfed2d-19b49a'
Entity Space:
Discrete properties:
name ┃ range ┃ interval
━━━━━━━━━━━━━╋━━━━━━━━━━━━━╋━━━━━━━━━━
temperature ┃ [270, 300] ┃ 2
volume ┃ [1, 10] ┃ 1
mol ┃ [0.1, 1.0] ┃ 0.1
Measurement Space:
Experiments:
base identifier ┃ required major version
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━
custom_experiments.calculate_pressure_ideal_gas ┃ v1
Sample Store identifier: 19b49a
Tip
The entity space has discrete dimensions, so ado can enumerate all possible entities in advance. TRIM leverages this to guide its sampling strategy — it knows exactly which points are unmeasured and selects the most informative ones to probe next.
Step 3 — Run TRIM¶
The file examples/trim/example_yamls/op_pressure.yaml configures a TRIM characterization run:
ado create operation -f examples/trim/example_yamls/op_pressure.yaml --use-latest space
TRIM logs its progress to the terminal as it runs. There are three distinct stages to watch for.
Stage 1 — No-priors characterization¶
Since the sample store starts empty, TRIM cannot immediately build a model. It logs this and begins an initial characterization phase using Concatenated Latin Hypercube Sampling (clhs) to collect a representative baseline:
2026-07-09 15:35:48,452 WARNING MainThread trim.samplers.no_priors_utils: No measured properties found in the discovery space
2026-07-09 15:35:48,470 WARNING MainThread trim.operator: Only 0 points in the source space.
Starting with no-prior characterization operation, it will sample 18 points.
You will see output for each point being submitted and completed:
(RandomWalk pid=74822) Continuous batching: SUBMIT EXPERIMENT. Submitted experiment
custom_experiments.calculate_pressure_ideal_gas for mol.0.7-temperature.272-volume.1.
(RandomWalk pid=74822) Continuous Batching: EXPERIMENT COMPLETION. Received finished notification for
experiment in measurement request in group 1: request-4f70cf-...
Stage 2 — Iterative modeling¶
Once the baseline is collected, TRIM enters its main loop. In each iteration it samples a new point guided by the current model, retrains AutoGluon, and evaluates whether accuracy is still improving:
(RandomWalk pid=76621) AutoGluon training complete, total runtime = 1.49s ...
Best model: WeightedEnsemble_L2 | Estimated inference throughput: 508.6 rows/s
After every iterationSize iterations (5 in op_pressure.yaml), TRIM checks the stopping criterion:
(RandomWalk pid=10736) Testing stopping criterion after measuring 14 points, mean_ratio=... std_ratio=...
(RandomWalk pid=10736) Stopping not triggered for i=14
Stage 3 — Finalizing¶
When the stopping criterion is met, TRIM trains one high-quality model on all data collected and saves it to the outputDirectory:
(RandomWalk pid=10736) Stopping criteria hit after measuring 22 entities.
(RandomWalk pid=10736) Finalizing the predictive model: Fitting AutoGluon TabularPredictor on full Source Space data of 42 rows. Model will be saved in: trim_models_finalized
(RandomWalk pid=10736) Final model root_mean_squared_error=-48.72586662062896. Saving predicted model to: trim_models_finalized.
The operation ends with a success message:
Success! Created operation with identifier operation-trim@2.0.3-cb3448b3 and it finished successfully.
Key TRIM parameters
The op_pressure.yaml file controls TRIM's behaviour:
targetOutput— the experiment output property to model (pressure)outputDirectory— where the finalAutoGluonmodel is savediterationSize— how many points to sample before checking the stopping criterionstoppingCriterion.meanThreshold/stdThreshold— model-quality thresholds that trigger early stoppingautoGluonArgs— passed directly toAutoGluon'sTabularPredictor
See the TRIM operator reference for the full parameter list.
Step 4 — Inspect the results¶
Sampled measurements¶
To see every point TRIM evaluated, along with its measured pressure value:
ado show measurements space --use-latest
┌───────┬────────────────┬────────────────┬────────────────┬─────────────┬────────┬─────┬───────────────┐
│ INDEX │ identifier │ generatorid │ experiment_id │ temperature │ volume │ mol │ pressure │
├───────┼────────────────┼────────────────┼────────────────┼─────────────┼────────┼─────┼───────────────┤
│ 0 │ mol.0.1-tempe… │ no_priors_cha… │ custom_experi… │ 270 │ 1 │ 0.1 │ 224.49049068… │
│ 1 │ mol.0.1-tempe… │ no_priors_cha… │ custom_experi… │ 274 │ 2 │ 0.1 │ 113.90813786… │
│ 2 │ mol.0.1-tempe… │ no_priors_cha… │ custom_experi… │ 280 │ 3 │ 0.1 │ 77.601651101… │
│ ... │ ... │ ... │ ... │ ... │ ... │ ... │ ... │
│ 72 │ mol.0.9-tempe… │ no_priors_cha… │ custom_experi… │ 298 │ 9 │ 0.9 │ 247.77098601… │
└───────┴────────────────┴────────────────┴────────────────┴─────────────┴────────┴─────┴───────────────┘
The generatorid column shows which sub-operation produced each measurement. TRIM runs two internal sub-operations: one for no-priors characterization (no_priors_characterization) and one for iterative modeling. You can inspect the full sub-operation hierarchy with:
ado show related space --use-latest
The saved surrogate model¶
TRIM saves the final AutoGluon model to the directory specified by outputDirectory (trim_models by default). Load it in Python to make predictions at unmeasured points:
from autogluon.tabular import TabularPredictor
predictor = TabularPredictor.load("trim_models")
# Predict pressure for an unmeasured configuration
result = predictor.predict({"mol": 0.5, "temperature": 285, "volume": 4})
print(result)
Tip
The surrogate model covers the entire entity space, including the points that were never directly measured. This is the core value of TRIM: you pay for a small fraction of measurements, but get predictions everywhere.
Summary¶
| Step | What you did | ado concept |
|---|---|---|
| 1 | Installed trim and the custom experiment | Operator / custom experiment |
| 2 | Defined a three-dimensional discrete discovery space | Discovery space |
| 3 | Ran TRIM to characterize the space and train a surrogate model | Operation / trim operator |
| 4 | Retrieved the sampled measurements and loaded the saved model | ado show measurements / AutoGluon |
Going further¶
Try extending this example:
- Tune the stopping thresholds — tighten
meanThreshold/stdThresholdfor a more accurate model (at the cost of more samples), or loosen them for a faster run; seeexamples/trim/example_yamls/quick_exploration.yamlfor a pre-configured fast variant andhigh_quality_characterization.yamlfor a high-accuracy variant - Budget the sampling — add a
samplingBudgetblock withminPointsandmaxPointsto set hard limits on how many measurements TRIM can make - Switch the initial sampler — set
noPriorsParameters.sampling_strategytosobolinstead ofclhsto use Sobol sequences for the baseline - Improve final-model quality — configure
finalModelAutoGluonArgsseparately fromautoGluonArgsto give the final fit more time and better presets than the intermediate models - Bring your own data — if you already have measurements in a sample store from a previous
random_walkoperation, TRIM will skip the no-priors phase and move directly to iterative modeling - Apply TRIM to a real workload — replace
calculate_pressure_ideal_gaswith an actuator-based experiment (e.g. SFT Trainer throughput) to build a surrogate model for a genuinely expensive system
See the TRIM operator reference for the full configuration reference and debugging guidance.
What's next¶
-
Discovering important entity space dimensions
Use
adoto identify which entity space dimensions most influence a target metric — a natural complement to TRIM's surrogate model. -
Search a space with an optimizer
Use
ray_tuneto drive an optimizer over a continuous space and locate the best configuration.