FE-1408: Run a trial as multiple seeded simulations aggregated by mean - #9223
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
2 Skipped Deployments
|
797689e to
ec38102
Compare
ec38102 to
8b4144f
Compare
PR SummaryMedium Risk Overview The returned Docs ( Reviewed by Cursor Bugbot for commit 1e8fcb6. Bugbot is set up for automated code reviews on this repo. Configure here. |
There was a problem hiding this comment.
Pull request overview
Adds deterministic multi-seed optimization trials to the Petrinaut CLI, aggregating replicate objectives by mean.
Changes:
- Runs sequential simulations using reusable derived seeds.
- Returns mean objectives and per-seed replicate results.
- Adds protocol, bundle, and unit coverage plus documentation.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
turbo.json |
Builds CLI before unit tests. |
optimization.ts |
Implements seeded trial evaluation and aggregation. |
optimization.test.ts |
Tests seeds, aggregation, and validation. |
transports.test.ts |
Tests multi-seed stdio responses. |
built-cli.test.ts |
Adds bundled CLI smoke test. |
README.md |
Documents multi-seed evaluation. |
OPTIMIZATION_INTEGRATION.md |
Documents protocol and seed derivation. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
8b4144f to
cbb5fca
Compare
cbb5fca to
1e8fcb6
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 7 out of 7 changed files in this pull request and generated no new comments.
Suppressed comments (1)
libs/@hashintel/petrinaut-cli/src/runtime/optimization.ts:275
- The online update still overflows for opposite-signed finite values:
[Number.MAX_VALUE, -Number.MAX_VALUE]computes-MAX_VALUE - MAX_VALUEon the second iteration and returns-Infinity, although the mean is0. The transports then serialize that objective asnull(src/commands/stdio.ts:57). Use a sign-aware update that avoids both overflowing sums and differences, and cover this opposite-sign boundary case.
const objective = replicates.reduce(
(mean, replicate, index) =>
mean + (replicate.objective - mean) / (index + 1),
Optimization trials run execution.seedsPerTrial seeded simulations
sequentially within one evaluate and aggregate the per-seed objectives
by mean. Seeds derive deterministically from execution.seed - replicate
0 keeps the base seed, later replicates reuse the Monte Carlo
derivation - and every trial reuses the same list, so Optuna compares
configurations under common random numbers. The evaluate response stays
{objective}-compatible and reports per-seed replicates; describe
reports seedsPerTrial. Parallelising the seeded runs is deferred to the
shared experiment-backend interface (FE-1341) so the CLI and the editor
share one worker story instead of a CLI-specific pool.
1e8fcb6 to
90ea6b1
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 7 out of 7 changed files in this pull request and generated no new comments.
Suppressed comments (1)
libs/@hashintel/petrinaut-cli/src/runtime/optimization.ts:275
- This online-mean formula still overflows for finite objectives with opposite signs:
[Number.MAX_VALUE, -Number.MAX_VALUE]makesreplicate.objective - meanequal-Infinity, so the protocol returns a non-finite aggregate (serialized asnull) instead of the correct mean0. Use a same-sign incremental update and a weighted form for opposite signs, and cover this boundary case alongside the existing overflow test.
const objective = replicates.reduce(
(mean, replicate, index) =>
mean + (replicate.objective - mean) / (index + 1),
🌟 What is the purpose of this PR?
Optimization trials currently run one simulation with the fixed
execution.seed, so a stochastic net is scored on a single replicate. This PR makes the Petrinaut CLI run a trial'sexecution.seedsPerTrialseeded simulations — sequentially — and aggregate the per-seed objectives by mean, keeping the{objective}response shape so the Python service needs no logic changes. Simulator side of FE-1273; aggregation-method selection (FE-1277) and Optuna-side handling of per-seed values (FE-1281) are out of scope.Parallelising the seeded runs is deliberately not done here: it will come through the shared experiment-backend interface (FE-1341/#9178) so the CLI and the editor share one worker story instead of a CLI-specific pool.
Stack #9226: FE-1410 (contract) → FE-1411 (async-safe protocol) → this PR → arch-docs manual → FE-1270 (Python bindings) → FE-1412 (Python client support).
🔗 Related links
🔍 What does this change?
@hashintel/petrinaut-clionly:optimization.evaluateruns the trial's seeds sequentially and returns their mean objective plus areplicates: [{ seed, objective }]array;optimization.describereportsstudy.seedsPerTrial. A trial's wall-clock time grows linearly withseedsPerTrial.execution.seed(M=1 stays bit-identical to today, and one editor run still reproduces a trial replicate), replicate i uses the exported Monte CarloderiveRunSeed(seed, i). Every trial reuses the same list → common random numbers across Optuna steps.dist/cli.jsand checks the full describe/evaluate exchange, including a two-seed trial.Pre-Merge Checklist 🚀
🚢 Has this modified a publishable library?
This PR:
@hashintel/petrinaut-cliis private; the@hashintel/petrinaut-corechangeset landed with FE-1410)📜 Does this require a change to the docs?
The changes in this PR:
OPTIMIZATION_INTEGRATION.mdand the CLI README document the field, seed derivation, and response shape. The in-app user guide is untouched: the UI never setsseedsPerTrialyet, so in-app behaviour is unchanged until FE-1273's UI half lands.🕸️ Does this require a change to the Turbo Graph?
The changes in this PR:
turbo.json's have been updated to reflect thispetrinaut-cli'stest:unitnow depends on its ownbuild, so the built-CLI smoke test always runs against a fresh bundle in CI.🐾 Next steps
seedsPerTrial, which sequential execution makes essential.🛡 What tests cover this?
optimization.test.ts— mean aggregation, per-seedreplicates, identical seed list across trials (CRN), non-finite replicate rejection,deriveTrialSeedsrange/stability/uniqueness.transports.test.ts— end-to-end multi-seed evaluate over stdio,seedsPerTrialin describe.built-cli.test.ts— spawns the real bundled CLI and checks the full describe/evaluate exchange with two seeds.❓ How to test this?
turbo run test:unit --filter @hashintel/petrinaut-cli"seedsPerTrial": 4toexecutioninlibs/@hashintel/petrinaut-cli/examples/supply-chain-profit-optimization.json,yarn workspace @hashintel/petrinaut-cli build, thennode libs/@hashintel/petrinaut-cli/dist/cli.js serve --optimization <manifest> --stdioand send anoptimization.evaluaterequest.objectiveplus fourreplicates, and that repeating the request returns identical values.🤖 Generated with Claude Code