I'm still relatively new to python so I'm having trouble figuring out how to accomplish a certain feat.
What I'm trying to do: I have an Excel file with two columns - Sell and margin. There could be a variable number of rows. I need to find a "best fit" where the sum of n# of Sell rows is within 5% of a target sell amount AND where the avg margin is also within 5% of a target margin % (if there is a solution, if not increase the % tolerances and run again. But I can figure that out later).
From my googling, I learned this a multi-constraint knapsack problem and I was able to find some examples to work off of. The code I borrowed is from here: https://towardsdatascience.com/solving-the-multiple-knapsack-problem-with-google-or-tools-e961dfc8288e
My problem: I can't figure out how to set a constraint where the average margin of the items placed in the bag are near the target average margin.
Here's my modified code from the above site where I'm using random data for sell and margin:
from ortools.linear_solver import pywraplp
solver = solver = pywraplp.Solver.CreateSolver('SCIP')
data = {}
sell = [8520,9600,5340,8379,846,1098,1510,4954,1039,620,795,3260,75,200,75]
margin = [25, 25, 25, 34, 25, 25, 25, 25, 25, 25, 27, 20, 100, 27, 100]
assert len(sell) == len(margin)
data['values'] = values
data['sell'] = sell
data['margin'] = margin
data['items'] = list(range(len(sell)))
data['num_items'] = len(sell)
number_bags = 1 #All have the same capacity of 50 pounds
data['target_amount'] = [9262]
data['avg_margin'] = [27]
data['bags'] = list(range(number_bags))
assert len(data['target_amount']) == number_bags
assert len(data['target_amount']) == len(data['avg_margin'])
print('sell:',*data['sell'])
print('margin:',*data['margin'])
print("Number of Items:", data['num_items'])
print("Number of Knapsacks:" , number_bags)
x = {}
for i in data['items']:
for j in data['bags']:
x[(i,j)] = solver.IntVar(0,1,'x_%i_%i' % (i, j))
#Constraint for an item being placed in 1 knapsack
for i in data['items']:
solver.Add(sum(x[i,j] for j in data['bags'])<=1)
#Knapsack Capacity Constraint
for j in data['bags']:
solver.Add(sum(x[(i,j)]*data['sell'][i]
for i in data['items']) <= data['target_amount'][j])
#margin Constraint
#for j in data['bags']:
# solver.Add(sum(x[(i,j)]*data['margin'][i]
# for i in data['items']) <= data['target_amount'][j])
#objective function
objective = solver.Objective()
for i in data['items']:
for j in data['bags']:
objective.SetCoefficient(x[(i,j)], data['sell'][i])
objective.SetMaximization()
solv = solver.Solve()
if solv == pywraplp.Solver.OPTIMAL:
print('Total Packed Value:', objective.Value())
total_Sell = 0
for j in data['bags']:
bag_Sell = 0
avg_margin= 0
count = 0
print('\n','Bag', j+1 , '\n')
for i in data['items']:
if x[i,j].solution_value()>0:
print('Line:', i ,
'Sell', data['sell'][i],
'margin',data['margin'][i],
)
bag_Sell += data['sell'][i]
avg_margin += data['margin'][i]
count += 1
print('Packed Knapsack Sell: ', bag_Sell)
print('Packed Knapsack margin: ', round(avg_margin / count, 2))
else:
print("There is no optimal solution")
Is this even possible? Am I just way out of my league?
Thanks