Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

Inline linear SCCs: 296×296 dense runtime solve for an ~18-unknown core; non-rank-tolerant; symbolic shrinkage intractable — solve sparse+rank-tolerant instead

オープン
#95 コメント 6 件 リアクション 0 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

評価

難易度
5/5
見積もり時間
1週間以上
初心者へのやさしさ
35/100
issue の種類
バグ
明瞭さ
おおむね明確
活発さ
静か
技術スタック
julia

調査の方向性

get_linear_scc_linsol から開始し、ArrayMaker リージョンが生成された疎性パターンをどのように公開しているか、また __reduce_linear_system! がランタイムの求解にどのように入力を渡しているかを調べます。シンボリックなゼロ除去の失敗については、別途 get_new_mm を確認します。生成されたシステムが、シンボリックな肥大化、dense-LU の特異性による失敗、または無言の Inf 結果なしに、疎でランク許容のランタイム求解を使用すれば完了です。

索引モデルが issue の本文から書いたものです。

説明

Summary

For multibody vehicle models, the inline-linear-SCC pass (DefaultReassembleAlgorithm(inline_linear_sccs = true)) emits a runtime dense A \ b over a system that is an order of magnitude larger than the mathematically-required core, and solves it with a non-rank-tolerant dense LU. Measured on a half-car suspension model (22 states after mtkcompile):

  • The big algebraic SCC enters get_linear_scc_linsol with 396 rows.
  • __reduce_linear_system! removes only 101 (the all-constant-coefficient rows) → a 296×296 dense runtime LU, evaluated every RHS call and during initialization reconstruction.
  • Of the 396 rows, 384 are matched (torn) and 378 of those have a constant pivot coefficient — i.e. the irreducible simultaneous core is only ~18–24 unknowns (consistent with the same model compiled with inline_linear_sccs=false, which yields a 48-state DAE = 22 differential + 26 algebraic).
  • The emitted 296×296 pattern is 1.6% dense and, after a Dulmage–Mendelsohn analysis, ~93% block-triangular given the tearing order; only the small core is truly coupled.

The inflation mechanism: rows whose non-pivot coefficients are symbolic (every product-rule-differentiated definitional equation — rotation-matrix entries, contact-frame vectors, etc.) fail the all(isconst, coeffs) gate in __reduce_linear_system! and are kept inside the numeric solve, even though tearing already matched them with constant pivots.

Why the obvious fix doesn't work (tested)

Relaxing the gate to "pivot coefficient constant" (which is sufficient for a division-free elimination, and the alias/substitution machinery in __reduce_linear_system!/get_new_mm handles symbolic alias coefficients as-is) shrinks the system but explodes symbolically:

  1. First failure: iszero(::Num) inside get_new_mm's duplicate-entry pruning goes through fraction_iszero → expand, which is exponential for the deep product-of-sums coefficients → OutOfMemoryError. (Workaroundable with a cheap syntactic zero test — see suggestion below.)
  2. With that bypassed, mtkcompile succeeds (~90 s) but ODEProblem construction stalls indefinitely: the substituted core coefficients are enormous expression trees and codegen blows up.

So full symbolic elimination of the torn rows is intractable; the inflation is an inherent artifact of numeric tearing. Sequential runtime evaluation of the eliminated rows is also impossible (they depend on the core unknowns — circular).

Suggested fixes

  1. Solve the emitted system sparse and rank-tolerant at runtime. The pattern is already available (the ArrayMaker regions); a sparse LU/QR with fill-reducing ordering automatically exploits the ~93% triangular structure, so the 296-system costs about as much as the 18-core. Crucially it should be rank-revealing (or regularized): these acceleration/reaction systems are legitimately rank-deficient whenever constraint reactions are statically indeterminate (vehicle with ≥2 rigid suspension mounts on one body) — the current dense \ throws SingularException (LU) and the DyadCompilerPasses LDIV rewrite produces silent Inf (unpivoted QR). See JuliaComputing/DyadCompilerPasses.jl#40.
  2. Independent robustness improvement: the duplicate-entry pruning in get_new_mm should use a cheap syntactic zero test (term construction already cancels syntactically identical terms; an entry that is mathematically zero but kept is harmless), e.g. an overridable prune_iszero(x) = iszero(x) specialized for Num to a syntactic check — exact iszero(::Num) can OOM via polynomial expansion.
  3. Optionally expose the SCC composition (total/matched/const-pivot counts) as a debug aid — these numbers immediately reveal the inflation.

Context

Found while debugging SingularException(13) during initialization of suspension vehicle models (Multibody-style components). ModelingToolkit v11.26.8 (#master), ModelingToolkitTearing v1.14.1, StateSelection v1.9.3. Related: SciML/ModelingToolkit.jl#4237 (init reconstruction LU of indeterminate reactions), SciML/ModelingToolkit.jl#4607.

主要言語
Julia
スター
7
フォーク
10
平均マージ
5日 11時間
マージ済み PR(30日)
3

環境構築

このプロジェクトには開発コンテナ、Dockerfile、コントリビューションガイドがありません。まず README を読み、一般的な手順ははじめてのコントリビューションガイドを参照してください。

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

JuliaComputing/StateSelection.jl のほかの issue

JuliaComputing/StateSelection.jl の issue をすべて見る

似ている issue

Julia の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。