Adding a variable to an existing constraint on pyomo - pyomo

I have the constraint z_1 + z_2 = 1 in a concrete model. I want to add another variable z_n at the nth step of solving. E.g. the constraint would become z_1 + z_2 + z_3 = 1 in the first step of solving and z_1 + z_2 + z_3 + z_4 = 1 in the next step, and so on.
I really appreciate it if anyone has a suggestion
Thanks a lot!
I am using ConstraintList() method and one way that came to my mind was deleting the constraint in each step and rewriting that. But I am not sure how to do it and if it is efficient or not.
Thanks,

There are a lot of ways to do what you want. The simplest is to update the constraint in question with a new relational expression:
>>> import pyomo.environ as pyo
>>> m = pyo.ConcreteModel()
>>> m.z = pyo.Var(range(5))
>>> m.c = pyo.Constraint(expr=m.z[0] + m.z[1] == 1)
>>> m.c.pprint()
c : Size=1, Index=None, Active=True
Key : Lower : Body : Upper : Active
None : 1.0 : z[0] + z[1] : 1.0 : True
>>> m.c.set_value(m.c.body + m.z[2] == m.c.upper)
>>> m.c.pprint()
c : Size=1, Index=None, Active=True
Key : Lower : Body : Upper : Active
None : 1.0 : z[0] + z[1] + z[2] : 1.0 : True
>>> m.c.set_value(m.c.body + m.z[3] == m.c.upper)
>>> m.c.pprint()
c : Size=1, Index=None, Active=True
Key : Lower : Body : Upper : Active
None : 1.0 : z[0] + z[1] + z[2] + z[3] : 1.0 : True
Alternatively, an approach that requires less manipulation of the model is to use an Expression (named expression) component to hold the constraint body and just update that expression:
>>> m = pyo.ConcreteModel()
>>> m.z = pyo.Var(range(5))
>>> m.e = pyo.Expression(expr=m.z[0] + m.z[1])
>>> m.c = pyo.Constraint(expr=m.e == 1)
>>> m.c.pprint()
c : Size=1, Index=None, Active=True
Key : Lower : Body : Upper : Active
None : 1.0 : e : 1.0 : True
>>> m.e.pprint()
e : Size=1, Index=None
Key : Expression
None : z[0] + z[1]
>>> m.e.expr += m.z[2]
>>> m.c.pprint()
c : Size=1, Index=None, Active=True
Key : Lower : Body : Upper : Active
None : 1.0 : e : 1.0 : True
>>> m.e.pprint()
e : Size=1, Index=None
Key : Expression
None : z[0] + z[1] + z[2]
>>> m.e.expr += m.z[3]
>>> m.c.pprint()
c : Size=1, Index=None, Active=True
Key : Lower : Body : Upper : Active
None : 1.0 : e : 1.0 : True
>>> m.e.pprint()
e : Size=1, Index=None
Key : Expression
None : z[0] + z[1] + z[2] + z[3]

Related

Sympy: Is it possible use function collect() to IndexedBase variables?

I'm trying to use the function collect() to simplify mi expression . My desired result is
My code:
from sympy import *
#index
i = symbols('i' , integer = True )
#constants
a = symbols( 'a' )
#variables
alpha = IndexedBase('alpha', positive=True, domain=QQ)
index = (i, 1, 3)
rho = symbols( 'rho')
U = product( alpha[i]**(1/(rho-1)) , index )
U
:
My solution attempt:
U = U.subs(1/(rho-1),a)
collect(U,rho, evaluate=False)[1]
:
What I'm doing wrong?
You must be using a fairly old version of SymPy because in recent versions the form that you wanted arises automatically. In any case you should be able to use powsimp:
In [9]: U
Out[9]:
a a a
alpha[1] ⋅alpha[2] ⋅alpha[3]
In [10]: powsimp(U, force=True)
Out[10]:
a
(alpha[1]⋅alpha[2]⋅alpha[3])
https://docs.sympy.org/latest/tutorials/intro-tutorial/simplification.html#powsimp

how to rewrite (a+b+c)**2 as a**2 + b**2 + c*2 + 2*(a*b + b*c + c*a) & ^2-->**2

sympy conversion:(a+b+c)^2 --> a^2 +b^2+c^2+2*(ab + bc + c*a) : I want
sorry add
sympy conversion: I want
(a+b+c)**2 --> a**2 +b**2+c**2+2*(a*b + b*c + c*a)
I try
from sympy import *
var('a b c')
f=(a+b+c)**2
print("#f",f)
print("#e",expand(f))
#f (a + b + c)**2
#e a**2 + 2*a*b + 2*a*c + b**2 + 2*b*c + c**2
(2022-02-02)
i try use factor atom
from sympy import *
var('a b c x')
f_str="a+b+c"
g_str="a**2+b**2+c**2"
f =factor(simplify(f_str))
g =factor(simplify(g_str))
mySubs={f:1,g:13}
#
h =factor(f**2-g)
ha=list(h.atoms(Number))[0]
hb=h/ha
Le=(f.subs(mySubs))**2
Ri1=g.subs(mySubs)
Ri2=h.subs({hb:x})
print("#","(",f_str,")**2=",g_str,"+",ha,"*(",hb,")")
print("#",f_str,"=",mySubs[f],",",g_str,"=",mySubs[g])
print("#",Le,"**2=",Ri1,"+",ha,"*(",solve(Eq(Le,Ri1+Ri2))[0],")")
# ( a+b+c )**2= a**2+b**2+c**2 + 2 *( a*b + a*c + b*c )
# a+b+c = 1 , a**2+b**2+c**2 = 13
# 1 **2= 13 + 2 *( -6 )
(2022-02-04) value subs
from sympy import *
var('a b c')
f_str="a+b+c "
g_str="a**2+b**2+c**2"
h_str="a*b+a*c+b*c "
mySubs={a:0,b:-2,c:3}
f=factor(simplify(f_str)).subs(mySubs)
g=factor(simplify(g_str)).subs(mySubs)
h=factor(simplify(h_str)).subs(mySubs)
print("#",mySubs)
print("#",f_str,"=",f)
print("#",g_str,"=",g)
print("#",h_str,"=",h)
print("#",f_str,"**2=",g_str,"+2*(",h_str,")")
print("#",f,"**2=",g,"+2*(",h,")")
# {a: 0, b: -2, c: 3}
# a+b+c = 1
# a**2+b**2+c**2 = 13
# a*b+a*c+b*c = -6
# a+b+c **2= a**2+b**2+c**2 +2*( a*b+a*c+b*c )
# 1 **2= 13 +2*( -6 )
(2022-02-05) value subs
from sympy import *
var('a b c')
f=a+b+c
g=a**2+b**2+c**2
h=a*b+a*c+b*c
mySubs={a:0,b:-2,c:3}
#
f_val=factor(f).subs(mySubs)
g_val=factor(g).subs(mySubs)
h_val=factor(h).subs(mySubs)
print("#",mySubs)
print("#",f,"=",f_val)
print("#",g,"=",g_val)
print("#",h,"=",h_val)
print("#",f,"**2=",g_val,"+2*(",h,")")
print("#",f_val,"**2=",g_val,"+2*(",h_val,")")
# {a: 0, b: -2, c: 3}
# a + b + c = 1
# a**2 + b**2 + c**2 = 13
# a*b + a*c + b*c = -6
# a + b + c **2= 13 +2*( a*b + a*c + b*c )
# 1 **2= 13 +2*( -6 )
(Reference)
2022 Mathematics IA Q1 < The Common Test for University Admissions is a common entrance examination for Japanese universities
japanese only
https://cdn.mainichi.jp/item/jp/etc/kyotsu-2022/pdf/MT1P.pdf#page=1
>>> from sympy.parsing.sympy_parser import *
>>> f = parse_expr('(a+b+c)^2', transformations=(auto_symbol, convert_xor))
>>> f
(a + b + c)**2
>>> from sympy import Pow
>>> nopow, pow = f.expand().as_independent(Pow)
>>> pow + nopow.factor()
a**2 + b**2 + c**2 + 2*(a*b + a*c + b*c)

How to add to a set in pyomo

I am trying to run this code (some important part of the code is here):
Master = AbstractModel()
Master.intIndices = Set(initialize=INTVARS)
Master.constraintSet = Set(initialize=CONS)
Master.conIndices = Set(initialize=CONVARS)
Master.intPartList = Set()
Master.dualVarSet = Master.constraintSet * Master.intPartList
Master.theta = Var(domain=Reals, bounds = (None, None))
Master.intVars = Var(Master.intIndices, domain=NonNegativeIntegers, bounds=(0, 10))
Master.dualVars = Var(Master.dualVarSet, domain=Reals, bounds = (None, None))
max_iters = 1000
opt = SolverFactory("couenne")
for i in range(max_iters):
Master.intPartList.add(i)
but it shows me this error on the last line:
RuntimeError: Cannot access add on AbstractOrderedSimpleSet 'intPartList' before it has been constructed (initialized).
Can somebody help me?
You are not initializing Master.intPartList with any data, so you can't update it like that. However, if you make your model a concrete model, and supply an initialization for your set you can...
In [11]: from pyomo.environ import *
In [12]: m2 = ConcreteModel()
In [13]: m2.X = Set(initialize=[1,])
In [14]: m2.X.add(2)
Out[14]: 1
In [15]: m2.X.pprint()
X : Size=1, Index=None, Ordered=Insertion
Key : Dimen : Domain : Size : Members
None : 1 : Any : 2 : {1, 2}
In [16]:

[Pyomo]How to generate a constraints via a loop

all
i want to create a set of constraints, as following:
Pg[0] <= Pmax[0]
Pg[1] <= Pmax[1]
Pg[3] <= Pmax[3]
Pg[4] <= Pmax[4]
Pg[5] <= Pmax[5]
and, my code is as following:
import pyomo.environ as pyo
model = pyo.ConcreteModel()
Ngen = 5
Pmax = [40, 170, 520, 200, 100]
model.Ngen = pyo.Set(dimen=Ngen)
model.Pg = pyo.Var(model.Ngen)
def Co1(model):
return ((model.Pg[ii] for ii in model.Ngen) <= (Pmax[jj] for jj in range(Ngen)))
model.Co1 = pyo.Constraint(rule=Co1)
but, the Python Console tells me:
" TypeError: '<=' not supported between instances of 'generator' and 'generator' "
HOW DO I RECORRECT this?
and the other quesiton, if the Pmax is not a list, but a numpy-ndarray. somethings will different?
thanks a lot!
The clue is in the fact that your constraint is defined over a set. Pyomo allows you to pass args to the Constraint constructor that define the set(s) of that constraint.
Therefore your final line should look something like:
model.Co1 = pyo.Constraint(model.Ngen, rule=Co1)
The second issue is the constraint expression itself. Now that this is defined with respect to a Set, you need only express the constraint in terms of a given index (say i), because the rule also expects arguments pertaining to each index of each Set of the Constraint:
def Co1(model, i):
return model.Pg[i] <= Pmax[i]
Finally, the Set you're defining is of size=5, not dimen=5. Sets are usually dimen=1 unless you're working with say arc links of a network in which case they would be of dimension 2. Since your set is defined over integers, the easiest way to add this is via RangeSet which defines all the integers from 1 to N:
model.Ngen = pyo.RangeSet(Ngen)
Given this, the only thing to change is that the list Pmax is 0-indexed and so our constraint will need to account for i being offset by one:
import pyomo.environ as pyo
model = pyo.ConcreteModel()
Ngen = 5
Pmax = [40, 170, 520, 200, 100]
model.Ngen = pyo.RangeSet(Ngen)
model.Pg = pyo.Var(model.Ngen)
def Co1(model, i):
return model.Pg[i] <= Pmax[i - 1]
model.Co1 = pyo.Constraint(model.Ngen, rule = Co1)
model.pprint()
# 1 RangeSet Declarations
# Ngen : Dim=0, Dimen=1, Size=5, Domain=Integers, Ordered=True, Bounds=(1, 5)
# Virtual
#
# 1 Var Declarations
# Pg : Size=5, Index=Ngen
# Key : Lower : Value : Upper : Fixed : Stale : Domain
# 1 : None : None : None : False : True : Reals
# 2 : None : None : None : False : True : Reals
# 3 : None : None : None : False : True : Reals
# 4 : None : None : None : False : True : Reals
# 5 : None : None : None : False : True : Reals
#
# 1 Constraint Declarations
# Co1 : Size=5, Index=Ngen, Active=True
# Key : Lower : Body : Upper : Active
# 1 : -Inf : Pg[1] : 40.0 : True
# 2 : -Inf : Pg[2] : 170.0 : True
# 3 : -Inf : Pg[3] : 520.0 : True
# 4 : -Inf : Pg[4] : 200.0 : True
# 5 : -Inf : Pg[5] : 100.0 : True
#
# 3 Declarations: Ngen Pg Co1
NumPy arrays can be sliced in exactly the same way as lists so the above constraint will still work fine if you change Pmax = np.array([40, 170, 520, 200, 100])

unsupported operand type(s) error

a = 3,3 b = 5,3
a2 = a**2
b2 = b**2
eq1_sum = a2 + 2ab + b2
eq2_sum = a2 - 2ab + b2
eq1_pow = (a + b)**2
eq2_pow = (a - b)**2
print ’First equation: %g = %g’, % (eq1_sum, eq1_pow)
print ’Second equation: %h = %h’, % (eq2_pow, eq2_pow)
This program it shows error:
TypeError: unsupported operand type(s) for ** or pow(): 'tuple' and 'int'
You need to use . if you wish to use a floating-point number:
a = 3.3
b = 5.3
a2 = a**2
b2 = b**2
Otherwise, using a comma, you're creating a tuple:
>>> a = 3,3
>>> type(a)
<type 'tuple'>
>>> a = 3.3
>>> type(a)
<type 'float'>
You're now getting an error because a and b are tuples and you can't raise tuples to a power.