I have a pyomo model "m" with 4 variables and several constraints (both equality and inequality) in the form:
Min F(G1,G2,D1,D2) st h=0 g<=0
Then I need to build the lagrangian function, which is something like this:
Briefly, lambda and mu are the duals of the constraints. So I need the objective function + dual1cons1 + dual2cons2 and so on.
I have literally no idea how to do this. The closest I got is with this:
Lagrange = m.objective #initialize the variable with the f(x)
for cons in m.component_objects(pyomo.core.base.constraint.Constraint): #iterates over the constraints
print("\n->" + str(cons) + ":")
if isinstance(cons, pyomo.core.base.constraint.SimpleConstraint): #selects whether it is an individual constraint
# print(cons)
print(expression_to_string(m.component(cons).expr)) #prints the expresion
if isinstance(cons, pyomo.core.base.constraint.ConstraintList): #or a list of constraints
for i in m.component(cons):
Lagrange=Lagrange+m.component('LinLim')[i].expr
# print(expression_to_string(m.component(cons)[i].expr)) #prints the expresion
print(expression_to_string(Lagrange))
Then, the print statement returns this:
(12Pgen[G1] + 20Pgen[G2] - (40Pdem[D1] + 35Pdem[D2])) + (500*(teta[n1] - teta[n2]) - 100 <= 0.0) - (500*(teta[n1] - teta[n2]) + 100) <= 0.0 + (500*(teta[n1] - teta[n3]) - 100 <= 0.0) + (500*(teta[n1] - teta[n2]) - 100 <= 0.0) - (500*(teta[n1] - teta[n2]) + 100) <= 0.0 + (500*(teta[n1] - teta[n3]) - 100 <= 0.0) - (500*(teta[n1] - teta[n3]) + 100) <= 0.0 + (500*(teta[n2] - teta[n3]) - 100 <= 0.0) - (500*(teta[n2] - teta[n3]) + 100) <= 0.0
I am aware that is a nightmare to read. The point is, it includes the operator of the equations (==, >=, <=) while I would only be interested in the left hand side part of the equation. Then, in addition I would need to add new variables representing the duals (lambda and mu).
Pyomo constraints have a body
attribute, and uslack
and lslack
functions that give you a sum expression of the constraint left hand side, the upper slack, and lower slack respectively. The `body attribute is what you want to multiply by lambda and mu. Here is an example with a simple constraint
import pyomo.environ as pyo
m = pyo.ConcreteModel()
index = [1,2,3,4]
m.x = pyo.Var(index,domain = pyo.Binary,initialize = 0)
m.c1 = pyo.Constraint(expr=sum([m.x[i] for i in index])<=3)
print('Constraint 1: {}'.format(str(m.c1.body)))
# Constraint 1: x[1] + x[2] + x[3] + x[4]
m.fixed_lambda = pyo.Var(domain = pyo.NonNegativeReals)
m.lagrangian = pyo.Objective(expr = m.fixed_lambda * m.c1.body,sense=pyo.minimize)
print('Lagrangian expression: {}'.format(str(m.lagrangian.expr)))
# Lagrangian expression: fixed_lambda*(x[1] + x[2] + x[3] + x[4])