Gurobi - Solving Capacity Location Problem - python

I am trying to solve a Capacity location Problem from the OR database named: capa
OR files here
The answer should be:
capa 19240822.449 (capacity 8000)
But I found:
Best objective 3.145815023928e+08
For sure it is a problem on my code... Can someone help me?
Maybe I am doing something wrong on the Optmization formula ... or on the construction of my shipping demand. I really do not know, because it looks correct to me.
Any help would be appreciated... thanks in advance
from itertools import product
from math import sqrt
import gurobipy as gp
from gurobipy import GRB
import time
# Get Clients and Facilities
def getFacilities_Clients(file_list):
return int(file_list[0]), int(file_list[1])
# Get Facilities Fixed Costs
def getFacilities_STRCapacity_FixedCosts(file_list, num_facilities):
shift = 2
capacity = []
cost = []
#loop to get all i location costs
for i in range(0,num_facilities*2,2):
#capacity.append(file_list[i+shift])
capacity.append(8000)
cost.append(int(file_list[i+1+shift].replace(".","")))
return capacity, cost
# Get Demand and Allocation Costs for j(customer) to each i(client)
def getClient_Demand_AllocationCosts(file_list, num_facilities, num_customers):
shift = 2 + (num_facilities*2)
demand = []
allocation_cost = []
#loop to get all j Clients
j=0
for r in range(0,num_customers):
#get demand
demand.append(int(file_list[j+shift]))
#loop to get all i location costs
for i in range(0,num_facilities):
allocation_cost.append(float(file_list[j+1+i+shift]))
#fix j
j += num_facilities+1
return demand, allocation_cost
#Read File from OR datasets
fileName='datasets/ORcapa'
ORlist = []
with open(fileName, "r") as f:
ORlist = f.read().split()
##### Sets and Indices #####
num_facilities, num_customers = getFacilities_Clients(ORlist)
capacity, fixed_cost = getFacilities_STRCapacity_FixedCosts(ORlist, num_facilities)
cartesian_prod = list(product(range(num_customers), range(num_facilities)))
# shipping costs
demand, alloc_cost = getClient_Demand_AllocationCosts(ORlist, num_facilities, num_customers)
shipping_cost = dict(zip(cartesian_prod, alloc_cost))
shipping_demand={}
for k, v in shipping_cost.items():
shipping_demand[k] = v * demand[k[0]]
#setup cost
setup_cost = fixed_cost
#demand of customer
dc = demand
#max production
maxp= capacity
start = time.time()
# MIP model formulation
m = gp.Model('CFLP')
##### Decision Variable #####
x = m.addVars(num_facilities, vtype=GRB.BINARY, name='x')
y = m.addVars(cartesian_prod, ub=1, vtype=GRB.CONTINUOUS, name='y')
##### Constraints #####
m.addConstrs((y[(c,f)] <= x[f] for c,f in cartesian_prod), name='Shipping')
m.addConstrs((gp.quicksum(y[(c,f)] for f in range(num_facilities)) == 1 for c in range(num_customers)), name='Demand')
m.addConstrs((gp.quicksum(dc[c]*y[(c,f)] for c in range(num_customers)) <= maxp[f]*x[f] for f in range(num_facilities)), name='Capacity')
##### Objective Function #####
m.setObjective(x.prod(setup_cost)+y.prod(shipping_demand), GRB.MINIMIZE)
m.Params.Method = 1
# Options are:-1=automatic, 0=primal simplex, 1=dual simplex, 2=barrier, 3=concurrent, 4=deterministic concurrent, 5=deterministic concurrent simplex
m.optimize()
end = time.time()

that solved my issue:
m.setObjective(x.prod(setup_cost)+y.prod(shipping_cost), GRB.MINIMIZE)
I was computing a different value for the shipping.

Related

Piecewise objective functions using Pyomo

I'm currently trying to use Pyomo to solve a battery dispatch problem, i.e. Given demand, solar generation and price to buy from the grid and a price to sell back to the grid, when and how much should the battery (dis)/charge.
I am new to Pyomo and I have tried to use the following code.
'''
import pyomo.environ as pyomo
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
# A piecewise example
# We can bound the X with min and max
# Xmin = -1, Xmax = 1
#
#
# / Y * SP, , 0 <= Y <= 1
# X(Y) = |
# \ Y * P , -1 <= Y >= 0
# We consider a flat price for purchasing electricity
df = pd.read_csv('optimal_dispatch_flatprice.csv').iloc[:,1:]
P = df.iloc[:,2] #Price to buy (fixed)
S = df.iloc[:,1] #Solar output
L = df.iloc[:,0] #Demand (load)
SP = df.iloc[:,4] #Price to sell (fixed)
T = len(df)
#Z : charge of battery at time t (how much is in the battery)
Zmin = 0.0
Zmax = 12
#Qt = amount the battery (dis)/charges at time t
Qmin = -5.0
Qmax = 5.0
RANGE_POINTS = {-1.0:-2.4, 0.0:0.0, 1.0:13.46}
def f(model,x):
return RANGE_POINTS[x]
model = pyomo.ConcreteModel()
model.Y = pyomo.Var(times, domain=pyomo.Reals)
model.X = pyomo.Var()
times = range(T)
times_plus_1 = range(T+1)
# Decisions variables
model.Q = pyomo.Var(times, domain=pyomo.Reals) # how much to (dis)/charge
model.Z = pyomo.Var(times_plus_1, domain=pyomo.NonNegativeReals) # SoB
# constraints
model.cons = pyomo.ConstraintList()
model.cons.add(model.Z[0] == 0)
for t in times:
model.cons.add(pyomo.inequality(Qmin, model.Q[t], Qmax))
model.cons.add(pyomo.inequality(Zmin, model.Z[t], Zmax))
model.cons.add(model.Z[t+1] == model.Z[t] - model.Q[t])
model.cons.add(model.Y[t] == L[t]- S[t] - model.Q[t])
model.cons = pyomo.Piecewise(model.X,model.Y, # range and domain variables
pw_pts=[-1,0,1] ,
pw_constr_type='EQ',
f_rule=f)
model.cost = pyomo.Objective(expr = model.X, sense=pyomo.minimize)
'''
I get the error "'IndexedVar' object has no attribute 'lb'.
I think this is referring to the fact that model.Y is index with times.
Can anyone explain how to set the problem up?
Since one of the variables is indexed, you need to provide the index set as the first argument to Piecewise. E.g., Piecewise(times,model.X,model.Y,...

How to use MIPGap and TimeLimit from Gurobi in python?

I'm working on a large scale MILP. So I have to set the time limit to a reasonable value or I have to set the MIPGap to a reasonable level. I already know the documentation from gurobi.
MIPGap: https://www.gurobi.com/documentation/6.5/refman/mipgap.html
TimeLimit: https://www.gurobi.com/documentation/8.0/refman/timelimit.html#parameter:TimeLimit
MIPGap Gurobi will stop when it finds a solution within a percentage of optimal
TimeLimit Gurobi will stop after a certain amount of time.
But can you send me an example with setting for example the time limit to 5 minutes
or setting the MIPGap to 5 % ?
I don't know how to exactly implement those character?
Please help me I am quite new to python
I tried this but this doesn't work
model.Params.TimeLimit = 5
model.setParam("MIPGap", mipgap)
Here is a short version of my model
from gurobipy import *
import csv
import geopandas as gpd
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
from pandas.core.common import flatten
import math
################################# SOLVE function START ###################################################################
def solve(
vpmaint, wpunit, wuunit, vumaint,
kfuel, koil, kbio,
hb, ht,
cj, ci,
zinvestp, zinvestu,
DEMAND, DEMANDM,
LOCATION, SOURCE, BTYPE, SOURCEM,
osi, oij, ojm
):
model = Model("Biomass to liquid supply chain network design")
################################# SOLVE function END ###################################################################
####################################################### variable section START ####################################################################################################
#binary variables ############################# Binary 1-2 ####################################################
#binary 1: Pyrolyse i with capacity p open?
fpopen = {}
for i in LOCATION:
for p in R:
fpopen[i,p] = model.addVar(vtype = GRB.BINARY,name = "fpopen_%s_%s" % (i,p))
#binary 2: Upgrading j with capacity r and technology t open?
fuopen = {}
for j in LOCATION:
for r in R:
for t in TECHNOLOGY:
fuopen[j,r,t] = model.addVar(vtype = GRB.BINARY,name = "fuopen_%s_%s_%s" % (j,r,t))
################################################ continous variables Integer 1-9 #############################################################
#integer 1: Mass of Biomass type b from Source s to Pyrolyse i
xsi = {}
for s in SOURCE:
for i in LOCATION:
for b in BTYPE:
xsi[s,i,b] = model.addVar(vtype = GRB.INTEGER,name = "xsi_%s_%s_%s" % (s,i,b))
#integer 2:Mass of Biomass type b from Source s to Pyrolyse i
xjm = {}
for j in LOCATION:
for m in DEMAND:
xjm[j,m] = model.addVar(vtype = GRB.INTEGER,name = "xjm_%s_%s" % (j,m))
model.update()
model.modelSense = GRB.MAXIMIZE
####################################################### Objective Function START
model.setObjective(
#quicksum(DEMANDM[m] * l for m in DEMANDM )
quicksum(xjm[j,m] * l for j in LOCATION for m in DEMAND)
- quicksum(ainvest[i] + aoperation[i] + aprod[i] for i in LOCATION)
- quicksum(einvest[j] + eoperation[j] + eprod[j] for j in LOCATION)
## ......
####################################################### Constraints
############################## Satisfy Demand Constraint 1-3
# Constraint 1: Always Satisfy Demand at marketplace m
for m in DEMAND:
model.addConstr(quicksum(xjm[j,m] for j in LOCATION) <= int(DEMANDM[m]))
# for m in DEMAND:
# model.addConstr(quicksum(x[j,m] for j in LOCATION) >= DEMANDM[m])
# Constraint 2: The amount of bio-oil sent from pyrolyse station i to Upgrading
###...Here are more constraints
model.optimize()
model.getVars()
model.MIPGap = 5
model.Params.TimeLimit = 1.0
model.setParam("MIPGap", mipgap)
Alternatively, you could call the setParam() method of the model:
model.setParam('MIPGap', 0.05)
model.setParam('Timelimit', 300)
You need to set the parameters before you call Model.optimize(). Also, the units for MIPGap and TimeLimit are fractions and seconds, respectively. So your code should be:
model.Params.MIPGap = 0.05 # 5%
model.Params.TimeLimit = 300 # 5 minutes
model.optimize()
I haven't run this code in a couple years... I don't have a Gurobi license anymore. But, something like this should work. You didn't mention how you encoded your model. The below is from a pyomo script. I would think something similar would work however you get a handle on the solver instance.
solver = SolverFactory("gurobi")
solver.options['timeLimit'] = 1200 # seconds
solver.options['mipgap'] = 0.01

Is it possible to loop to a certain value and carry on further calculations with this value?

I am new here and new in programming, so excuse me if the question is not formulated clearly enough.
For a uni assignment, my labpartner and I are programming a predator-prey system.
In this predator-prey system, there is a certain load factor 'W0'.
We want to find a load factor W0, accurate to 5 significant digits, for which applies that there will never be less than 250 predators (wnum[1] in our code). We want to find this value of W0 and we need the code to carry on further calculations with this found value of W0. Here is what we've tried so far, but python does not seem to give any response:
# Import important stuff and settings
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
print ('Results of Group 4')
def W0():
W0 = 2.0
while any(wnum[1])<250:
W0 = W0-0.0001
return W0
def W(t):
if 0 <= t < 3/12:
Wt = 0
elif 3/12 <= t <= 8/12:
Wt = W0
elif 8/12 < t < 1:
Wt = 0
else:
Wt = W(t - 1)
return Wt
# Define the right-hand-side function
def rhsf(t,y):
y1 = y[0]
y2 = y[1]
f1 = (2-2*10**-3*y2)*y1-W(t)*y1
f2 = (-3.92+7*10**-3*y1)*y2
return np.array([f1,f2])
# Define one step of the RK4 method
def RK4Step(tn,wn,Dt,f):
# tn = current time
# wn = known approximation at time tn
# Dt = the time step to use
# f = the right-hand-side function to use
# wnplus1 = the new approximation at time tn+Dt
k1 = Dt*f(tn,wn)
k2 = Dt*f(tn+0.5*Dt,wn+0.5*k1)
k3 = Dt*f(tn+0.5*Dt,wn+0.5*k2)
k4 = Dt*f(tn+Dt,wn+k3)
wnplus1 = wn + 1/6*(k1 +2*k2 +2*k3 +k4)
return wnplus1
# Define the complete RK4 method
def RK4Method(t0,tend,Dt,f,y0):
# t0 = initial time of simulation
# tend = final time of simulation
# Dt = the time step to use
# f = the right-hand-side function to use
# y0 = the initial values
# calculate the number of time steps to take
N = int(np.round((tend-t0)/Dt))
# make the list of times t which we want the solution
time = np.linspace(t0,tend,num=N+1)
# make sure Dt matches with the number of time steps
Dt = (tend-t0)/N
# Allocate memory for the approximations
# row i represents all values of variable i at all times
# column j represents all values of all variables at time t_j
w = np.zeros((y0.size,N+1))
# store the (given) initial value
w[:,0] = y0
# Perform all time steps
for n,tn in enumerate(time[:-1]):
w[:,n+1] = RK4Step(tn,w[:,n],Dt,f)
return time, w
# Set all known values and settings
t0 = 0.0
tend = 10.0
y0 = np.array([600.0,1000.0])
Dt = 0.5/(2**7)
# Execute the method
tnum, wnum = RK4Method(t0,tend,Dt,rhsf,y0)
# Make a nice table
alldata = np.concatenate(([tnum],wnum),axis=0).transpose()
table = pd.DataFrame(alldata,columns=['t','y1(t)','y2(t)'])
print('\nA nice table of the simulation:\n')
print(table)
# Make a nice picture
plt.close('all')
plt.figure()
plt.plot(tnum,wnum[0,:],label='$y_1$',marker='o',linestyle='-')
plt.plot(tnum,wnum[1,:],label='$y_2$',marker='o',linestyle='-')
plt.xlabel('$t$')
plt.ylabel('$y(t)$')
plt.title('Simulation')
plt.legend()
# Do an error computation
# Execute the method again with a doubled time step
tnum2, wnum2 = RK4Method(t0,tend,2.0*Dt,rhsf,y0)
# Calculate the global truncation errors at the last simulated time
errors = (wnum[:,-1] - wnum2[:,-1])/(2**4-1)
print('\nThe errors are ',errors[0],' for y1 and ',errors[1],' for y2 at time t=',tnum[-1])

How can I optimise the weights of CNN using PSO?

I want to optimize the weights of CNN using Particle Swarm Optimization. Basically weights are at penultimate layer and filters that are tobe optimised. The PSO replaces the optimisers and rest work is done in same way. Will it be possible by using Keras or Tensorflow? Have written a PSO code that is attached below.
import random
w = 0.729844 # Inertia weight to prevent velocities becoming too large
c1 = 1.496180 # Scaling co-efficient on the social component
c2 = 1.496180 # Scaling co-efficient on the cognitive component
dimension = 20 # Size of the problem
iterations = 3000
swarmSize = 30
# This class contains the code of the Particles in the swarm
class Particle:
velocity = []
pos = []
pBest = []
def __init__(self):
for i in range(dimension):
self.pos.append(random.random())
self.velocity.append(0.01 * random.random())
self.pBest.append(self.pos[i])
return
def updatePositions(self):
for i in range(dimension):
self.pos[i] = self.pos[i] + self.velocity[i]
return
def updateVelocities(self, gBest):
for i in range(dimension):
r1 = random.random()
r2 = random.random()
social = c1 * r1 * (gBest[i] - self.pos[i])
cognitive = c2 * r2 * (self.pBest[i] - self.pos[i])
self.velocity[i] = (w * self.velocity[i]) + social + cognitive
return
def satisfyConstraints(self):
#This is where constraints are satisfied
return
# This class contains the particle swarm optimization algorithm
class ParticleSwarmOptimizer:
solution = []
swarm = []
def __init__(self):
for h in range(swarmSize):
particle = Particle()
self.swarm.append(particle)
return
def optimize(self):
for i in range(iterations):
print "iteration ", i
#Get the global best particle
gBest = self.swarm[0]
for j in range(swarmSize):
pBest = self.swarm[j].pBest
if self.f(pBest) > self.f(gBest):
gBest = pBest
solution = gBest
#Update position of each paricle
for k in range(swarmSize):
self.swarm[k].updateVelocities(gBest)
self.swarm[k].updatePositions()
self.swarm[k].satisfyConstraints()
#Update the personal best positions
for l in range(swarmSize):
pBest = self.swarm[l].pBest
if self.f(self.swarm[l]) > self.f(pBest):
self.swarm[l].pBest = self.swarm[l].pos
return solution
def f(self, solution):
#This is where the metaheuristic is defined
return random.random()
def main():
pso = ParticleSwarmOptimizer()
pso.optimize()
Well, you need to define a good cost function, which measures the error between the optimal number of layers and filters and current layers and filters.
But what goal you want to obtain? Minimize time cost or minimize the accuracy?
By the way, if its accuracy, it might be too costy, because for each population of particle swarm optimization, it would train your CNN model once.

CVXPY country/sector/industry like constraints for min variance optimization

I am trying to implement a portfolio optimization that uses constraints to define e.g. max exposure to country/ sector/ industry etc. I have implemented the following code below, where I pass in a 'africa' vector to map stocks to country africa, in my constraints I then bound those to be not more then 40% in weights overall. The only way that I managed to implement it is to use sum_weights over the indexes where africa = 1. I also tried using the Parameter function but didn't succeed. There must be a more elegant way to apply these kind of constraints, hopefully. Any suggestion is appreciated. Also if anyone knows about an example that shows the use of tracking error constraints, turnover constraints or volatility constraints, these are the ones where I am also still struggling with.
import numpy as np
from cvxpy import *
np.random.seed(1)
n = 10 # number of assets
mu = np.abs(np.random.randn(n,1)) #mean
Sigma = np.random.randn(n,n)
Sigma = Sigma.T.dot(Sigma)
# Long only PFO Opt
w = Variable(n)
#africa = Parameter(10, sign='positive')
#africa.value = [1,1,1,0,0,0,0,0,0,0]
africa = [0,0,0,0,0,0,0,1,1,1]
gamma = Parameter(sign='positive')
ret = mu.T*w
risk = quad_form(w,Sigma)
filters = [i for i in range(len(africa)) if africa[i] == 1]
constraints = [sum_entries(w) == 1, w >=0, w[1] > 0.50, w[0] == 0, sum_entries(w[filters]) == 0.4]
#prob = Problem(Maximize(ret - gamma*risk), [sum_entries(w) == 1, w >=0])
prob = Problem(Minimize(risk), constraints)
SAMPLE = 1000
risk_data = np.zeros(SAMPLE)
ret_data = np.zeros(SAMPLE)
gamma_vals = np.logspace(-2,3,num=SAMPLE)
for i in range(SAMPLE):
gamma.value = gamma_vals[i]
prob.solve()
risk_data[i] = sqrt(risk).value
ret_data[i] = ret.value
print(prob.status)
print(prob.value)
print('OPT WEIGHTS : ')
for i in range(n):
print(round(w[i].value,3))
I think you may want to have a look at these examples. The developer has incorporated portfolio risk constraint as follows:
import cvxpy as cp
w = cp.Variable(n)
gamma = cp.Parameter(nonneg=True)
ret = mu.T*w
risk = cp.quad_form(w, Sigma)
Lmax = cp.Parameter()
# Portfolio optimization with a leverage limit and a bound on risk.
prob = cp.Problem(cp.Maximize(ret),
[cp.sum(w) == 1,
cp.norm(w, 1) <= Lmax,
risk <= 2])
Here's the link to jupyter nbviewer

Categories