Knapsack in PuLP, adding Constraints on Number of Items selected - python

I have some puLP code, which solves my knapsack problem.
prob = LpProblem("Knapsack problem", LpMaximize)
x1 = LpVariable("x1", 0, 12, 'Integer')
x2 = LpVariable("x2", 0, 12, 'Integer')
x3 = LpVariable("x3", 0, 12, 'Integer')
x4 = LpVariable("x4", 0, 12, 'Integer')
x5 = LpVariable("x5", 0, 12, 'Integer')
x6 = LpVariable("x6", 0, 12, 'Integer')
x7 = LpVariable("x7", 0, 12, 'Integer')
x8 = LpVariable("x8", 0, 12, 'Integer')
x9 = LpVariable("x9", 0, 12, 'Integer')
x10 = LpVariable("x10", 0, 12, 'Integer')
x11 = LpVariable("x11", 0, 12, 'Integer')
x12 = LpVariable("x12", 0, 12, 'Integer')
x13 = LpVariable("x13", 0, 12, 'Integer')
x14 = LpVariable("x14", 0, 12, 'Integer')
x15 = LpVariable("x15", 0, 12, 'Integer')
x16 = LpVariable("x16", 0, 12, 'Integer')
x17 = LpVariable("x17", 0, 12, 'Integer')
x18 = LpVariable("x18", 0, 12, 'Integer')
x19 = LpVariable("x19", 0, 12, 'Integer')
x20 = LpVariable("x20", 0, 12, 'Integer')
x21 = LpVariable("x21", 0, 12, 'Integer')
x22 = LpVariable("x22", 0, 12, 'Integer')
x23 = LpVariable("x23", 0, 12, 'Integer')
x24 = LpVariable("x24", 0, 12, 'Integer')
x25 = LpVariable("x25", 0, 12, 'Integer')
prob += 15 * x1 + 18 * x2 + 18 * x3 + 23 * x4 + 18 * x5 + 20 * x6 + 15 * x7 + 16 * x8 + 12 * x9 + 12 * x10 + 25 * x11 + 25 * x12 + 28 * x13 + 35 * x14 + 28 * x15 + 28 * x16 + 25 * x17 + 25 * x18 + 25 * x19 + 28 * x20 + 25 * x21 + 32 * x22 + 32 * x23 + 28 * x24 + 25 * x25, "obj"
prob += 150 * x1 + 180 * x2 + 180 * x3 + 230 * x4 + 180 * x5 + 200 * x6 + 150 * x7 + 160 * x8 + 120 * x9 + 120 * x10 + 250 * x11 + 250 * x12 + 280 * x13 + 350 * x14 + 280 * x15 + 280 * x16 + 250 * x17 + 250 * x18 + 250 * x19 + 280 * x20 + 250 * x21 + 320 * x22 + 320 * x23 + 280 * x24 + 250 * x25 == 6600, "c1"
prob.solve()
print "Status:", LpStatus[prob.status]
for v in prob.variables():
print v.name, "=", v.varValue
print ("objective = %s" % value(prob.objective))
But to this code I need append another restriction: For example, a restriction That the number of non-zero prob.variables must equal (say) 10.
Could anybody help with that?
UPDATE:
For this code I have output:
Status: Optimal
X1 = 1.0
x10 = 0.0
x11 = 0.0
x12 = 0.0
x13 = 0.0
x14 = 0.0
x15 = 0.0
x16 = 0.0
x17 = 0.0
x18 = 0.0
x19 = 0.0
x2 = 0.0
x20 = 0.0
x21 = 0.0
x22 = 0.0
x23 = 0.0
x24 = 0.0
x25 = 0.0
x3 = 0.0
x4 = 11.0
x5 = 0.0
x6 = 10.0
x7 = 0.0
x8 = 12.0
x9 = 0.0
objective = 660.0
The number of prob.variables that have non-zero values equals only 4. But say I need 10, how would I ensure that?

If you want a certain number of non-zero values, you can do that by introducing new 0/1 variables.
Formulation
Introduce 25 new Y variables [y1..y25] which are all binary {0,1}
If X[i] > 0, we want Y[i] to take on the value 1.
You can do by adding the following constraints.
x[i] < y[i] x M (where M is some big number, say 10,000) for 1 in 1..25
Now, to ensure that at least 10 Y values are non-zero, we want at least 10 of them to be 1.
Sum over Y[1]...y[25] >= 10 will ensure that.
In PuLP
The puLP code is untested, but will give you the right idea to proceed.
x=[]
y=[]
for index in range(25):
y[index] = LpVariable("y"+str(index), 0, 1) #binary variables
prob += x[index] <= 10000 * y[index], "If x%s is non-zero, then y%s is forced to be 1",%index, %index
prob += lpSum([y[i] for i in range(25)]) >= 10,"Ensuring at least 10 items are non-zero"
Hope that helps.

I second the provided answer, but also would comment on making better use of PuLP's (and Python's) list comprehensions for shorter code:
from pulp import *
prob = LpProblem("Knapsack problem", LpMaximize)
cost = [15,18,18,23,18,20,15,16,12,12,25,25,28,35,28,28,25,25,25,28,25,32,32,28,25]
x = LpVariable.dicts('x',range(1,26),lowBound=0,upBound=12,cat=pulp.LpInteger)
cap = [150,180,180,230,180,200,150,160,120,120,250,250,280,350,280,280,250,250,250,280,250,320,320,280,250]
prob += pulp.lpSum([cost[ix]*x[ix] for ix in range(1,25)]), "obj"
prob += pulp.lpSum([cap[ix]*x[ix] for ix in range(1,25)]) == 6600, "c1"
prob.solve()
print "Status:", LpStatus[prob.status]
for v in prob.variables():
if v.varValue>0.0001:
print v.name, "=", v.varValue
print ("objective = %s" % value(prob.objective))
I may have mistyped some coefficients in there, but I'm sure you get my point.

correct with new version pulp
for correct errors
# Import PuLP modeler functions
from pulp import *
prob = LpProblem("Knapsack_problem", LpMaximize)
cost = [30,18,18,23,18,20,15,16,12,12,25,25,28,35,28,28,25,25,25,28,25,32,32,28,25]
x = LpVariable.dicts('x',range(1,26),lowBound=0,upBound=12,cat=LpInteger)
cap = [150,180,180,230,180,200,150,160,120,120,250,250,280,350,280,280,250,250,250,280,250,320,320,280,250]
prob += pulp.lpSum([cost[ix]*x[ix] for ix in range(1,25)]), "obj"
prob += pulp.lpSum([cap[ix]*x[ix] for ix in range(1,25)]) == 6600, "c1"
prob.solve()
print ("Status:", LpStatus[prob.status])
for v in prob.variables():
if v.varValue>0.0001:
print (v.name, "=", v.varValue)
print ("objective = %s" % value(prob.objective))

Related

I Keep Having a Syntax Error Message With This Python Code

Having issue with small python script. trying to add 1 to a global variable every 3 iterations. I keep seeing
"for 3 in scalerVal:
^
SyntaxError: cannot assign to literal"
I will appreciate an answer
x1 = 0
x2 = 0
x3 = 0
x4 = 0
x5 = 0
x6 = 0
x7 = 0
x8 = 0
x9 = 0
itVal = 0
scalerVal = 3
# -- STEP 1: --
# (greatest value) = 3 * itVal + itVal
# adder = (greatest value) - (current value) = (differnce in value) + itVal
# scaler = itVal - intVal - itVal
# -- STEP 2: --
# add the adder to all n values
def a1():
global x1
x1 = x1 + 3
global x2
x2 = x2 + 2
global x3
x3 = x3 + 1
global x4
x4 = x4 + 2
global x5
x5 = x5 + 2
global x6
x6 = x6 + 1
global x7
x7 = x7 + 1
global x8
x8 = x8 + 1
global x9
x9 = x9 + 1
global scalerVal
for 3 in scalerVal:
scalerVal + 1
return()
global itVal
if itVal == 0:
#gVal = 3 * itVal + itVal
#adder = gVal - x1 + itVal
#x1 = x1 + adder
itVal = itVal + 1
print(x1, x2, x3, x4, x5, x6, x7, x8, x9, itVal)
return()
else:
gVal = scalerVal * itVal + itVal
adder = gVal - x1 + itVal
x1 = x1 + adder
itVal = itVal + 1
print(x1 , x2, x3, x4, x5, x6, x7, x8, x9, itVal)
return()
return()
def a2():
global x1
x1 = x1 + 2
global x2
x2 = x2 + 3
global x3
x3 = x3 + 2
global x4
x4 = x4 + 2
global x5
x5 = x5 + 2
global x6
x6 = x6 + 2
global x7
x7 = x7 + 1
global x8
x8 = x8 + 1
global x9
x9 = x9 + 1
global itVal
return()
def a3():
global x1
x1 = x1 + 1
global x2
x2 = x2 + 2
global x3
x3 = x3 + 3
global x4
x4 = x4 + 1
global x5
x5 = x5 + 2
global x6
x6 = x6 + 2
global x7
x7 = x7 + 1
global x8
x8 = x8 + 1
global x9
x9 = x9 + 1
global itVal
if itVal == 0:
#gVal = 3 * itVal + itVal
#adder = gVal - x3 + itVal
#x3 = x3 + adder
itVal = itVal + 1
print(x1, x2, x3, x4, x5, x6, x7, x8, x9, itVal)
return()
else:
gVal = 3 * itVal + itVal
adder = gVal - x3 + itVal
x3 = x3 + adder
itVal = itVal + 1
print(x1 , x2, x3, x4, x5, x6, x7, x8, x9, itVal)
return()
return()
def valAdd():
#for _ in range(1000000000):
#a1()
a1()
a2()
a3()
print(x1, x2, x3, x4, x5, x6, x7, x8, x9, itVal)
return()
valAdd()
Having issue with small python script. trying to add 1 to a global variable every 3 iterations. I keep seeing
"for 3 in scalerVal: ^ SyntaxError: cannot assign to literal"
I will appreciate an answer
The problem is that you are using a constant where you should put a variable instead.
More specifically, in the python for loop, it should be something like this:
for x in [scalerVal]
Actually, the first one should be a variable and the second one should be a iterable
3 needs to be a variable name such as X
for x in scalerVal:
x + 1
return()
Also, scalarVal should be a list or array, not a scalar for use with for.
You can just use the value directly.

Why when using Mystic in Python to optimise a non linear constrained optimisation do I receive a 'cannot simply inequalities' error?

I am trying to optimise the problem below using Mystic. I am currently receiving an error that I don't understand and was hoping someone more familiar with the library could help.
def objective(x):
x0,x1,x2,x3,x4,x5,x6,x7,x8 = x
return x0**2 + x4**2 + x8**2
equations = '''
x0 + x1 + x2 - x3 - x6 - 20 == 0.0
x4 + x3 + x5 - x1 - x7 - 150 == 0.0
x8 + x6 + x7 - x2 - x5 + 100 == 0.0
x6 == 0
x7 == 0
x0 >= 10
x4 >= 60
'''
from mystic.symbolic import generate_conditions, generate_penalty
pf = generate_penalty(generate_conditions(equations), k=1e4)
from mystic.symbolic import generate_constraint, generate_solvers, solve
cf = generate_constraint(generate_solvers(solve(equations))
When calculating cf i receive an 'NotImplementedError:cannot simplify inequalities' and wanted to know why this could be?
If anyone knows how i would extend this such that i can create the constraints through a function or in a different manner I would also be keen to know.
Cheers
I'm the mystic author. You should always first try just using solve(equations) and see what happens. It can fail to symbolically solve the equations due to the inequalities. If so, then try to do simplify(equalities) instead. That symbolically simplifies equations so there's only one variable on the LHS for each line. The inequality solver usually can then work in that case. If that fails, you can rewrite the equations so there's only one variable on the LHS.
>>> def objective(x):
... x0,x1,x2,x3,x4,x5,x6,x7,x8 = x
... return x0**2 + x4**2 + x8**2
...
>>> import mystic
>>> equations = '''
... x0 + x1 + x2 - x3 - x6 - 20 == 0.0
... x4 + x3 + x5 - x1 - x7 - 150 == 0.0
... x8 + x6 + x7 - x2 - x5 + 100 == 0.0
... x6 == 0
... x7 == 0
... x0 >= 10
... x4 >= 60
... '''
>>> eqns = mystic.symbolic.simplify(equations)
>>> print(eqns)
x0 == -x1 - x2 + x3 + x6 + 20
x8 == x2 + x5 - x6 - x7 - 100
x4 >= 60
x7 == 0
x6 == 0
x0 >= 10
x4 == x1 - x3 - x5 + x7 + 150
>>> from mystic.symbolic import generate_constraint, generate_solvers
>>> cf = generate_constraint(generate_solvers(eqns))
>>> cf([0,1,2,3,4,5,6,7,8])
[26, 1, 2, 3, 143, 5, 0, 0, -106]
>>>

How solve this MILP problem with Pulp Python module?

I think I'm facing a Milp problem but I'm not sure.
The problem in a simplified form is: There are 3 suppliers of materials (trucks) for 3 cities. The real problem is 30 Suppliers and 100 cities...
Supliers capacity: a:1; b:2; c:3.
Cities Demand: a:2; b:3; c:1
Distances Supplier(Cities):
a(a:2;b:4;c:6)
b(a:4;b:2;c:4)
c(a:6;b:4;c:2)
like this with each Capacity and Demand
Sa1 - Ca2
Sb2 - Cb3
Sc3 - Cc1
The goal its optimize the suply but there is one (devil) condition:
Just one supplier per city.
Whitout the contidion the problem is a simple problem to solve with basic Linear Programming.
With the condition I think that could be solved with Mixed Integer Linear Programming - MILP.
But not figure it out how to solve this with MILP Method and Pulp (python module).
If someone can help me
Thanks!
My first try
from scipy.optimize import linprog
c = [2,4,6,4,2,4,6,4,2]
Ae = [[1,1,1,0,0,0,0,0,0],
[0,0,0,1,1,1,0,0,0],
[0,0,0,0,0,0,1,1,1],
[1,0,0,1,0,0,1,0,0],
[0,1,0,0,1,0,0,1,0],
[0,0,1,0,0,1,0,0,1],
]
be = [1,2,3,2,3,1]
x0_bounds = (0,None)
x1_bounds = (0,None)
x2_bounds = (0,None)
x3_bounds = (0,None)
x4_bounds = (0,None)
x5_bounds = (0,None)
x6_bounds = (0,None)
x7_bounds = (0,None)
x8_bounds = (0,None)
sol = linprog(c, A_eq= Ae, b_eq = be, bounds = ((x0_bounds,x1_bounds,x2_bounds,x3_bounds,x4_bounds,x5_bounds,x6_bounds,x7_bounds,x8_bounds)) )
print(sol)
fun: 18.0
message: 'Optimization terminated successfully.'
nit: 10
slack: array([], dtype=float64)
status: 0
success: True
x: array([1., 0., 0., 0., 2., 0., 1., 1., 1.])
Process finished with exit code 0
I've done!
Videos of Caylie Cincera from youtube help me a lot. Illustration of the problem. Each location could receive at most of one supplier.
https://imgur.com/O2CNa9M
from pulp import *
#Pulp way to start a LP problem
prob = LpProblem("testpulp",LpMinimize)
#The 9 Arcs Origin and destiny
x1 = LpVariable("x1_11",0,None,LpInteger)
x2 = LpVariable("x2_12",0,None,LpInteger)
x3 = LpVariable("x3_13",0,None,LpInteger)
x4 = LpVariable("x4_21",0,None,LpInteger)
x5 = LpVariable("x5_22",0,None,LpInteger)
x6 = LpVariable("x6_23",0,None,LpInteger)
x7 = LpVariable("x7_31",0,None,LpInteger)
x8 = LpVariable("x8_32",0,None,LpInteger)
x9 = LpVariable("x9_33",0,None,LpInteger)
#Auxiliar Variables z y and k
z1 = LpVariable("z1",0,1,LpBinary)
z2 = LpVariable("z2",0,1,LpBinary)
z3 = LpVariable("z3",0,1,LpBinary)
y1 = LpVariable("y1",0,1,LpBinary)
y2 = LpVariable("y2",0,1,LpBinary)
y3 = LpVariable("y3",0,1,LpBinary)
k1 = LpVariable("k1",0,1,LpBinary)
k2 = LpVariable("k2",0,1,LpBinary)
k3 = LpVariable("k3",0,1,LpBinary)
#Objective Function
prob += 2*x1 + 4*x2+ 6*x3 + 4*x4 + 2*x5 + 4*x6 + 6*x7 + 4*x8 + 2*x9, "fobj"
#Constraints
#Supply constraints
prob += x1 + x2 + x3 == 1, "m1"
prob += x4 + x5 + x6 == 2, "m2"
prob += x7 + x8 + x9 == 3, "m3"
#Demand constraints
prob += x1 + x4 + x7 == 2, "d1"
prob += x2 + x5 + x8 == 3, "r2"
prob += x3 + x6 + x9 == 1, "r4"
#Trick to force unique supplier for each location
prob += x1 <= 2*y1, "yx1"
prob += x4 <= 2*y2, "yx2"
prob += x7 <= 2*y3, "yx3"
prob += x2 <= 3*z1, "zx1"
prob += x5 <= 3*z2, "zx2"
prob += x8 <= 3*z3, "zx3"
prob += x3 <= 1*k1, "kx1"
prob += x6 <= 1*k2, "kx2"
prob += x9 <= 1*k3, "kx3"
prob += y1 + y2 + y3 == 1, "yk"
prob += z1 + z2 + z3 == 1, "zk"
prob += k1 + k2 + k3 == 1, "kk"
prob.solve()
for v in prob.variables():
print(v.name, " = ", v.varValue)
print("Total Profit: ",value(prob.objective))
#The "optimal" solution of this problem is the unique solution
#The hard part is to force unique supplier for each location
The output:
k1 = 1.0
k2 = 0.0
k3 = 0.0
x1_11 = 0.0
x2_12 = 0.0
x3_13 = 1.0
x4_21 = 2.0
x5_22 = 0.0
x6_23 = 0.0
x7_31 = 0.0
x8_32 = 3.0
x9_33 = 0.0
y1 = 0.0
y2 = 1.0
y3 = 0.0
z1 = 0.0
z2 = 0.0
z3 = 1.0
Total Profit: 26.0
Process finished with exit code 0

Create a new dataframe with k copies of each row appended to itself

Suppose I have a dataframe with n rows:
Index data1 data2 data3
0 x0 x0 x0
1 x1 x1 x1
2 x2 x2 x2
...
n xn xn xn
How do I create a new dataframe (using pandas) with k copies of each row appended to itself:
Index data1 data2 data3
0 x0 x0 x0
1 x0 x0 x0
...
k-1 x0 x0 x0
k x1 x1 x1
k+1 x1 x1 x1
...
2k-1 x1 x1 x1
2k x2 x2 x2
...
First concat, then sort
The method I'd use is to create a list of duplicate dataframes, concat them together, and then sort_index:
count = 5
new_df = pd.concat([df]*count).sort_index()
Using numpy.repeat and .iloc In here, k=2
df.iloc[np.repeat(np.arange(len(df)), 3)]
Out[256]:
Index data1 data2 data3
0 0 x0 x0 x0
0 0 x0 x0 x0
0 0 x0 x0 x0
1 1 x1 x1 x1
1 1 x1 x1 x1
1 1 x1 x1 x1
2 2 x2 x2 x2
2 2 x2 x2 x2
2 2 x2 x2 x2
Option 1
Use repeat + reindex + reset_index:
df
data1 data2 data3
0 x0 x0 x0
1 x1 x1 x1
2 x2 x2 x2
df.reindex(df.index.repeat(5)).reset_index(drop=1)
data1 data2 data3
0 x0 x0 x0
1 x0 x0 x0
2 x0 x0 x0
3 x0 x0 x0
4 x0 x0 x0
5 x1 x1 x1
6 x1 x1 x1
7 x1 x1 x1
8 x1 x1 x1
9 x1 x1 x1
10 x2 x2 x2
11 x2 x2 x2
12 x2 x2 x2
13 x2 x2 x2
14 x2 x2 x2
Option 2
Similar solution with repeat + pd.DataFrame:
pd.DataFrame(np.repeat(df.values, 5, axis=0), columns=df.columns)
data1 data2 data3
0 x0 x0 x0
1 x0 x0 x0
2 x0 x0 x0
3 x0 x0 x0
4 x0 x0 x0
5 x1 x1 x1
6 x1 x1 x1
7 x1 x1 x1
8 x1 x1 x1
9 x1 x1 x1
10 x2 x2 x2
11 x2 x2 x2
12 x2 x2 x2
13 x2 x2 x2
14 x2 x2 x2
Comparisons
%timeit pd.concat([df] * 100000).sort_index().reset_index(drop=1)
1 loop, best of 3: 14.6 s per loop
%timeit df.iloc[np.repeat(np.arange(len(df)), 100000)].reset_index(drop=1)
10 loops, best of 3: 22.6 ms per loop
%timeit df.reindex(df.index.repeat(100000)).reset_index(drop=1)
10 loops, best of 3: 19.9 ms per loop
%timeit pd.DataFrame(np.repeat(df.values, 100000, axis=0), columns=df.columns)
100 loops, best of 3: 17.1 ms per loop

How do I specify multiple variable constraints using Integer Programming in PuLP?

I am trying to solve the Bin Packing Problem using the Integer Programming Formulation in Python PuLP. The model for the problem is as follows:
I have written the following Python Code using the PuLP library
from pulp import *
#knapsack problem
def knapsolve(bins, binweight, items, weight):
prob = LpProblem('BinPacking', LpMinimize)
y = [LpVariable("y{0}".format(i+1), cat="Binary") for i in range(bins)]
xs = [LpVariable("x{0}{1}".format(i+1, j+1), cat="Binary")
for i in range(items) for j in range(bins)]
#minimize objective
nbins = sum(y)
prob += nbins
print(nbins)
#constraints
prob += nbins >= 1
for i in range(items):
con1 = sum(xs[(i * bins) + j] for j in range(bins))
prob += con1 == 1
print(con1)
for k in range(bins):
x = xs[k*bins : (k+1)*bins]
con1 = sum([x1*y for x1, y in zip(x, weight)])
prob += con1 <= binweight[k]
print(con1)
exec('prob')
status = prob.solve()
print(LpStatus[status])
print("Objective value:", value(prob.objective))
print ('\nThe values of the variables : \n')
for v in prob.variables():
print(v.name, "=", v.varValue)
return
def knapsack():
#bins
bins = int(input ('Enter the upper bound on the number of bins:'))
print ('\nEnter {0} bins\' capacities one by one'.format(bins))
binweight = []
for i in range(0, bins):
print('Enter {0} bin capacity'.format(i+1))
binweight.append(int(input()))
for i in range(0, bins):
print('The capacity at {0} is {1}'.format(i, binweight[i]))
#items
items = int(input('Enter the number of items:'))
weight = []
print ('\nEnter {0} items weights one by one'.format(items))
for i in range(0, items):
print('Enter {0} item weight'.format(i+1))
weight.append(int(input()))
for i in range(0, items):
print('The weight at {0} is {1}'.format(i, weight[i]))
knapsolve(bins, binweight, items, weight)
return
knapsack()
Here is a sample run of the code :
Enter the upper bound on the number of bins:3
Enter 3 bins' capacities one by one
Enter 1 bin capacity
6
Enter 2 bin capacity
4
Enter 3 bin capacity
5
The capacity at 0 is 6
The capacity at 1 is 4
The capacity at 2 is 5
Enter the number of items:3
Enter 3 items weights one by one
Enter 1 item weight
5
Enter 2 item weight
1
Enter 3 item weight
2
The weight at 0 is 5
The weight at 1 is 1
The weight at 2 is 2
y1 + y2 + y3
x11 + x12 + x13
x21 + x22 + x23
x31 + x32 + x33
5*x11 + x12 + 2*x13
5*x21 + x22 + 2*x23
5*x31 + x32 + 2*x33
Optimal
Objective value: 1.0
The values of the variables :
x11 = 0.0
x12 = 1.0
x13 = 0.0
x21 = 0.0
x22 = 0.0
x23 = 1.0
x31 = 0.0
x32 = 1.0
x33 = 0.0
y1 = 0.0
y2 = 0.0
y3 = 1.0
The output is not as expected. How do I specify the above constraints properly to get the correct output?
You can check the resulting LP/MIP model by writing it to a file after you build the problem:
...
prob.writeLP("binpacking")
status = prob.solve()
...
Now if you take a look at the binpacking file:
\* BinPacking *\
Minimize
OBJ: y1 + y2 + y3
Subject To
_C1: y1 + y2 + y3 >= 1
_C2: x11 + x12 + x13 = 1
_C3: x21 + x22 + x23 = 1
_C4: x31 + x32 + x33 = 1
_C5: 5 x11 + x12 + 2 x13 <= 6
_C6: 5 x21 + x22 + 2 x23 <= 4
_C7: 5 x31 + x32 + 2 x33 <= 5
Binaries
x11
x12
x13
x21
x22
x23
x31
x32
x33
y1
y2
y3
End
The constraints for bin capacities are not right. They are working as if all the bins are used without assigning 1's to the variables. It's because you are overwriting y value while using item weights.
You need to change those constraints like this:
for k in range(bins):
x = xs[k*bins : (k+1)*bins]
con1 = sum([x1*w for x1, w in zip(x, weight)])
prob += con1 <= binweight[k] * y[k]
print(con1)
Now they will be modeled as follows:
_C5: 5 x11 + x12 + 2 x13 - 6 y1 <= 0
_C6: 5 x21 + x22 + 2 x23 - 4 y2 <= 0
_C7: 5 x31 + x32 + 2 x33 - 5 y3 <= 0
Also, the indices for items constraints are not correct. Instead of x11 + x12 + x13 = 1 it should be x11 + x21 + x31 = 1
You can correct it like this:
for i in range(items):
con1 = sum(xs[(i + j*bins)] for j in range(bins))
prob += con1 == 1
print(con1)
The constraints will be:
_C2: x11 + x21 + x31 = 1
_C3: x12 + x22 + x32 = 1
_C4: x13 + x23 + x33 = 1

Categories

Resources