feat: resolve symbolic loop-opening op values from the solution - #4894
Open
baggepinnen wants to merge 3 commits into
Open
feat: resolve symbolic loop-opening op values from the solution#4894baggepinnen wants to merge 3 commits into
baggepinnen wants to merge 3 commits into
Conversation
Values in `LinearizationOpPoint.op` may now be symbolic expressions, e.g. `opened_signal => driving_signal`, which are evaluated from the solution at each time point. This linearizes the opened signal around the value it has in the loop-closed solution, which is the natural operating point when linearizing along a trajectory. Previously such values were passed through verbatim: they either errored at problem construction (eager varmap evaluation), or silently resolved via `getu(prob, v)(prob)` against a `prob.u0` that is only refreshed by initialization inside `solve`, yielding a constant stale linearization at every time point. Also skip `missing` op values in `__linearize_multiple_op_barrier`, mirroring the skip added to single-point `linearize` in #4855. Closes the symbolic-value half of #4830. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SWPXe76HwiugWWyLP7BYrL
Co-authored-by: Aayush Sabharwal <aayush.sabharwal@gmail.com>
Co-authored-by: Aayush Sabharwal <aayush.sabharwal@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements the symbolic-value half of #4830 (the
missinghalf was implemented in #4855).What
Values in
LinearizationOpPoint.opmay now be symbolic expressions, e.g.op = Dict(opened_signal => driving_signal), which are evaluated from the wrapped solution at each time point. Mapping an opened signal to the expression that drives it thus linearizes around the value the opened signal has in the loop-closed solution — the natural operating point when linearizing along a trajectory withloop_openings.Why resolve in
_build_op_from_solutionPreviously, symbolic values were passed through verbatim, and depending on the model they either
MTKParametersevaluates operating-point values eagerly before any initialization has run ("Could not evaluate value of parameter … Missing values for variables in expression …"), or_resolve_op_valueroutes symbolic values throughgetu(prob, v)(prob), but state values are written asInitial(x)parameters andprob.u0is only refreshed by initialization insidesolve, so the observed function evaluates against the construction-time state at every iteration of__linearize_multiple_op_barrier.Resolving symbolic values against the solution inside
_build_op_from_solution(once per value for all time points) means the downstream machinery — problem construction and the per-point setters — only ever sees numbers, avoiding both failure modes as well as any sensitivity to dict iteration order.On a plant/controller loop where the controller dynamics are nonlinear in its input, the new test verifies that the per-point linearizations exactly match ground truth (and match single-point linearizations with manually resolved numeric values), where previously they were constant along the trajectory.
Also
missingop values are now skipped in__linearize_multiple_op_barrier, mirroring the skip added to single-pointlinearizein feat: allow passingmissingfor loop opening variables inlinearize#4855 (they previously threwconvert(Float64, ::Missing)in the multi-timepoint path).LinearizationOpPointand the_check_loop_opening_operror message updated to mention symbolic values.Not addressed (out of scope): symbolic op values in plain
linearizewithout a solution still error at problem construction; supporting that would require initialization-level changes.🤖 Generated with Claude Code
https://claude.ai/code/session_01SWPXe76HwiugWWyLP7BYrL