Pyomo error in formulating the constraint - python

I am trying to formulate a battery optimization problem to charge/discharge the battery optimally. The formulation is the following:
model = pyo.ConcreteModel()
#Set time period
model.timesteps = pyo.Set(initialize=pyo.RangeSet(len(pv)),ordered=True)
#Parameters
model.b_efficiency = pyo.Param(initialize=etta)
model.b_cap = pyo.Param(initialize=battery_capacity)
model.b_min_soc = pyo.Param(initialize=battery_soc_min)
model.b_max_soc = pyo.Param(initialize=battery_soc_max)
model.b_charging_rate = pyo.Param(initialize=battery_charge_rate)
model.Ppv = pyo.Param(model.timesteps,initialize=dict(enumerate(pv,1)),within=pyo.Any)
model.Pdemand = pyo.Param(model.timesteps, initialize=dict(enumerate(demand,1)),within=pyo.Any)
#Variables
model.Pbat_ch = pyo.Var(model.timesteps, within = pyo.NonNegativeReals)
model.Pbat_dis = pyo.Var(model.timesteps, within = pyo.NonNegativeReals)
model.Ebat = pyo.Var(model.timesteps, within = pyo.NonNegativeReals)
model.Pgrid = pyo.Var(model.timesteps, within = pyo.NonNegativeReals)
# Define the constraints of the model
def BatEnergyBounds(model, t):
return model.b_min_soc * model.b_cap <= model.Ebat[t] <= model.b_max_soc * model.b_cap
model.cons1 = pyo.Constraint(model.timesteps, rule = BatEnergyBounds)
def BatChargingBounds(model, t):
return 0 <= model.Pbat_ch[t] <= model.b_charging_rate
model.cons2 = pyo.Constraint(model.timesteps, rule = BatChargingBounds)
def BatDischargingBounds(model, t):
return 0 <= model.Pbat_dis[t] <= model.b_charging_rate
model.cons3 = pyo.Constraint(model.timesteps, rule = BatDischargingBounds)
def BatEnergyRule(model, t):
if t == model.timesteps.first():
return model.Ebat[t] == model.b_cap/2
else:
return model.Ebat[t] == model.Ebat[t-1] + (model.b_efficiency * model.Pbat_ch[t] - model.Pbat_dis[t]/model.b_efficiency)
model.cons4 = pyo.Constraint(model.timesteps, rule = BatEnergyRule)
def PowerBalanceRule(model, t):
return model.Pgrid[t] == model.Ppv[t] - model.Pdemand[t] + model.Pbat_dis[t] - model.Pbat_ch[t]
model.cons5 = pyo.Constraint(model.timesteps, rule = PowerBalanceRule)
# Define the objective function
def ObjRule(model):
return sum(model.Pgrid[t] for t in model.timesteps)
model.obj = pyo.Objective(rule = ObjRule, sense = pyo.minimize)
However, I am getting the following error:
PyomoException: Cannot convert non-constant Pyomo expression (1.0 <= Ebat[1]) to bool.
This error is usually caused by using a Var, unit, or mutable Param in a
Boolean context such as an "if" statement, or when checking container
membership or equality. For example,
>>> m.x = Var()
>>> if m.x >= 1:
... pass
and
>>> m.y = Var()
>>> if m.y in [m.x, m.y]:
... pass
would both cause this exception.
It seems like the error is caused by the IF statement that I used in cons4. Any idea of what is causing the error?

It isn't clear what is causing the error. If you are looking for help with an error, it is best to provide an example that produces the error by itself with the exact stack trace, etc.
Your "example" code produces the error because you are using a conditional if statement that depends on the value of a variable, which isn't allowed. Your code in the main program does not do that, so it looks fine.
If you are stuck, edit your post with a completely reproducible example.

Related

Task on inner functions in Python

I just created my 3 functions for a business problem : wether invest or not in my company.
These are the function i created.
The order should be:
Outer function = def is_investable
inner functions = def sanityChekc, def grahamNumberCalculator
In the end, the result should be "True" for the function is_investable if we decide to invest and false if we decide not.
def grahamNumberCalculator(EarningsPerShare, BookValuePerShare):
ConstInt = 22.5
IntermediateValue = ConstInt * EarningsPerShare * BookValuePerShare
HighestPrice = math.sqrt(IntermediateValue)
return HighestPrice
def is_investable(MarketPrice, HighestPrice, sanityCheck):
if MarketPrice <= HighestPrice and sanityCheck == True:
return True
else:
return False
def sanityCheck(CurrAssets, Liabilities, Debt, EarningOverTime):
First_subcheck = []
Second_subcheck = []
Forth_subcheck = []
if CurrAssets >= 1.5 * Liabilities:
First_subcheck.append('True')
if (Debt / CurrAssets) < 1.1:
Second_subcheck.append('True')
for i in EarningOverTime:
if i > 0:
Forth_subcheck.append('True')
if First_subcheck == ['True'] and Second_subcheck == ['True'] and len(Forth_subcheck) == len(EarningOverTime):
return (True)
else:
return (False)
This is my first time i try the inner functions, I saw some tutorials and with simple tasks I think i can menage it, but with this i can't figure it out. Would someone help meto understand how it works? Thank you very much
Sorry about the probable confusion of the request

Not defined variable in numpy

I'm trying to run the code below but I get a NameError when running the code. The issue is that q seems not to be defined but this should not be true.
class SimpleNamespace():
pass
#Question 1
#i)
#Defining the parameters using SimpleNameSpace. par = Parameters
par = SimpleNamespace()
par.y = 1 #assets
par.p = 0.2 #probability
par.theta = -2 #elasticity
#Defining utility function for agent
def utility(z,par):
return (z**(1+par.theta))/(1+par.theta)
#Defining premium
def premium(q,par):
return par.p*q
#Defining expected value
#Note that z_1, z_2 represents first and second part of the objective function - just in a compressed version
def exp_value (i,q,par):
z_1 = par.y-i+q-premium(q,par)
z_2 = par.y-premium(q,par)
return par.p*utility(z_1,par)+(1-par.p)*utility(z_2,par)
def opt_q(i,q,par):
obj = lambda q: -exp_value(i,q,par) #defining the objective function
solution = optimize.minimize_scalar(obj, bounds=(0,0.9), method="bounded") #bounded solution within [0.01, 0.9]
q = solution.x
return q
for i in np.linspace(0.01,0.9,num=100):
res = opt_q(i,q,par)
print(res)
You are getting the NameError because you are not passing the q to opt_q in the last for-loop. Since it is already defined inside opt_q just remove q from its arguments and don't pass it in the for-loop as well as follows:
def opt_q(i,par):
obj = lambda q: -exp_value(i,q,par) #defining the objective function
solution = minimize_scalar(obj, bounds=(0,0.9), method="bounded") #bounded solution within [0.01, 0.9]
q = solution.x
return q
for i in np.linspace(0.01,0.9,num=100):
res = opt_q(i,par)
print(res)
This resolves your issue.

Python function replacing part of variable

I am writing a code for a project in particle physics (using pyroot).
In my first draft, I use the following line
for i in MyTree:
pion.SetXYZM(K_plus_PX, K_plus_PY, K_plus_PZ,K_plus_MM)
This basically assigns to the pion the values of variables in the parenthesis, ie momenta and inv. mass of the kaon.
Physics aside, I would like to write a function "of the form":
def myfunc(particle):
return %s_PX % particle
I know this is wrong. What I would like to achieve is to write a function that allows, for a given particle, to set particle_PX, particle_PY etc to be the arguments of SetXYZM.
Thank you for your help,
B
To access class attributes from string variables you can use python's getattr:
import ROOT
inputfile = ROOT.TFile.Open("somefile.root","read")
inputtree = inputfile.Get("NameOfTTree")
inputtree.Print()
# observe that there are branches
# K_plus_PX
# K_plus_PY
# K_plus_PZ
# K_plus_MM
# K_minus_PX
# K_minus_PY
# K_minus_PZ
# K_minus_MM
# pi_minus_PX
# pi_minus_PY
# pi_minus_PZ
# pi_minus_MM
def getx(ttree,particlename):
return getattr(ttree,particlename+"_PX")
def gety(ttree,particlename):
return getattr(ttree,particlename+"_PY")
def getz(ttree,particlename):
return getattr(ttree,particlename+"_PZ")
def getm(ttree,particlename):
return getattr(ttree,particlename+"_MM")
def getallfour(ttree,particlename):
x = getattr(ttree,particlename+"_PX")
y = getattr(ttree,particlename+"_PY")
z = getattr(ttree,particlename+"_PZ")
m = getattr(ttree,particlename+"_MM")
return x,y,z,m
for entry in xrange(inputtree.GetEntries()):
inputtree.GetEntry(entry)
pion1 = ROOT.TLorentzVector()
x = getx(inputtree,"K_plus")
y = gety(inputtree,"K_plus")
z = getz(inputtree,"K_plus")
m = getm(inputtree,"K_plus")
pion2.SetXYZM(x,y,z,m)
x,y,z,m = getallfour(inputtree,"pi_minus")
pion2 = ROOT.TLorentzVector()
pion2.SetXYZM(x,y,z,m)
As linked by Josh Caswell, you can similarly access variable names:
def getx(particlename):
x = globals()[partilcename+"_PX"]
though that might get nasty quickly as of whether your variables are global or local and for local, in which context.

Proper handling of spark broadcast variables in a Python class

I've been implementing a model with spark via a python class. I had some headaches calling class methods on a RDD defined in the class (see this question for details), but finally have made some progress. Here is an example of a class method I'm working with:
#staticmethod
def alpha_sampler(model):
# all the variables in this block are numpy arrays or floats
var_alpha = model.params.var_alpha
var_rating = model.params.var_rating
b = model.params.b
beta = model.params.beta
S = model.params.S
Z = model.params.Z
x_user_g0_inner_over_var = model.x_user_g0_inner_over_var
def _alpha_sampler(row):
feature_arr = row[2]
var_alpha_given_rest = 1/((1/var_alpha) + feature_arr.shape[0]*(1/var_rating))
i = row[0]
items = row[1]
O = row[3] - np.inner(feature_arr,b) - beta[items] - np.inner(S[i],Z[items])
E_alpha_given_rest = var_alpha_given_rest * (x_user_g0_inner_over_var[i] + O.sum()/var_rating)
return np.random.normal(E_alpha_given_rest,np.sqrt(var_alpha_given_rest))
return _alpha_sampler
As you can see, to avoid serialization errors, I define a static method that returns a function that is in turn applied to each row of an RDD (model is the parent class here, and this is called from within another method of model):
# self.grp_user is the RDD
self.params.alpha = np.array(self.grp_user.map(model.alpha_sampler(self)).collect())
Now, this all works fine, but is not leveraging Spark's broadcast variables at all. Ideally, all the variables I'm passing in this function (var_alpha, beta, S, etc.) could first be broadcast to the workers, so that I wasn't redundantly passing them as part of the map. But I'm not sure how to do this.
My question, then, is the following: How/where should I make these into broadcast variables such that they are available to the alpha_sampler function that I map to grp_user? One thing I believe will work would be to make them globals, e.g.
global var_alpha
var_alpha = sc.broadcast(model.params.var_alpha)
# and similarly for the other variables...
Then the alpha_sampler could be much simplified:
#staticmethod
def _alpha_sampler(row):
feature_arr = row[2]
var_alpha_given_rest = 1/((1/var_alpha.value) + feature_arr.shape[0]*(1/var_rating.value))
i = row[0]
items = row[1]
O = row[3] - np.inner(feature_arr,b.value) - beta.value[items] - np.inner(S.value[i],Z.value[items])
E_alpha_given_rest = var_alpha_given_rest * (x_user_g0_inner_over_var.value[i] + O.sum()/var_rating.value)
return np.random.normal(E_alpha_given_rest,np.sqrt(var_alpha_given_rest))
But of course this is really dangerous use of globals that I would like to avoid. Is there a better way that lets me leverage broadcast variables?
Assuming that variables you use here are simply scalars there is probably nothing to gain here from a performance perspective and using broadcast variables will make you code less readable but you can either pass a broadcast variable as an argument to the static method:
class model(object):
#staticmethod
def foobar(a_model, mu):
y = a_model.y
def _foobar(x):
return x - mu.value + y
return _foobar
def __init__(self, sc):
self.sc = sc
self.y = -1
self.rdd = self.sc.parallelize([1, 2, 3])
def get_mean(self):
return self.rdd.mean()
def run_foobar(self):
mu = self.sc.broadcast(self.get_mean())
self.data = self.rdd.map(model.foobar(self, mu))
or initialize it there:
class model(object):
#staticmethod
def foobar(a_model):
mu = a_model.sc.broadcast(a_model.get_mean())
y = a_model.y
def _foobar(x):
return x - mu.value + y
return _foobar
def __init__(self, sc):
self.sc = sc
self.y = -1
self.rdd = self.sc.parallelize([1, 2, 3])
def get_mean(self):
return self.rdd.mean()
def run_foobar(self):
self.data = self.rdd.map(model.foobar(self))

Undertanding OOP and static methods

I haven't coded in OOP ever before. I've some functions to handle and verify VAT numbers and I want to enclose them in a class (more later, with other classes for handle IBAN account numbers make a module or a package, I'm not sure yet what's the difference of both).
I take a VAT number (CIF in spanish terms) and, at first, I need to clean it from any other characters than digits and letters. Then validate the number.
Input:
h55/586-75 4
Desired Output:
H55586754
True
Real Output:
h55/586-75 4
False
My Code:
import re
class CheckingCIF:
_letras = "ABCDEFGHIJKLMNPQRSVW" # Not used yet.
def __init__(self, un_cif):
self.cif = un_cif
self._limpiarCIF()
def _limpiarCIF(self):
self.cif = re.sub('\W', "", self.cif.upper())
return self
def validarCodigoCIF(self):
if len(self.cif) != 9:
return False
numero = self.cif[1:10]
pares = int(numero[1]) + int(numero[3]) + int(numero[5])
impares = 0
for i in range(0, 8, 2):
j = int(numero[i]) * 2
if j < 10:
impares += j
else:
impares += j - 9
digito = str(pares+impares)[-1]
if int(digito) == 0:
checkCIF = 0
else:
checkCIF = 10 - int(digito)
if str(checkCIF) == self.cif[-1]:
return True
else:
return False
if __name__ == "__main__":
entradaCodigoCIF = input('Enter the VAT number: ')
mi_cif = CheckingCIF(entradaCodigoCIF)
print(mi_cif.cif)
print(CheckingCIF.validarCodigoCIF(mi_cif))
The problem isn't in the validarCodigoCIF(self) method, since I've test before and it works fine.
The issue probably is in the _limpiarCIF(self) method because my incomprehension of the Object Oriented Programming and the use of the self word and the static methods.
You don't have static methods, you have regular methods, but are not calling them on the instance:
entradaCodigoCIF = input('Enter the VAT number: ')
mi_cif = CheckingCIF(entradaCodigoCIF)
print(mi_cif.cif)
print(mi_cif.validarCodigoCIF())
Referencing the method on an instance gives you a bound method, an object that knows how to call the underlying function and pass in the instance as a first argument.

Categories

Resources