Skip to content

lp_dual transformation mapping function between dual vars and primal constraints is not well-defined. #3843

@ChrisLaliwala

Description

@ChrisLaliwala

Summary

When constructing the dual problem on a primal model with ranged constraints, the mapping between dual variables and primal constraints in non-unique. Both duals will map to the same ranged primal constraint, and the ranged primal constraint will only map to one of the two dual variables. This also raises the issue of what to do when the user creates ranged constraints with variable bounds... or if it is still worth implementing a mapping if this is the case...

Steps to reproduce the issue

Here is an example that illustrates the issue:

# example.py
import pyomo.environ as pyo

m = pyo.ConcreteModel()
m.x1 = pyo.Var(domain=pyo.NonNegativeReals)
m.x2 = pyo.Var(domain=pyo.Reals)
m.con1 = pyo.Constraint(expr=(1, m.x1, 4))
m.con2 = pyo.Constraint(expr=m.x2 <= 10)
m.obj = pyo.Objective(expr=m.x1 + m.x2, sense=pyo.maximize)

dual = pyo.TransformationFactory("core.lp_dual").create_using(m)

# get transformation mapping
td = pyo.TransformationFactory('core.lp_dual')

# get primal constraints
print('Primal constraints from dual variables:')
primal_con1 = td.get_primal_constraint(dual, dual.x[0])
primal_con1.pprint()
primal_con2 = td.get_primal_constraint(dual, dual.x[1])
primal_con2.pprint()
primal_con3 = td.get_primal_constraint(dual, dual.x[2])
primal_con3.pprint()

# get dual variables
print('\nDual variables from primal constraints:')
dual_var1 = td.get_dual_var(dual, m.con1)
dual_var1.pprint()
dual_var2 = td.get_dual_var(dual, m.con2)
dual_var2.pprint()
...

Error Message

Here is the printed output illustrating the non-unique mapping:

$ # Output message here, including entire stack trace, if available
Primal constraints from dual variables:
con1 : Size=1, Index=None, Active=True
    Key  : Lower : Body : Upper : Active
    None :   1.0 :   x1 :   4.0 :   True
con1 : Size=1, Index=None, Active=True
    Key  : Lower : Body : Upper : Active
    None :   1.0 :   x1 :   4.0 :   True
con2 : Size=1, Index=None, Active=True
    Key  : Lower : Body : Upper : Active
    None :  -Inf :   x2 :  10.0 :   True

Dual variables from primal constraints:
{Member of x} : Size=3, Index={0, 1, 2}
    Key : Lower : Value : Upper : Fixed : Stale : Domain
      1 :  None :  None :     0 : False :  True : NonPositiveReals
{Member of x} : Size=3, Index={0, 1, 2}
    Key : Lower : Value : Upper : Fixed : Stale : Domain
      2 :     0 :  None :  None : False :  True : NonNegativeReals

Information on your system

Pyomo version: 6.9.5
Python version: 3.14.3
Operating system: Ubuntu 22.04.5 LTS (WSL2/Windows 11)
How Pyomo was installed (PyPI, conda, source): pip install pyomo
Solver (if applicable): not applicable

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions