Feat/schema improvements and optimization - #95
Conversation
|
Thank you for this — the overall direction is right. Putting the search loop outside the workflow, the file-based ledger that a person, the GUI, or an agent can all read and steer, and the per-population firing-rate / ISI outputs on the analysis node are all things users will benefit from, optimization or not. The reasoning captured in the docs is also a real asset for whoever touches this next. Before merging I'd like to settle one design question and fix a handful of things that would bite users on first use. I'm listing them symptom-first. I also have a detailed, file-by-file list and will hand it over in stages so this doesn't have to be fixed all at once. One design question to settle firstThe PR currently describes three different homes for "what to explore and what to hit":
The GUI work depends heavily on which of these is the intended model, so I'd rather pick one now than build the panel on the wrong one. My preference is the handoff-document version (study lives in the optimization node, referencing nodes by id), and dropping Things that would bite users on first use
Smaller things worth fixing in the same pass
Housekeeping
Let's hold off on merging until the design question above is settled — thanks again for the careful work here. Reviewed with the help of Claude Code. |
Treat NaN as a failed trial, complete injected candidates, pass CMA-ES popsize, restrict connection_rule strings to lambdas, and default NW_Optimization to random so a search runs without Optuna. Add toy-node tests, strip notebook outputs, and document that GUI generate-code and the nest image extra remain follow-ups.
|
Audit on this branch (engine harden, not a rewrite): the outer-loop search is applicable and reasonable. I pushed first-use fixes: NaN is a failed trial (not “in target”), inject completes missing dims and records Open question for @carlosengutierrez (please do not merge until this is answered): where does the study live — per-parameter GUI generate-code and adding |
|
@carlosengutierrez — one decision is needed from you before this can move, and it is a product question, not a code one. Where should a user set up an optimization?
Both work with the engine you wrote; the difference is what users will see in the GUI, and the GUI panel has to be built for one of them. Kirill has already fixed the correctness items from my review, so this is the only thing holding the PR. If I don't hear back by Tuesday, September 16, I'll go ahead with A and adjust the docs and the |
Adds parameter optimization to Neuro-Workflow: a search loop that runs an existing workflow
repeatedly, tunes declared parameters and reports how close each run lands to a declared target.
A workflow is a DAG that runs once; a search is a loop that runs it many times, so the loop sits
outside the graph rather than becoming a node inside it.
What is here
src/neuroworkflow/optimization/— the engine: dotted addressing (Node.parameter[.key]totune,
Node.output_port[.key]to measure), the spec, a file-based ledger, and optimizer backends(random plus Optuna's CMA-ES, TPE, NSGA-II/III). Single-objective backends refuse a
multi-objective spec rather than inventing weights between objectives.
NW_Optimizationnode — declares how to search: algorithm, budget, seed. No ports and noprocess steps, so a workflow containing it executes exactly as it would without it. Its presence
on the canvas is the signal for the generator to emit an optimization run instead of a single
execution. Replaces
JointOptimizationNode, which was an in-graph grid search.NW_SimConfigrebuilds the SONATA network only whensomething structural changed, so a search does not rebuild it once per trial. Nodes opt in with
REUSABLE_PATHS; the engine itself stays domain-free.NW_Analysis—firing_rate_hzandisi_statsper population, so a targethas something to be compared against.
unitandmeasuresonParameterDefinition;optimization_rangeaccepts aper-key dict for dict-valued parameters. Each node instance now carries its own
NODE_DEFINITIONcopy, so markingexcoptimizable no longer affectsinh.Reporting across objectives in different units
A miss in Hz and a miss in ms cannot be added. Each objective reports its own miss in its own unit,
and the single comparable figure is the worst objective's miss divided by the width of its target
range — printed as
furthest from target: probe_isi, 1.4x its target rangeand stored astarget_ranges_off. Pareto dominance is scale-free and NSGA-II rescales internally, so thisaffects reporting and ranking only; what the optimizer is told stays raw and per-objective.
Docs and examples
docs/OPTIMIZATION.mdfor how the engine works,docs/OPTIMIZATION_GUI_HANDOFF.mdfor the GUIhalf. Five notebooks under
notebooks/, two of which show what the code generator should emit.Not done, and needed before the GUI can use this
optunaandcmaesare not in the nest kernel image.NW_Optimizationdefaults tocmaes,so the first optimization generated in the GUI fails on import until one line is added at
Dockerfile.nest:128. Left out of this PR because it forces a rebuild of the nest image; it iswritten up as step 1 of the handoff document.
Testing
Single- and multi-objective searches run end to end in Jupyter against real NEST/BMTK, and with toy
nodes for the engine paths. GUI copies under
codes/are synced and byte-identical tosrc/.