Grouped-sum absence rules are implemented twice (CSRStore._from_scatter and CSRStore.aggregate)
メンテナーはふだん 1 日以内に返信
まだ誰も着手していません。
評価
調査の方向性
The two grouped-sum kernels are CSRStore._from_scatter and CSRStore.aggregate in linopy/csr.py, reached through from_grouper, and CSRStore.from_coo is a third presence rule. Start by reading convention.rst §13 and comparing how each kernel derives presence and the constant. The lower-effort path is a conformance test that runs groupby().sum() through both kernels over the listed absence cases and asserts identical stores. Refactoring _from_scatter onto aggregate is design work and should be agreed with maintainers first.
索引モデルが issue の本文から書いたものです。
説明
[!NOTE]
The following content was generated by AI.
CSRStore has two kernels that compute a grouped sum, and each one implements the absence rules (convention.rst §13) on its own:
CSRStore._from_scatter(linopy/csr.py, used byfrom_grouperfor dense sources) scatters the dataset's terms into cells. It drops-1/ NaN terms, then derives presence and the constant itself:const[cell_rows] = 0.0+np.add.at(...), with askipnaswitch.CSRStore.aggregate(linopy/csr.py, used byfrom_grouperfor CSR sources and byDenseStore.aggregateviaas_sparse(...).aggregate(...).to_dense()) regroups CSR rows. It derives presence from the row bounds (const[np.diff(bounds) == 0] = np.nan) and always skips NaN constants.
Today both agree on every case we probed: cells nothing lands in are absent, cells whose members are all absent are present with constant 0, and NaN constants are skipped. But the rules live in two places. A change to one won't reach the other, and dense and sparse groupby().sum() could start to diverge silently. This came up in the review of #1122, where a third copy of the presence rule (CSRStore.from_coo) had already drifted: cells reached only through masked labels came out absent instead of zero.
Possible directions
- Express
_from_scatteras "build one CSR row per member, thenaggregate", so presence and constant handling live inaggregatealone. Theskipna=Falsecase would remain a small post-step on the constant. - Or, at minimum, add a conformance test that runs
groupby().sum()through both kernels over a table of absence cases (unaddressed cell, all-masked members, NaN member constants, explicit zero coefficients, duplicates) and asserts identical stores.
Related observations, possibly separate
- §13 says "a sum of none is the zero expression", but a multi-key cartesian
groupbyandreindexgive absent cells, while@/.sum()give zero. The convention docs should say which rule applies where. - At the constraint layer, a present row with no live terms is silently dropped (
active_row_mask,constraints.py). An all-masked0 == 1therefore disappears instead of making the model infeasible, and the solver can't tell absent from zero.
Generated by Claude Code
- 主要言語
- Python
- スター
- 263
- フォーク
- 93
- 平均マージ
- 1日 10時間
- マージ済み PR(30日)
- 68
環境構築
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートあり
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
PyPSA/linopy のほかの issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
メンテナーはふだん 1 日以内に返信
-
bug
難易度 3/5 1〜2日 初心者へのやさしさ 70/100
メンテナーはふだん 1 日以内に返信
-
enhancement
難易度 4/5 3〜5日 初心者へのやさしさ 48/100
メンテナーはふだん 1 日以内に返信
-
enhancement math-spec
難易度 5/5 1週間以上 初心者へのやさしさ 35/100
PyPSA/linopy#1063 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
Zero culling forces model rebuilding対応中かも @MaykThewessen が 33 日前に担当しました。 オープンbug data-model performance
難易度 4/5 3〜5日 初心者へのやさしさ 58/100
メンテナーはふだん 1 日以内に返信
似ている issue
-
bug good first issue
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
-
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
graphql-python/graphql-core#304 ·
メンテナーはふだん 1 日以内に返信
-
docs size:S
難易度 1/5 1時間未満 初心者へのやさしさ 88/100
メンテナーはふだん 1 日以内に返信
-
難易度 1/5 1〜3時間 初心者へのやさしさ 88/100
Gathin23/cleanyourtv#3464 ·
メンテナーはふだん 1 日以内に返信
-
documentation
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
メンテナーはふだん 1 日以内に返信