Reputation: 11
I'm very new to Python and am having some trouble with the minimize part of scipy.optimize. I've set up a simple example to show what I am trying to do. My objective is to determine the lowest purchase quantity of items that also minimizes stock.
Everything that I purchase is split up between two products - 25% goes into Product A, 75% into Product B. One unit of Product A has a unit size of 100, while Product B has a unit size of 300. I also have a minimum purchase quantity of 100, and a maximum purchase quantity of 2000.
The below code is the setup for my objective function.
import math
from scipy.optimize import minimize
unitsize = [100, 300]
proportion = [0.25, 0.75]
minpurchase = 100
maxpurchase = 2000
def stock (purchase):
test = []
for i in xrange(len(unitsize)):
product_purchase = purchase * proportion[i]
units = math.floor(product_purchase / unitsize[i])
y = product_purchase - (units * unitsize[i])
test.append(y)
z = sum(test)
return z
I have tested the stock function and it seems to work as desired. For instance, when I call stock(500), stock(400) and stock(300), it correctly returns 100, 0 and 300 respectively.
Then I tried, to implement the minimization as per below, with constraints based on the minimum and maximum purchase amounts.
However, when I start this with an initial guess of zero, it returns a result of 100, which I consider a wrong result, as it will cause 100 stock and no full units. I am expecting e.g. a result of 400 (where stock is zero). The same problem occurrs when I e.g. start with an initial guess of 100.
cons = ({'type': 'ineq', 'fun': lambda x: x[0] - minpurchase},
{'type': 'ineq', 'fun': lambda x: x[0] + maxpurchase}
)
print minimize(lambda x: stock(x[0]), [0],
method='COBYLA',
constraints = cons,
options={'maxiter':10000})
status: 1
nfev: 106
maxcv: -0.0
success: True
fun: 100.0
x: array([ 100.])
message: 'Optimization terminated successfully.'
When I start with an initial guess of 500, the returned result is correct at 400. However, when I e.g. start with 1900, it returns 1600 as the result as well, as stock is also zero at that point.
Couple of questions:
In trying to work out Question 2, I have considered passing an array of testvalues into the initial guess as below, but it returns "IndexError: too many indices for array".
Any idea what I am doing wrong here?
testvalues = [1000,2000]
for j in range(len(testvalues)):
print minimize(lambda x: stock(x[0]), testvalues[j],
method='COBYLA',
constraints = cons,
options={'maxiter':10000})
[...]
IndexError: too many indices for array
Any help and pointers much appreciated, I have been trying to get this to work all day long.
Upvotes: 1
Views: 2559
Reputation: 11
This error raise because COBYLA method does not handle bounds. Only BFGS, L-BFGS-B, and SLSQP methods do. See: documentation link
Upvotes: 1