Skip to content

fix: extra output comparison #240

Merged
aoustry merged 5 commits into
mainfrom
claude/fix-extra-output-comparison-237
Jul 13, 2026
Merged

fix: extra output comparison #240
aoustry merged 5 commits into
mainfrom
claude/fix-extra-output-comparison-237

Conversation

@aoustry

@aoustry aoustry commented Jun 26, 2026

Copy link
Copy Markdown
Collaborator

Process ID

[GP-02] Fix expressions in extra-outputs with <= and min
#237

Description

Expressions in extra-output such as : dual(balance) >= unsupplied_cost - 5 and min(variable, parameter) shouldn't raise errors.

Impact Analysis

simulation/extra_outputs.py

Checklist

  • Unit tests pass (pytest)
  • Type checking passes (mypy)
  • Formatting passes (black, isort)
  • pyproject.toml version bumped if applicable
  • AGENTS.md reviewed for impact and updated if needed

claude added 2 commits June 25, 2026 17:56
Extra-output expressions such as `dual(balance) >= unsupplied_cost - 5`
previously raised NotImplementedError at post-solve evaluation because
VectorizedExtraOutputBuilder inherited the base comparison() that
unconditionally rejects ComparisonNode.

Override comparison() in the post-solve builder to evaluate both operands
(concrete DataArrays) element-wise and return a float indicator (1.0 where
the condition holds, 0.0 otherwise). The base builder still rejects
comparisons, since pre-solve they are constraints, not values.

min()/max() already worked post-solve; add regression tests covering both
the min and comparison extra-output cases. Bump version to 0.1.3.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AmfPS89otsiw1q7LDGwumU
Keep the version at 0.1.2 (revert pyproject.toml and uv.lock) and record the
extra-output comparison-operator bug fix under an [Unreleased] changelog section.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AmfPS89otsiw1q7LDGwumU
@aoustry
aoustry requested a review from Juliette-Gerbaux June 26, 2026 07:44
Comment thread tests/unittests/simulation/test_simulation_table_extra_outputs.py Outdated
Comment thread tests/unittests/simulation/test_simulation_table_extra_outputs.py Outdated
@aoustry

aoustry commented Jun 26, 2026

Copy link
Copy Markdown
Collaborator Author

Closes #237

@aoustry aoustry linked an issue Jun 26, 2026 that may be closed by this pull request
20 tasks
variables=[float_variable("a", lower_bound=literal(5), upper_bound=literal(5))],
extra_outputs={"capped": minimum(var("a"), param("cap"))},
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
OTHER_MODEL = model(
id="OTHER_MODEL",
parameters=[float_parameter("p")],
variables=[float_variable("b", lower_bound=literal(1), upper_bound=literal(1))],
)

)

database = DataBase()
comp = create_component(model=SIMPLE_MODEL, id="comp_1")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
comp = create_component(model=SIMPLE_MODEL, id="comp_1")
other_comp = create_component(model=OTHER_MODEL, id="comp_2")


database = DataBase()
comp = create_component(model=SIMPLE_MODEL, id="comp_1")
database.add_data("comp_1", "cap", ConstantData(3.0))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
database.add_data("comp_1", "cap", ConstantData(3.0))
database.add_data("comp_2", "p", ConstantData(0.0))

database.add_data("comp_1", "cap", ConstantData(3.0))

system = System("test_min_extra")
system.add_component(comp)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
system.add_component(comp)
system.add_component(other_comp)

@Juliette-Gerbaux Juliette-Gerbaux left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When multiple models coexist in a problem, linopy's outer join causes solution DataArrays to include NaN-filled entries for components of other models. This breaks minimum()/maximum(), which use xr.where and require aligned coordinates.

Fix: Filter solution/dual/reduced-cost arrays to the current model's own components before passing them to the VectorizedExtraOutputBuilder.

…puts (#246)

* fix: filter solution/dual arrays to own model components in extra outputs

When multiple models coexist in a problem, linopy's merged solution/dual
Datasets outer-join their component coordinates, padding each model's
variable and constraint-dual arrays with NaN entries for other models'
components. minimum()/maximum() in extra outputs use xr.where, which
requires aligned coordinates and breaks on this padding.

Filter var_solution_arrays and constraint_dual_arrays back down to each
model's own components in simulation_table.py, mirroring the existing
guard in _collect_vars_outputs. Extends test_extra_output_min_on_variable
with a second coexisting model to reproduce and guard against the issue,
per Juliette Gerbaux's review on #240.
@aoustry
aoustry requested a review from Juliette-Gerbaux July 9, 2026 16:56
@aoustry
aoustry merged commit 9076ccc into main Jul 13, 2026
2 checks passed
@aoustry
aoustry deleted the claude/fix-extra-output-comparison-237 branch July 13, 2026 10:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[GP-02] Fix expressions in extra-outputs with <= and min

3 participants