Variable definition as constraint in pyomo

Question:

This question is related to my previous question found here. I have managed to solve this problem (big thanks to @AirSquid!) My objective function is something like:

enter image description here

So the avgPrice_n variable is indexed by n. However, it is actually defined as

enter image description here

Meaning that it is indexed by n and i.

So at the moment my objective function is very messy as I have three sums. It looks something like (I expanded the brackets in the objective function and added each component separately, so the avgPrice_n*demand_n looks like):

expr += sum(sum(sum((1/12)*model.c[i]*model.allocation[i,n] for i in model.MP[t]) for t in model.M)*model.demand_n[n] for n in model.N)

And while this works, debugging was quite difficult because the terms are very long. So intead of using the actual definition of avgPrice_n, I was wondering if it would be possible to create a avgPrice_n variable, use this in the objective function and then create a constraint where I define avgPrice_n as I showed above.

The issue I am having is that I created my decision variable, x_{i,n}, as a variable but apparently I can’t create a avgPrice_n as a variable where I index it by x_{i,n} as this results in a TypeError: Cannot apply a Set operator to an indexed Var component (allocation) error.

So as of now my decision variable looks like:

model.x = Var(model.NP_flat, domain = NonNegativeReals)

And I tried to create:

model.avg_Price = Var(model.x, domain = NonNegativeReals)

Which resulted in the above error. Any ideas or suggestions would be much appreciated!

Asked By: BenBernke

||

Answers:

You have a couple options. Realize you do not need the model.avg_price variable because you can construct it from other variables and you would have to make some constraints to constrain the value, etc. etc. and pollute your model.

The basic building blocks in the model are pyomo expressions, so you could put in a little "helper function" to build expressions (the cost function shown, which is dependent on n) which are not defined within the model, but just pop out an expression…totally legal). You can also "break up" large expressions into smaller expressions (like the other_stuff below) and then just kludge them all together in the objective (or where needed) this gives you the opportunity to evaluate them independently. I’ve made several models with an objective function that has a "cost" component and a "penalty" component by dividing it into 2 expressions…. Then when solved, you can inspect them independently.

My suggestion (if you don’t like the triple sum in your current model) is to make an avg_cost(n) function to build the expression similar to what is done in the nonsensical function below, and use that as a substitute for a new variable.

Note: the initialization of the variables here is generally unnecessary. I just did it to "simulate solving" or they would be None…

Code:

import pyomo.environ as pyo

m = pyo.ConcreteModel()

m.N = pyo.Set(initialize=[0,1,2])

m.x = pyo.Var(m.N, initialize = 2.0)

def cost(n):
    return m.x[n] + 2*m.x[n+1]

m.other_stuff = 3 * m.x[1] + 4 * m.x[2]

m.costs = sum(cost(n) for n in {0,1})

m.obj_expr = m.costs + m.other_stuff

m.obj = pyo.Objective(expr= m.obj_expr)


# inspect cost at a particular value of n...
print(cost(1))
print(pyo.value(cost(1)))

# inspect the pyomo expressions "other_stuff" and total costs...
print(m.other_stuff)
print(pyo.value(m.other_stuff))
print(m.costs)
print(pyo.value(m.costs))

# inspect the objective...  which can be accessed by pprint() and display()
m.obj.pprint()
m.obj.display()

Output:

x[1] + 2*x[2]
6.0
3*x[1] + 4*x[2]
14.0
12.0
obj : Size=1, Index=None, Active=True
    Key  : Active : Sense    : Expression
    None :   True : minimize : x[0] + 2*x[1] + x[1] + 2*x[2] + 3*x[1] + 4*x[2]
obj : Size=1, Index=None, Active=True
    Key  : Active : Value
    None :   True :  26.0
Answered By: AirSquid
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.