cplex changes the fixed variable after solving the problem in pyomo - python

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)

Related

PYOMO: Constraint does not have a proper value

I'm pretty new to pyomo and python, so this might be a pretty dumb mistake.
The gist of what I'm trying to do: I have a demand array, one demand value for each time step. The power bought plus the power provided by a CHP should equal the demand in each time step. (That's what I'm trying to do with the constraint). Running it leads to the following error:
ValueError: Constraint 'ElPowerBalanceEq' does not have a proper value. Found '<generator object ElPowerBalance.<locals>.<genexpr> at 0x000001BBF81DC040>'
Expecting a tuple or equation. Examples:
sum(model.costs) == model.income
(0, model.price[item], 50)
Here's the relevant code.
Thanks in advance :-)
from pyomo.environ import*
import numpy as np
t = np.linspace(0,24,97) #time variable, one day in 0.25 steps
model.i=range(t.size) #index
model.Pel_buy = Var(within=PositiveReals) #electrical power bought
model.Pel_chp = Var(within=PositiveReals) #electrical power of chp
Del = 2+2*np.exp(-(t-12)**2/8**2) #demand electrical
#Define constraints
#Power Balance
def ElPowerBalance(model) :
return (model.Pel_chp[i] + model.Pel_buy[i] == Del[i] for i in model.i)
model.ElPowerBalanceEq = Constraint(rule = ElPowerBalance)
Your ElPowerBalance() function is returning a generator object because you have the return value wrapped in parantheses (which python interprets as a generator). The simplest solution would be to use the * operator to unpack your generator, like so:
def ElPowerBalance(model) :
return *(model.Pel_chp[i] + model.Pel_buy[i] == Del[i] for i in model.i)

Pyomo: Implicitly replacing the Component attribute

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.

Solving Model with pulp python

I have been struggling with solving the following problem:
I have some values stored in variable returns, and I want to multiply them by a weight (x_vars)in order to make the sum of the products and obtain the value of the variable target_return. As the following equation:
I am struggling with the answer returned, as it saying x_13 = 1. But is not correct. I have tried to do it with normal constrains and eslastic but I get no correct answer. I have a tolerance of let's say 0.01% of error.
Any guess?
Thanks
import pulp as plp
# Name model
# set variables
target_return = 0.0204185791833761
returns = [0.025865338474480914,
0.031617753987556174,
0.017530329404997325,
-0.0008543358059154293,
0.010510143115372461,
0.012048338516174262,
0.04959181591738604,
0.06059545751936519,
0.05926623356137273,
0.058971753714631814,
0.03442022388647947,
0.013688974565667422,
0.02104075216985901,
-0.0021299262578251543,
0.017882182143459602,
0.018964184657020766,
0.005792320704504306,
0.018823216764509265,
-0.0015860431556348198,
0.008352716776521163,
0.030728674721250515,
0.016529301951210496,
0.0184734317514465,
-0.0008822232596910062,
0.010912806711330658,
0.023530497410194418,
0.0378090116601979,
0.009456335242604919,
0.005556382185357922,
0.020013334218681678,
0.05852489326632937,
0.047988175193893645,
0.016134386609760742,
0.014350880108888964,
0.006756782462879585]
# Initialize model
prob=plp.LpProblem("Find Weights Model", plp.LpMinimize)
x_vars=plp.LpVariable.dicts("x", range(0, len(returns)), 0, 1)
for index in range(len(returns)):
x_vars[index].setInitialValue(0.5)
#Set problem
prob += plp.lpSum([x_vars[i] for i in x_vars]) == 1
#Set constrain
constrain=plp.LpConstraint(plp.lpSum(
[returns[i]*x_vars[i] for i in range(0, len(returns))]), rhs=target_return)
# To use standard constrain uncomment following line
#prob.addConstraint(constrain)
# To use elastic constrain uncomment following line
elastic_constrain=constrain.makeElasticSubProblem(penalty = 500000,proportionFreeBoundList =[0.001,0.0001])
prob.extend(elastic_constrain)
prob.solve(plp.PULP_CBC_CMD(msg=True, warmStart=True))
final_weights={}
for v in prob.variables():
final_weights[v.name]=v.varValue
print("Status:", plp.LpStatus[prob.status])
final_weights
Possible solutions:
solution1 = [0.00962135141677065,
0.00962135141677065,
0.0277264834687149,
0.0297957188693739,
0.0324961558793471,
0.030826881062523,
0.0306009427392119,
0.0250863577897657,
0.0234700849350161,
0.0236653284777789,
0.0237085827820698,
0.0273148420035226,
0.0303599573647406,
0.0292800893464517,
0.0326835213770196,
0.0297440370126145,
0.0295851066643113,
0.0315198597719625,
0.0296058126214705,
0.0326036329340179,
0.0311437752841399,
0.0278570759221869,
0.0299427552142207,
0.0296571910611703,
0.0325002521378998,
0.0307677356659276,
0.0289143823239777,
0.0268170787933395,
0.0309816698637205,
0.0315545156635921,
0.0294310019878726,
0.023774220455596,
0.0253219090166822,
0.0300007623180508,
0.0302627332639599]
solution2 = [0.0291039150753347,
0.0291039150753347,
0.028739103831572,
0.0296325128619877,
0.0307984495156388,
0.0300777243941537,
0.0299801757193628,
0.027599206714805,
8.34695965451632E-05,
0.0269856659961344,
0.0270043421537945,
0.0285613748092319,
0.0298761263170002,
0.0294098868961038,
0.0308793458966854,
0.0296102001652331,
0.0295415791679557,
0.0303769265588311,
0.0295505206943934,
0.0308448536374279,
0.0302145485146196,
0.0287954885757358,
0.0296959977222549,
0.0295727013961937,
0.030800217918514,
0.0300521885203749,
0.0292519883685474,
0.0283464607865791,
0.0301445556616913,
0.030391887092054,
0.0294750434895131,
0.0270326804365011,
0.0277009088398652,
0.0297210421051448,
0.0298341506415484]
In excel, I've got the solutions using the following configuration:
I think the solution you got from pulp (CBC) is correct, it's just not the same as the one from Excel. To confirm the constraints are respected you can do the following:
solution3 = [x.value() for x in x_vars.values()]
# objective: 0.0204185791833761
sum(val*returns[i] for i, val in enumerate(solution1))
# 0.02053629325573023
sum(val*returns[i] for i, val in enumerate(solution3))
# 0.02039816058427895
# constraint:
sum(val for i, val in enumerate(solution1))
# 0.9782431569057903
sum(val for i, val in enumerate(solution3))
# 0.999999999
In fact, the solution from pulp is closer to the objective and respects a lot better the constraint of sum()=1.

CVXPY throws SolverError

When using CVXPY, I frequently get "SolverError". Their doc just says this is caused by numerical issues, but no further information is given about how to avoid them.
The following code snippet is an example, the problem is trivial, but the 'CVXOPT' solver just throws "SolverError". It is true that if we change the solver to another one, like 'ECOS', the problem will be solved as expected. But the point is, 'CVXOPT' should in principle solve this trivial problem and it really baffles me why it doesn't work.
import numpy as np
import cvxpy as cv
np.random.seed(0)
temp = np.random.rand(5)
T = 2
x = cv.Variable(T)
u = cv.Variable(2, T)
pbs = []
for t in range(T):
cost = cv.sum_squares(x[t]-temp[t])
constr = [x[t] == u[0,t]+u[1,t],]
pbs.append(cv.Problem(cv.Minimize(cost), constr))
prob = sum(pbs)
prob.solve(solver='CVXOPT')
Use prob.solve(solver='CVXOPT', kktsolver=cv.ROBUST_KKTSOLVER) to make the optimisation process more robust.

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

Categories

Resources