How to implement LPP function using PULP in python 3.7? - python-3.x

I want to calculate the Linear Programming Problem(LPP) for my Max function and its constraints as below
I used the follwing pulp code in python 3.7.
import random
import pulp
import pandas as pd
L1=[5,10,15]
L2=[1,2,3]
L3=[5,6,7]
n = 10
set_I = range(2, n-1)
set_J = range(2, n)
c = {(i,j): random.normalvariate(0,1) for i in set_I for j in set_J}
a = {(i,j): random.normalvariate(0,5) for i in set_I for j in set_J}
l = {(i,j): random.randint(0,10) for i in set_I for j in set_J}
u = {(i,j): random.randint(10,20) for i in set_I for j in set_J}
b = {j: random.randint(0,30) for j in set_J}
e={0 or 1 or 0.5}
I=L1
P=L2
C=L3
opt_model = pulp.LpProblem(name="LPP")
# if x is Continuous
x_vars = {(i,j):
pulp.LpVariable(cat=pulp.LpContinuous,
lowBound=l[i,j], upBound=u[i,j],
name="x_{0}_{1}".format(i,j))
for i in set_I for j in set_J}
# if x is Binary
x_vars = {(i,j):
pulp.LpVariable(cat=pulp.LpBinary, name="x_{0}_{1}".format(i,j))
for i in set_I for j in set_J}
# if x is Integer
x_vars = {(i,j):
pulp.LpVariable(cat=pulp.LpInteger,
lowBound=l[i,j], upBound= u[i,j],
name="x_{0}_{1}".format(i,j))
for i in set_I for j in set_J}
# Less than equal constraints
constraints = {j :
pulp.LpConstraint(
e=pulp.lpSum(a[i,j] * x_vars[i,j] for i in set_I),
sense=pulp.pulp.LpConstraintLE,
rhs=b[j],
name="constraint_{0}".format(j))
for j in set_J}
# >= constraints
constraints = {j :
pulp.LpConstraint(
e=pulp.lpSum(a[i,j] * x_vars[i,j] for i in set_I),
sense=pulp.LpConstraintGE,
rhs=b[j],
name="constraint_{0}".format(j))
for j in set_J}
# == constraints
constraints = {j :
pulp.LpConstraint(
e=pulp.lpSum(a[i,j] * x_vars[i,j] for i in set_I),
sense=pulp.LpConstraintEQ,
rhs=b[j],
name="constraint_{0}".format(j))
for j in set_J}
objective = pulp.lpSum(x_vars[i,j] * ((e*I*(C[i])) + (1-e)* P(i) )
for i in set_I
for j in set_J)
# for maximization
opt_model.sense = pulp.LpMaximize
opt_model.setObjective(objective)
# solving with CBC
opt_model.solve()
# solving with Glpk
opt_model.solve(solver = GLPK_CMD())
opt_df = pd.DataFrame.from_dict(x_vars, orient="index",
columns = ["variable_object"])
opt_df.index =pd.MultiIndex.from_tuples(opt_df.index,names=
["column_i", "column_j"])
opt_df.reset_index(inplace=True)
opt_df["solution_value"] = opt_df["variable_object"].apply(lambda
item: item.varValue)
opt_df.drop(columns=["variable_object"], inplace=True)
opt_df.to_csv("./optimization_solution.csv")
I am beginner to LPP and PULP. So I implemented first 2 equations only up to my knowledge.That code also gives me error as below
TypeError: can't multiply sequence by non-int of type 'set'
How to add the constraints of equations 3 and 4 to my code and resolve my error. Also guide me whether my code is correct or not where I want to modify to satisfy the Max function.. Thanks in advance.

Related

PuLP Optimization problem - how to add constraints?

I am trying to solve a linear programming problem with the following constraints:
for some given values of N and T. So suppose N={1,2} and T={1,2}
It is easy to write out for small |N|, but is impossible to write as N becomes large.
Im confused as to how to actually code these sums by indexing on my objective variables.
I used the following to create my objective variables:
for t in range(1,T+1):
for i in range(1,n+1):
for j in range(1,n+1):
# Skip the x_i,i,t entries
if j == i:
continue
element = "x"+str(i)+','+str(j)+','+str(t)
x_ijt_holding.append(element)
x_ijt =[]
for i in x_ijt_holding:
x_ijt.append(pulp.LpVariable(i, cat = "Binary"))
Initially I thought I could just define each constraint with LpVariable, but I realized the solver doesn't like that.
For example I did:
# Constraint 2 enter entries
x_ijt_2_holding = []
for j in range(1,n+1):
for i in range(1,j):
equations_2 = []
equations_3 = []
for t in range(1, T+1):
equations_2.append("x"+str(i)+','+str(j)+','+str(t))
equations_2.append("x"+str(j)+','+str(i)+','+str(t))
x_ijt_2_holding.append(equations_2)
# Constraint 2 as LpVariable:
for i in x_ijt_2_holding:
temp = []
for sublist in i:
temp.append(pulp.LpVariable(sublist, cat = "Binary"))
x_ijt_con2.append(temp)
So how would I then code the constraints into the problem?
Constraints defines relationships on previously defined variable written as equations. When you are building your constraints you need to reference the variables you defined in your first part. Saving your variables in dicts makes it much easier to reference your variables later.
Take a look at this
"""
Optimizing
sum(x[i][j][t] + x[j][i][t]) ==1 where j in N \ {i} for each i in N and for each t in T
sum(x[i][j][t] + x[j][i][t]) ==2 where t in T for each i,j in N, i < j
programmer Michael Gibbs
"""
import pulp
N = [1,2]
T = [1,2]
model = pulp.LpProblem("basis")
# variables
# x[i][j][t]
x = {
i:{
j:{
t:pulp.LpVariable(
'x_' + str(i) + '_' + str(j) + '_' + str(t),
cat=pulp.LpBinary
)
for t in T
}
for j in N if j != i
}
for i in N
}
# constraints
#sum(x[i][j][t] + x[j][i][t]) ==1 where j in N \ {i} for each i in N and for each t in T
for i in N:
for t in T:
c = pulp.lpSum([x[i][j][t] + x[j][i][t] for j in N if j != i]) == 1
model += c
#sum(x[i][j][t] + x[j][i][t]) ==2 where t in T for each i,j in N, i < j
for i in N:
for j in N:
if i < j:
c = pulp.lpSum([x[i][j][t] + x[j][i][t] for t in T]) == 2
model += c
# no objective
model.solve()
print("i","j","t","value")
print('-------------------')
[print(i,j,t, pulp.value(x[i][j][t])) for i in N for j in N if i != j for t in T]

DOcplexException: Expression xx cannot be used as divider of xxx

I am new to CPLEX and I was trying to find an example where the decision variable is in the denominator of the objective function but couldn't. My optimisation problem;
I have tried the following on Python3;
from docplex.mp.model import Model
import numpy as np
N = 1000
S = 10
k = 2
u_i = np.random.rand(N)[:,np.newaxis]
u_ij = np.random.rand(N*S).reshape(N, S)
beta = np.random.rand(N)[:,np.newaxis]
m = Model(name = 'model')
R = range(1, S+1)
idx = [(j) for j in R]
I = m.binary_var_dict(idx)
m.add_constraint(m.sum(I[j] for j in R)<= k)
total_rev = m.sum(beta[i,0] / ( 1 + u_i[i,0]/sum(I[j] * u_ij[j,i-1] for j in R) ) for i in range(N) )
m.maximize(total_rev)
sol = m.solve()
sol.display()
However Im getting the following error when running the line;
total_rev = m.sum(beta[i,0] / ( 1 + u_i[i,0]/sum(I[j] * u_ij[j,i-1] for j in R) ) for i in range(N) )
Error :
DOcplexException: Expression 0.564x1+0.057x2+0.342x3+0.835x4+0.452x5+0.802x6+0.324x7+0.763x8+0.264x9+0.226x10 cannot be used as divider of 0.17966220449798675
Can you please help me to overcome this error?
Since your objective is not linear you should use CPO within CPLEX
from docplex.cp.model import CpoModel
import numpy as np
N = 10
S = 10
k = 2
u_i = np.random.rand(N)[:,np.newaxis]
u_ij = np.random.rand(N*S).reshape(N, S)
beta = np.random.rand(N)[:,np.newaxis]
m = CpoModel(name = 'model')
R = range(1, S)
idx = [(j) for j in R]
I = m.binary_var_dict(idx)
m.add_constraint(m.sum(I[j] for j in R)<= k)
total_rev = m.sum(beta[i,0] / ( 1 + u_i[i,0]/sum(I[j] * u_ij[j,i-1] for j in R) ) for i in range(N) )
m.maximize(total_rev)
sol=m.solve()
for i in R:
print(sol[I[i]])
works fine

Simpson's rule 3/8 for n intervals in Python

im trying to write a program that gives the integral approximation of e(x^2) between 0 and 1 based on this integral formula:
Formula
i've done this code so far but it keeps giving the wrong answer (Other methods gives 1.46 as an answer, this one gives 1.006).
I think that maybe there is a problem with the two for cycles that does the Riemman sum, or that there is a problem in the way i've wrote the formula. I also tried to re-write the formula in other ways but i had no success
Any kind of help is appreciated.
import math
import numpy as np
def f(x):
y = np.exp(x**2)
return y
a = float(input("¿Cual es el limite inferior? \n"))
b = float(input("¿Cual es el limite superior? \n"))
n = int(input("¿Cual es el numero de intervalos? "))
x = np.zeros([n+1])
y = np.zeros([n])
z = np.zeros([n])
h = (b-a)/n
print (h)
x[0] = a
x[n] = b
suma1 = 0
suma2 = 0
for i in np.arange(1,n):
x[i] = x[i-1] + h
suma1 = suma1 + f(x[i])
alfa = (x[i]-x[i-1])/3
for i in np.arange(0,n):
y[i] = (x[i-1]+ alfa)
suma2 = suma2 + f(y[i])
z[i] = y[i] + alfa
int3 = ((b-a)/(8*n)) * (f(x[0])+f(x[n]) + (3*(suma2+f(z[i]))) + (2*(suma1)))
print (int3)
I'm not a math major but I remember helping a friend with this rule for something about waterplane area for ships.
Here's an implementation based on Wikipedia's description of the Simpson's 3/8 rule:
# The input parameters
a, b, n = 0, 1, 10
# Divide the interval into 3*n sub-intervals
# and hence 3*n+1 endpoints
x = np.linspace(a,b,3*n+1)
y = f(x)
# The weight for each points
w = [1,3,3,1]
result = 0
for i in range(0, 3*n, 3):
# Calculate the area, 4 points at a time
result += (x[i+3] - x[i]) / 8 * (y[i:i+4] * w).sum()
# result = 1.4626525814387632
You can do it using numpy.vectorize (Based on this wikipedia post):
a, b, n = 0, 1, 10**6
h = (b-a) / n
x = np.linspace(0,n,n+1)*h + a
fv = np.vectorize(f)
(
3*h/8 * (
f(x[0]) +
3 * fv(x[np.mod(np.arange(len(x)), 3) != 0]).sum() + #skip every 3rd index
2 * fv(x[::3]).sum() + #get every 3rd index
f(x[-1])
)
)
#Output: 1.462654874404461
If you use numpy's built-in functions (which I think is always possible), performance will improve considerably:
a, b, n = 0, 1, 10**6
x = np.exp(np.square(np.linspace(0,n,n+1)*h + a))
(
3*h/8 * (
x[0] +
3 * x[np.mod(np.arange(len(x)), 3) != 0].sum()+
2 * x[::3].sum() +
x[-1]
)
)
#Output: 1.462654874404461

Vandermonde python3 matrix

I wrote a code to compute the vandermonde matrix but I can't get it to print in matrix form. Would really appreciate the help. my code is attached below.
x = [0.55,0.60,0.65,0.70,0.75,0.80,0.85,0.90,0.95,1.00]
col = 10
row = 10
matrix = [[0 for x in range(col)]for y in range(row)]
for i in (range(row)):
matrix[i][0] = 1;
for i in (range(row)):
for j in (1,2,3):
matrix[i][j] = matrix[i][j-1] * x[i]
for i in (range(row)):
for j in (range(col)):
print(matrix[i][j], end = "")
A = ("\n")
print(A)

optimize.brute: ValueError: array is too big

I need to optimize a non-convex problem (max likelihood), and when I try quadratic optmiziation algorithms such as bfgs, Nelder-Mead, it fails to find the extremum, I frequently get saddle point, instead.
You can download data from here.
import numpy as np
import csv
from scipy.stats import norm
f=open('data.csv','r')
reader = csv.reader(f)
headers = next(reader)
column={}
for h in headers:
column[h] = []
for row in reader:
for h,v in zip(headers, row):
column[h].append(float(v))
ini=[-0.0002,-0.01,.002,-0.09,-0.04,0.01,-0.02,-.0004]
for i in range(0,len(x[0])):
ini.append(float(x[0][i]))
x_header = list(Coef_headers)
N = 19 # no of observations
I = 4
P =7
Yobs=np.zeros(N)
Yobs[:] = column['size']
X=np.zeros((N,P))
X[:,0] = column['costTon']
X[:,1] = column['com1']
X[:,2] = column['com3']
X[:,3] = column['com4']
X[:,4] = column['com5']
X[:,5] = column['night']
X[:,6] = 1 #constant
def myfunction(B):
beta = B[0.299,18.495,2.181,2.754,3.59,2.866,-12.846]
theta = 30
U=np.zeros((N,I))
mm=np.zeros(I)
u = np.zeros((N,I))
F = np.zeros((N,I))
G = np.zeros(N)
l = 0
s1 = np.expm1(-theta)
for n in range (0,N):
m = 0
U[n,0] = B[0]*column['cost_van'][n]+ B[4]*column['cap_van'][n]
U[n,1] = B[1]+ B[5]*column['ex'][n]+ B[8]*column['dist'][n]+ B[0]*column['cost_t'][n]+ B[4]*column['cap_t'][n]
U[n,2] = B[2]+ B[6]*column['ex'][n]+ B[9]*column['dist'][n] + B[0]*column['cost_Ht'][n]+ B[4]*column['cap_Ht'][n]
U[n,3] = B[3]+ B[7]*column['ex'][n]+ B[10]*column['dist'][n]+ B[0]*column['cost_tr'][n]+ B[4]*column['cap_tr'][n]
for i in range(0,I):
mm[i]=np.exp(U[n,i])
m= sum(mm)
for i in range(0,I):
u[n,i]=1/(1+ np.exp(U[n,i]- np.log(m-np.exp(U[n,i]))))
F[n,i] = np.expm1(-u[n,i]*theta)
CDF = np.zeros(N)
Y = X.dot(beta)
resid = 0
for n in range (0,N):
resid = resid + (np.square(Yobs[n]-Y[n]))
SSR = resid / N
dof = N - P - 1
s2 = resid/dof # MSE, or variance: the mean squarred error of residuals
for n in range(0,N):
CDF[n] = norm.cdf((Yobs[n]+1),SSR,s2) - norm.cdf((Yobs[n]-1),SSR,s2)
G[n] = np.expm1(-CDF[n]*theta)
k = column['Choice_Veh'][n]-1
l = l + (np.log10(1+(F[n,k]*G[n]/s1))/(-theta))
loglikelihood = np.log10(l)
return -loglikelihood
rranges = np.repeat(slice(-10, 10, 1),11, axis = 0)
a = rranges
from scipy import optimize
resbrute = optimize.brute(myfunction, rranges, full_output=True,finish=optimize.fmin)
print("# global minimum:", resbrute[0])
print("function value at global minimum :", resbrute[1])
Now, I decided to go for grid search and tried scipy.optimize.brute, but I get this error. In fact, my real variables are 47, I decreased it to 31 to work, but still doesn't. please help.
File "C:\...\site-packages\numpy\core\numeric.py", line 1906, in indices
res = empty((N,)+dimensions, dtype=dtype)
ValueError: array is too big.

Resources