Integrate structured parameters into simulation#211
Integrate structured parameters into simulation#211TimothyWillard wants to merge 4 commits intomainfrom
Conversation
jc-macdonald
left a comment
There was a problem hiding this comment.
LGTM — one bug to fix in the docs engine, and a minor note on dead code in _sample_parameter.
| @@ -47,6 +56,9 @@ def runner( | |||
| msg = f"times[0] must be >= 0; got times[0]={times[0]}" | |||
| raise ValueError(msg) | |||
|
|
|||
| y0 = np.stack([ | |||
| initial_state[name].value for name in model_state.parameter_names | |||
| ]).astype(np.float64) | |||
| args = tuple(val for val in params.values()) if params is not None else None | |||
| result = solve_ivp( | |||
There was a problem hiding this comment.
params values are now ParameterValue objects, which have no arithmetic dunders. When solve_ivp forwards these as positional args to the stepper, beta * y_s * y_i raises TypeError: unsupported operand type(s) for *: 'ParameterValue' and 'float'. Needs unwrapping:
args = tuple(val.item() for val in params.values()) if params is not None else None| msg = "parameter_configs must be set before resolving parameters." | ||
| raise ValueError(msg) | ||
| if name not in self.parameter_configs: | ||
| if request.optional: |
There was a problem hiding this comment.
Nit: this branch raises KeyError for a missing optional parameter, but resolve_inputs() already guards missing optionals with continue before calling _sample_parameter — so the request.optional branch here is dead code. Not blocking, just a heads-up.
fb95ed2 to
5308e9b
Compare
5308e9b to
87fa852
Compare
Added the `axis` module for realizing and manipulating axes from configuration. Includes: - `ResolvedShape` as a container for metadata about the shape of an object based on its axes. - `Axis` as a data class for a realized axis that objects which need axes can use to do their calculations. - `AxisCollection` as a mapping of `Axis` objects that simplify access when multiple axes are needed. - Dropped deprecation warning from using the `axes` attribute of `ConfigurationModel`. Follow up to #147, #164.
Introduced `ParameterValue` as the return type for `ParameterABC.sample` that contains the underlying value as a numpy array as well as metadata, which at this point is the `ResolvedShape`. This container type is extensible for further metadata in the future such as type info and could easily be converted to a generic to generalize the underlying value, e.g. to use jax arrays or similar. Also added `ModelStateSpecification`, `ParameterRequest` as a way for systems to specify their underlying state and shape as well as request parameters that match that specification. However, this is not connected to systems yet. Currently the shapes are not utilized in simulation, but existing engines/systems should work as is due to the simulate command reducing parameters to scalars before calling `Simulator.run`
Added `SystemABC.requested_parameters()/model_state()` to allow systems to provide information about their underlying state specification, including shape, as well as request parameters that comply with said requirements. Also integrated this work into the existing wrapper system to demonstrate the functionality. - Added `requested_parameters()/model_state()` methods to `SystemABC`. - Extended `wrap()`/`_AdapterSystem` to accept explicit parameter request and model state callbacks. - Updated `_checked_partial()` so already materialized `ParameterValue` instances are preserved when binding static parameters. - Simplified the documentation quick start wrapper config to the minimal valid example.
It pushes `ParameterValue` and model-state handling through the simulator and engine interfaces so simulation, external providers, and the docs example all execute against the same structured parameter contract. - Updated `EngineABC` and the engine protocol to run against structured `initial_state`, `params`, and optional `model_state`. - Removed the engine protocol from `flepimop2.typing` and keep the engine specific contract alongside `engine.abc` and allow it to depend on `ParameterValue`. - Adapted wrapper engine fixtures and tests to assemble numeric state from `ModelStateSpecification` and `ParameterValue` inputs. - Wired the simulator and CLI flow through resolved structured inputs instead of hard-coded scalar state assembly. - Added external-provider integration coverage for axis-aware state and a linear parameter source.
87fa852 to
818ff28
Compare
| def _scenario_value( | ||
| value: object, | ||
| template: ParameterValue | None = None, | ||
| ) -> ParameterValue: | ||
| shape = template.shape if template is not None else ResolvedShape() | ||
| return ParameterValue(np.asarray(value, dtype=np.float64), shape) |
There was a problem hiding this comment.
This is temporary, I think ideally scenarios would also emit ParameterValue by default so scenarios could override parameters and the rest of flepimop2 could just consume them as the same thing.
It pushes
ParameterValueand model-state handling through thesimulator and engine interfaces so simulation, external providers, and
the docs example all execute against the same structured parameter
contract.
EngineABCand the engine protocol to run against structuredinitial_state,params, and optionalmodel_state.flepimop2.typingand keep theengine specific contract alongside
engine.abcand allow it to dependon
ParameterValue.from
ModelStateSpecificationandParameterValueinputs.instead of hard-coded scalar state assembly.
a linear parameter source.