Berk
Berk

Reputation: 263

Optimization of Data

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

Answers (2)

Berk
Berk

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

rafaelc
rafaelc

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

Related Questions