Fix input-derivative pairing; default to inline linear-SCC reassembly#83
Merged
Conversation
Add DEFAULT_LINEARIZE_KWARGS passing reassemble_alg = DefaultReassembleAlgorithm(; inline_linear_sccs = true, analytical_linear_scc_limit = 1) to every linearization-based function (named_ss, get_named_sensitivity and friends, batch_ss/batch_linearize, trajectory_ss, build_quadratic_cost_matrix). The numerical linear-SCC fallback in generated code can produce silently rank-deficient linearizations on models with large linear SCCs (observed on a planar two-joint robot, where the two torque-input columns of the loop transfer came out numerically identical, collapsing the input complementary sensitivity to a rank-1 projector instead of I at low frequency). Caller-supplied keyword arguments take precedence, so the ModelingToolkit default remains reachable. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W4JdEEqr6ifdSbp6MvbrU8
MTK's linearize with allow_input_derivatives = true returns B with 2nu columns where column nu + i is the derivative of input i. The pairing passed to causal_simplification was derived by broadcasting 1:nu against the set of NONZERO derivative columns, which silently pairs every input to the same derivative channel when exactly one column is nonzero (and errors for other partial subsets). This produced wrong linearizations whenever inputs enter retained algebraic equations, e.g. through the numerical (non-inlined) linear-SCC reassembly: on a planar two-joint robot the input complementary sensitivity collapsed to a rank-1 projector instead of I at low frequency. The pairing is now positional over all inputs; all-zero derivative columns contribute nothing. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W4JdEEqr6ifdSbp6MvbrU8
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.
Two changes to the linearization pipeline, found while linearizing a planar two-joint robot (a model whose large linear SCCs take the numerical LinearSolve-based path under the default reassembly).
Fix: input-derivative column pairing in
causal_simplificationcall sitesModelingToolkit.linearizewithallow_input_derivatives = truereturnsBwith2nucolumns, where columnnu + iis the derivative of inputi. The pairing passed tocausal_simplificationwas derived by broadcasting1:nuagainst the set of nonzero derivative columns:When exactly one derivative column is nonzero this silently broadcasts to
[1 => k, 2 => k, ...], pairing every input to the same derivative channel; other partial subsets throw aDimensionMismatch. The result is a wrong reduced system whenever inputs enter retained algebraic equations. On the robot, the input complementary sensitivity collapsed to a rank-1 projector (Ti(0) ≈ [1 1; 0 0]instead ofI), i.e. the loop transfer's input columns came out identical.The pairing is now positional over all inputs,
[i => i + nu for i in 1:nu]; all-zero derivative columns contribute nothing (and filtering them out is not an option, sincecausal_simplificationinfers the input count from the number of pairs).Verified on a minimal 5-equation model with a 3×3 linear SCC and two inputs: the numerically-reassembled linearization now matches the symbolically-inlined one to a relative error of 6e-16 (previously ~100% error); the robot's input complementary sensitivity matches to 8e-13 across frequency.
Default: inline linear-SCC reassembly for all linearizations
DEFAULT_LINEARIZE_KWARGS = (; reassemble_alg = DefaultReassembleAlgorithm(; inline_linear_sccs = true, analytical_linear_scc_limit = 1))is now forwarded by every linearization-based function (named_ss,get_named_sensitivity/get_named_comp_sensitivity/get_named_looptransfer,batch_ss/batch_linearize,trajectory_ss,build_quadratic_cost_matrix). Caller-supplied keyword arguments take precedence, so the ModelingToolkit default remains reachable.With the pairing fix above, both reassembly paths produce correct linearizations; the inline default is kept because it avoids the input-derivative-augmented form entirely (no spurious marginal modes, better conditioned realizations) on models with linear SCCs.
🤖 Generated with Claude Code