Reputation: 263
I have some guessed input data (X0) which I want to optimize them in multiple functions as described below.
X0 = [A, B, C, D, E, F, G, H, I, J, K] #each element is a float value
Functions:
F1 = A + B + C + D - 200 = 0
F2 = C + D + E - 50 = 0
F3 = C + D + E + F + G - 45 = 0
F4 = E + F + G + H + I + J + K - 67 = 0
F5 = H + I + J + K - 64 = 0
I'm not sure how scipy can optimize the input data in multiple functions. I prepared a script below; I'm not sure if it's responsive.
from scipy.optimize import minimize
x0 = np.array([1. for i in range(11)])
def my_function(A, B, C, D, E, F, G, H, I, J, K):
F1 = A + B + C + D - 200
F2 = C + D + E - 50
F3 = C + D + E + F + G - 45
F4 = E + F + G + H + I + J + K - 67
F5 = H + I + J + K - 64
return F1 + F2 +F3 +F4 + F5
cons = ({'type': 'ineq', 'my_function': lambda A, B, C, D: A + B + C + D - 200},
{'type': 'ineq', 'my_function': lambda C, D, E: C + D + E - 50},
{'type': 'ineq', 'my_function': lambda C, D, E, F, G: C + D + E + F + G - 45},
{'type': 'ineq', 'my_function': lambda E, F, G, H, I, J, K: E + F + G + H + I + J + K - 67},
{'type': 'ineq', 'my_function': lambda H, I, J, K: H + I + J + K - 64})
res = minimize(my_function, x0, method='BFGS', constraints=cons )
Upvotes: 0
Views: 238
Reputation: 263
In the script below I wanted to generate the constraints throughout a loop form (cons2) but the results output from the loop are different from the one that I used a non-loop (cons2) form. I expected to get a same result from both.
from scipy.optimize import minimize
import numpy as np
np.random.seed(15)
x0 = np.random.random(size=[11])
def my_function(X):
A, B, C, D, E, F, G, H, I, J, K = X
F1 = A + B + C + D - 200
F2 = C + D + E - 50
F3 = C + D + E + F + G - 45
F4 = E + F + G + H + I + J + K - 67
F5 = H + I + J + K - 64
return F1 + F2 +F3 +F4 + F5
#the constraints without loop
cons1 = ({'type': 'eq', 'fun': lambda X: X[0] + X[1] + X[2] + X[3] - 200},
{'type': 'eq', 'fun': lambda X: X[2] + X[3] + X[4] - 50},
{'type': 'eq', 'fun': lambda X: X[2] + X[3] + X[4] + X[5] + X[6] - 45},
{'type': 'eq', 'fun': lambda X: X[4] + X[5] + X[6] + X[7] + X[8] + X[9] + X[10] - 67},
{'type': 'eq', 'fun': lambda X: X[7] + X[8] + X[9] + X[10] - 64})
data = [200, 50, 45, 67, 64]
ran = [[0,3], [2,4], [2,6], [4,10], [7,10]]
_tmp= []
#the constraints with loop
for hh in range(5):
_tmp.append({'type': 'eq', 'fun': lambda X: sum([X[i] for i in range(ran[hh][0], ran[hh][1]+1)]) - data[hh]})
cons2 = tuple(_tmp)
#the outputs below must be the same, but it's not.
res1 = minimize(my_function, x0, constraints=cons1)
res2 = minimize(my_function, x0, constraints=cons2)
print res1.x
print res2.x
Upvotes: 0
Reputation: 59274
You are close. Use type eq
(equality) instead of inequality. In addition, your constraints should only receive one argument, which is the array of values, and you just access their positions.
Check the following:
from scipy.optimize import minimize
x0 = np.random.random(size=[11])
def my_function(X):
A, B, C, D, E, F, G, H, I, J, K = X
F1 = A + B + C + D - 200
F2 = C + D + E - 50
F3 = C + D + E + F + G - 45
F4 = E + F + G + H + I + J + K - 67
F5 = H + I + J + K - 64
return F1 + F2 +F3 +F4 + F5
cons = ({'type': 'eq', 'fun': lambda X: X[0] + X[1] + X[2] + X[3] - 200},
{'type': 'eq', 'fun': lambda X: X[2] + X[3] + X[4] - 50},
{'type': 'eq', 'fun': lambda X: X[2] + X[3] + X[4] + X[5] + X[6] - 45},
{'type': 'eq', 'fun': lambda X: X[4] + X[5] + X[6] + X[7] + X[8] + X[9] + X[10] - 67},
{'type': 'eq', 'fun': lambda X: X[7] + X[8] + X[9] + X[10] - 64})
res = minimize(my_function, x0, constraints=cons)
Returns
success: True
x: array([79.27328348, 78.72671652, 21.16500123, 20.83499877, 8. ,
-2.5794818 , -2.4205182 , 15.7738023 , 16.59847106, 15.92703282,
15.70069382])
Upvotes: 2