Pyomo: Implicitly replacing the Component attribute - python

I am trying to solve this problem in Pyomo. What I have done is like this:
model = AbstractModel()
model.Tom=Param(initialize=20100)
model.Peter=Var(domain=NonNegativeReals)
model.Gary =Var(domain=NonNegativeReals)
model.Nina=Var(domain=NonNegativeReals)
model.Samir=Var(domain=NonNegativeReals)
model.Linda=Var(domain=NonNegativeReals)
model.Bob=Var(domain=NonNegativeReals)
model.Y=Var(within=Binary)
model.M=Param(initialize=1000)
model.Cons_Peter = Constraint(expr=model.Peter-5000 >= model.Tom)
model.Cons_Nina = Constraint(expr=model.Nina-5000 >= model.Tom)
model.Cons_Samir = Constraint(expr=model.Samir-5000 >= model.Tom)
def Cons_Gary(model):
return (model.Tom+model.Peter) <= model.Gary
model.Cons_Gary = Constraint(rule=Cons_Gary)
def Sum_1(model):
return (model.Nina+model.Samir)>=2*(model.Tom+model.Peter)
model.Sum_1=Constraint(rule=Sum_1)
model.Cons_Bob1 = Constraint(expr=model.Bob+model.Y*model.M>= model.Peter)
model.Cons_Bob2 = Constraint(expr=model.Bob+(1-model.Y)*model.M>= model.Samir)
def Sum_2(model):
return model.Bob+model.Peter>=60245
model.Sum_2=Constraint(rule=Sum_2)
model.Cons_Linda=Constraint(expr=model.Linda<= model.Tom+model.Bob)
def obj_salary(model):
return model.Tom+model.Linda+model.Gary+model.Bob+model.Nina+model.Samir+model.Peter
model.salary= Objective(rule=obj_salary, sense=minimize)
The error is WARNING: Implicitly replacing the Component attribute Tom
(type=<class
'pyomo.core.base.param.SimpleParam'>) on block unknown with a new
Component (type=<class 'pyomo.core.base.param.SimpleParam'>). This is
usually indicative of a modelling error. To avoid this warning, use
block.del_component() and block.add_component().
I don't know why it can't run properly to get the minimum value of model.salary.
Can anyone help me with it?
Many thanks to your help!

Omg. I find the mistake finally.
It should be 'print(value(instance.profit))' not 'print(value(model.profit))'.
What a stupid mistake I made.

Related

Finding root of a function with two outputs specified in return statement

I am currently writing a code in Python where the objective is to find the root of the output of a function with respect to input variable x. The code looks like this:
def Compound_Correlation_Function(x):
# Here comes a long part of the code...
Equity_Solve = Tranches.loc[0, 'Par_Spread_bps'] - Market_Data.iloc[0,0]
Mezzanine_Solve = Tranches.loc[1, 'Par_Spread_bps'] - Market_Data.iloc[1,0]
return Equity_Solve, Mezzanine_Solve
Correlation_Value = optimize.root(Compound_Correlation_Function, x0 = 0.3)
As can be seen in the code block above, there are two outputs specified:
Equity_Solve
Mezzanine_Solve
I now want to find the root for both outputs separately. If I comment out the Mezzanine_Solve part in the return statement, then the the optimize procedure gives me the solution I want. Obviously, I want to automate my code as much as possible. Is it possible to specify the output for which I want to find the root in the optimize statement?
I tried the following, without success:
Correlation_Value = optimize.root(Compound_Correlation_Function[0], x0 = 0.3)
Correlation_Value = optimize.root(Compound_Correlation_Function(x)[0], x0 = 0.3)
Correlation_Value = optimize.root(Compound_Correlation_Function()[], x0 = 0.3)
Any help is appreciated. Thank you in advance!
I think the problem is that your function returns a tuple of numbers, but root is expecting a single number.
Assuming you want to solve each equation separately, then you could include an argument in Compound_Correlation_Function to switch between the functions:
def Compound_Correlation_Function(x, return_equity=True):
# Here comes a long part of the code...
if return_equity:
Equity_Solve = Tranches.loc[0, 'Par_Spread_bps'] - Market_Data.iloc[0,0]
return Equity_Solve
else:
Mezzanine_Solve = Tranches.loc[1, 'Par_Spread_bps'] - Market_Data.iloc[1,0]
return Mezzanine_Solve
Then pass the return_equity argument in as an extra argument via args, i.e. call
root(Compound_Correlation_Function, x0=0.3, args=(True,))
to solve Equity_Solve, and set args=(False,) to solve Mezzanine_Solve.
You could also define a function wrapper that calls Compound_Correlation_Function and returns only one of the values.
surely you're overthinking it. Just define two new functions:
def equity_solve(x):
return Compound_Correlation_Function(x)[0]
def mezzanine_solve(x):
return Compound_Correlation_Function(x)[1]

cplex changes the fixed variable after solving the problem in pyomo

I am trying to solve a MIP, I use pyomo, and Cplex(Interactive Optimizer 20.1.0.0) is solver.
The problem is that I want to fix some binary integer variables then solve the problem, and I used:
model.y[1,4].fix(1)
model.y[2,3].fix(0)
, but I have noticed that after solving the problem those fixed variables have changed to another values.
How can I say cplex to not change that fixed variables?
let me use the bus example for fixed start with pyomo
import pyomo.environ as pyo
from pyomo.opt import SolverFactory
opt = pyo.SolverFactory("cplex")
model = pyo.ConcreteModel()
model.nbBus = pyo.Var([40,30], domain=pyo.PositiveIntegers)
#fixed start
model.nbBus[40].fix(3)
# end of fixed start
model.OBJ = pyo.Objective(expr = 500*model.nbBus[40] + 400*model.nbBus[30])
model.Constraint1 = pyo.Constraint(expr = 40*model.nbBus[40] + 30*model.nbBus[30] >= 300)
results = opt.solve(model)
print("nbBus40=",int(model.nbBus[40].value))
print("nbBus30=",int(model.nbBus[30].value))
gives
nbBus40= 3
nbBus30= 6
whereas if you remove the fixed start you get
nbBus40= 6
nbBus30= 2
Since fixing variable didn't work for me, I tackle my problem with adding a new constraint to the model, and it works.
def yvar_fix(model, i, j ):
if (i,j) in y_set_init:
constraint = (model.y[i,j] == 1)
else:
constraint = (model.y[i,j] == 0)
return constraint
model.yvar_fix = pe.Constraint(model.edges, rule=yvar_fix)

Print the return of a method in python

I'm fairly new to OOP in python and i cant seem to figure out if I'm doing this the right way. I have a first script called TP2_dat.py in which I solve a problem in AMPL and then at the end i retrieve the variable X as follows (I simplified the code):
import amplpy
import os
class Solver:
def __init__(self, set_k, larg_on, poids):
self.set_K = set_k
self.larg_on = larg_on
self.poids = poids
def solve(self):
...
X = ampl.getVariable('X')
X_val = X.getValues()
X_val_dic = X_val.toDict()
# print(X_val_dic)
return X_val_dic
I tried to do a print instead of a return from the first script and it worked. But now i want to print it from another script as follows so i dont get the None at the end of the print from the second script:
from TP2_dat import Solver
set_K = [1,2,3,4,5,6]
larg_on = [4,3,5,4,6,5]
poids = [0,4,5,2,3,6,4,0,4,3,5,3,5,4,0,4,7,8,2,3,4,0,3,3,3,5,7,3,0,5,6,3,8,3,5,0]
affichage = Solver(set_K, larg_on, poids)
affichage.solve()
print(X_val_dic)
The part that i dont understand is can i do something similar to this? Am i right in thinking to return the value of X_val_dic or should i do something else?
Thanks a lot for your help !!
Since the class method solve returns a value you need to set it equal to a variable or print it directly:
X_val_dic = affichage.solve()
print(X_val_dic)
or
print(affichage.solve())
See this article for more information on pythons variable scoping.

How to prevent infeasible error with pulp and python?

I have an optimization problem and I write a python program to solve it. I used Pulp with the CPLEX solver:
import pulp
prob = LpProblem("myProblem", LpMinimize)
x = pulp.LpVariable.dicts("p", range( K ), 0, 1, pulp.LpContinuous)
prob += pulp.lpSum( x[k] for k in range( K ) )
...
# Rest of the constraints
status = prob.solve( pulp.CPLEX( msg = 0 ) )
I get the error:
File "C:\Anaconda\lib\site-packages\pulp\solvers.py", line 468, in readsol
raise PulpSolverError, "Unknown status returned by CPLEX: "+statusString
pulp.solvers.PulpSolverError: Unknown status returned by CPLEX: infeasible
My question is : How can I test if the problem is infeasible or not? I want to prevent this event like if problem is infeasible then return 0.
I tried :
if prob.status == 'infeasible':
...
and I tried
if pulp.LpStatusInfeasible == 'infeasible':
...
Is your 'problem' finding whether a given problem instance is feasible or not, or are you actually interested in the solution if it is feasible. Rather than just trap the error when the model is infeasible, I would examine your problem and try to add some slack variables and penalty costs to give you some more information when the problem would otherwise be infeasible.
So rather than add a hard constraint like
sum(x) <= K
you could try something like
sum(x) <= K + penaltyVar
and add a term into your objective like 1000000 * penaltyVar so that the solver really doesn't want to use that penalty variable as non-zero.
Adding these slack/penalty variables in various places in your model can help identify where the constraints are too tight and making your model infeasible.
Don't just ignore the answer above though, as it is still valuable to trap the error.
I think you can solve this by caging the statement inside a try-exception clause.
for example:
# ...
try:
status = prob.solve(pulp.CPLEX(msg = 0))
except PulpSolverError:
# infeasible
return 0
return status

TypeError: 'numpy.ndarray' object is not callable on Euler's method LTE calculation

Before anything, sorry any sppeling, english issues, english is not my mother tongue.
I'm doing an assgment on Euler's Method to calculate ODEs, and in the calculatrion of the LTE(Local truncation error) I keep receiving this error:
TypeError: 'numpy.ndarray' object is not callable
I took a look at previous questions with the same subject, but I didn't find exactly what I was looking for. Below the code for the euler's method and the error calculation.
def euler(f,y0,a,b,h):
t,y = a,y0
vet_s = np.array([])
vet_err = np.array([])
while t <= b:
#print t , y
vet_s = np.append(vet_s, y)
t += h
y += h * f(t,y)
vet_err = np.append(vet_err, erro(yn, y, t)) # The problem is here
return vet_s, vet_err
def y(t, y):
return lbd*y
def yn(t):
return np.exp(-1*t)
def erro(yn, un, t):
erro_local = abs(yn(t) - un)
return erro_local
When I call the error calculation inside the vet_err assigment function I receive the error displayed above.
I think that it's a simple fix, but i can't find it myself.
The main call for the Euler's method is this:
h = 30./60.
lbd = -1.0
t = np.arange(0, 30, h)
sol = erro = np.array([])
sol, erro = euler(y, 1.0, 0.0, 30.0, h)
Is there any syntax, code issue? Also any pointer in order to improve the code would be of great help. Thanks.
Some issues I see in your code -
I am assumming you have defined the function named erro first and then afterwards you are also doing -
erro = np.array([])
This causes the name erro to point to a np.array , which is what is causing the issue you are having, you should use a different name here , maybe something like erro1 (or some other good meaningful name).
Then in the function - euler(f,y0,a,b,h) - you are defining variable with name - y . But there is also a y function outside, (This does not directly cause issues, since you passed the reference to function y as the first argument to this function) .
But I would advice against doing this (As you may encounter issues later on). Always use different meaningful names, I do not think there is a shortage of words/letters in English for use :) .
Also there is no need to do -
sol = erro = np.array([])
Since you reassign it to return value of euler() functio in next line, you do not need to even define them before that (unless you want to use them , which does not seem like the case).

Categories

Resources