Skip to content

fix: use max() for penalty scaling floor (closes #75)#77

Merged
andig merged 2 commits into
mainfrom
fix/75-penalty-min-max
May 31, 2026
Merged

fix: use max() for penalty scaling floor (closes #75)#77
andig merged 2 commits into
mainfrom
fix/75-penalty-min-max

Conversation

@andig
Copy link
Copy Markdown
Member

@andig andig commented May 31, 2026

Summary

Fixes #75. The penalty-scaling base was computed with np.min([self.max_import_price, 0.1e-3]), despite the comment stating the intent was to keep the penalty positive. min() does the opposite:

  • Negative market prices (which occur in real energy markets) drive the base negative, turning penalties into rewards in the maximizing objective — the optimizer would then seek out goal/limit violations.
  • Normal prices above the 1e-4 floor get clamped down to that tiny floor, making penalties too weak to reliably dominate real costs.

The intended behavior is a positive floor that scales with the highest import price, which is np.max().

Changes

  • Switch np.minnp.max for the penalty base.
  • Deduplicate the expression — repeated 5× across the goal/SOC/grid-import/grid-export penalties — into a single penalty_base computed once (the "clean up the calculation of incentives" part of the issue).

Behavior is unchanged for typical positive prices above the floor, and corrected for the zero/negative-price edge cases the issue flagged.

Testing

  • uv run pytest → 13 passed
  • uv run ruff check → clean

🤖 Generated with Claude Code

The penalty scaling base was computed with np.min([max_import_price,
0.1e-3]) despite the comment intending a positive floor. min() inverts
penalties on negative market prices (turning them into rewards in the
maximizing objective) and clamps them to the tiny floor whenever real
prices are higher, making penalties too weak to dominate.

Switch to np.max() for a proper positive floor that scales with the
highest import price, and deduplicate the expression—repeated five
times—into a single penalty_base.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Comment thread src/optimizer/optimizer.py Outdated
@andig
Copy link
Copy Markdown
Member Author

andig commented May 31, 2026

@ekkea lgtm?

Copy link
Copy Markdown
Contributor

@ekkea ekkea left a comment

Choose a reason for hiding this comment

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

Looks good, let's merge!

@andig andig merged commit b5cbfeb into main May 31, 2026
1 check passed
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.

penalty limit logic is incorrect (min() called instead of max())

2 participants