Skip to content

feat: Add relax() and unrelax() to Variable and Variables#634

Open
FBumann wants to merge 5 commits intomasterfrom
feat/relax
Open

feat: Add relax() and unrelax() to Variable and Variables#634
FBumann wants to merge 5 commits intomasterfrom
feat/relax

Conversation

@FBumann
Copy link
Collaborator

@FBumann FBumann commented Mar 25, 2026

Follow up on #625

Summary

  • Adds relax() / unrelax() / relaxed to Variable and Variables, enabling LP relaxation of MILP models
  • Supports partial relaxation via filtered views: m.variables.integers.relax(), m.variables.binaries.relax(), or individual m.variables["x"].relax()
  • Semi-continuous variables raise NotImplementedError (their LP relaxation requires bound changes, not just a flag flip)
  • Removes the relax parameter from fix() — the canonical workflow is now fix() then relax() as separate, composable operations
  • unfix() delegates to unrelax() so the full fix+relax workflow is undone in one call

Usage

# Full LP relaxation
m.variables.relax()
m.solve()
m.variables.unrelax()

# Relax only integers, keep binaries as-is
m.variables.integers.relax()
m.solve()
m.variables.unrelax()

# Relax a single variable
m.variables["z"].relax()

# Fix-then-relax for MILP dual extraction
m.variables.binaries.fix()
m.variables.binaries.relax()
m.solve()
m.constraints["con1"].dual

# Fix a subset of variables to explore the feasible space
m.variables["commitment"].fix()
m.variables["dispatch"].relax()
m.solve()

This is sort of a refactor of #625 which works fine as not released yet!

Test plan

  • Tests for Variable.relax() / unrelax() on binary, integer, continuous, and semi-continuous
  • Tests for Variables.relax() / unrelax() on full and filtered containers
  • Tests for combined fix+relax workflow and unfix restoring integrality
  • Tests for netCDF round-trip of relaxed registry
  • Test that relaxing all variables converts MILP to LP (m.type)
  • All 56 tests in test_fix_relax.py pass

🤖 Generated with Claude Code

Add methods to relax integrality of binary/integer variables to
continuous, enabling LP relaxation of MILP models. Supports partial
relaxation of individual variables or filtered views (e.g.
m.variables.integers.relax()). Semi-continuous variables raise
NotImplementedError since their relaxation requires bound changes.

Refactors fix(relax=True) to delegate to relax(), removing the relax
parameter from fix() to avoid redundancy.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@FBumann FBumann marked this pull request as draft March 25, 2026 21:02
FBumann and others added 4 commits March 25, 2026 22:03
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@FBumann FBumann marked this pull request as ready for review March 25, 2026 21:21
@FBumann
Copy link
Collaborator Author

FBumann commented Mar 25, 2026

@FabianHofmann sorry for the noisy notebook! The rest should be easy to review.

@PyPSA PyPSA locked and limited conversation to collaborators Mar 25, 2026
@PyPSA PyPSA unlocked this conversation Mar 25, 2026
@FBumann
Copy link
Collaborator Author

FBumann commented Mar 25, 2026

I'll need to adjust this before merge.

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.

1 participant