Skip to content

Commit f45c49c

Browse files
committed
Updated docstrings for max -> min.
1 parent 1b6d09f commit f45c49c

1 file changed

Lines changed: 22 additions & 22 deletions

File tree

linopy/dual.py

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -193,24 +193,21 @@ def bounds_to_constraints(m: Model) -> None:
193193

194194
def _add_dual_variables(m: Model, m2: Model) -> dict:
195195
"""
196-
Add dual variables to m2 corresponding to constraints in m.
196+
Add dual variables to m2 corresponding to constraints in m..
197197
198198
For each active constraint in m, adds a dual variable to m2 following
199-
linopy's sign convention:
199+
standard LP duality sign conventions. The sign of the dual variable bounds
200+
depends on both the constraint type and the primal objective sense:
200201
202+
For a minimization primal:
201203
- Equality constraints (=) -> free dual variable (lower=-inf, upper=inf)
202204
- <= constraints -> non-positive dual variable (lower=-inf, upper=0)
203205
- >= constraints -> non-negative dual variable (lower=0, upper=inf)
204206
205-
This convention ensures that m2.variables[con_name].solution has the same
206-
sign as m.constraints[con_name].dual after solving, allowing direct
207-
comparison without sign adjustments.
208-
209-
The sign encodes the direction of impact on the objective per unit RHS change:
210-
- <= constraint dual (<=0): increasing RHS by 1 unit changes objective by
211-
dual units (negative = cost decreases, i.e. relaxing the constraint).
212-
- >= constraint dual (>=0): increasing RHS by 1 unit changes objective by
213-
dual units (positive = cost increases, i.e. tightening the constraint).
207+
For a maximization primal:
208+
- Equality constraints (=) -> free dual variable (lower=-inf, upper=inf)
209+
- <= constraints -> non-negative dual variable (lower=0, upper=inf)
210+
- >= constraints -> non-positive dual variable (lower=-inf, upper=0)
214211
215212
Skips constraints with no active rows (empty or fully masked).
216213
@@ -510,19 +507,21 @@ def dualize(
510507
"""
511508
Construct the dual of a linopy LP model.
512509
513-
Transforms the primal model into its dual equivalent m2 by:
514-
1. Converting variable bounds to explicit constraints
515-
2. Adding dual variables to m2 (one per active constraint)
516-
3. Adding dual feasibility constraints to m2 (one per primal variable)
517-
4. Adding the dual objective to m2
510+
Transforms the primal model into its dual equivalent m2 following
511+
standard LP duality theory. The dual sense is flipped relative to the
512+
primal (min -> max, max -> min), and dual variable bounds depend on
513+
both constraint type and primal objective sense.
514+
515+
For a minimization primal:
518516
519-
The dual is constructed following standard LP duality theory:
517+
Primal (min): Dual (max):
518+
min c^T x max b_eq^T λ + b_leq^T μ + b_geq^T ν
519+
s.t. A_eq x = b_eq : λ free s.t. A_eq^T λ + A_leq^T μ + A_geq^T ν = c
520+
A_leq x <= b_leq : μ <= 0 λ free, μ <= 0, ν >= 0
521+
A_geq x >= b_geq : ν >= 0
520522
521-
Primal (min): Dual (max):
522-
min c^T x max b_eq^T λ + b_leq^T μ + b_geq^T ν
523-
s.t. A_eq x = b_eq : λ free s.t. A_eq^T λ + A_leq^T μ + A_geq^T ν = c
524-
A_leq x <= b_leq : μ <= 0 λ free, μ <= 0, ν >= 0
525-
A_geq x >= b_geq : ν >= 0
523+
For a maximization primal the dual variable bounds are flipped:
524+
μ >= 0 for <= constraints, ν <= 0 for >= constraints.
526525
527526
Variable bounds are converted to explicit constraints before dualization
528527
via bounds_to_constraints(), so that they appear in the constraint matrix
@@ -535,6 +534,7 @@ def dualize(
535534
primal objective = dual objective
536535
537536
Note: The standalone dual m2 may be unbounded if the primal is degenerate.
537+
Only linear programs (LP) are supported.
538538
539539
Parameters
540540
----------

0 commit comments

Comments
 (0)