Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Iterating constraints with scipy.minimize

I am trying to minimize a function with 3 variables x[0], x[1] and x[2]. A, B, C, and D are dataframes with dimensions 72×33. The optimization works as intended when I don’t use constraints, however I also care for the constrainted case. For the constrainted case, I want

A.iloc[t,i]+(x[0]*B.iloc[t,i]+x[1]*C.iloc[t,i]+x[2]*D.iloc[t,i])/33

to be equal to or greater than zero for all combinations of t and i. To achieve this, I have defined constraints in the following way:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

cons=[]
def f(a):
    def g(x):
        return A.iloc[t,i]+(x[0]*B.iloc[t,i]+x[1]*C.iloc[t,i]+x[2]*D.iloc[t,i])/33
    return g

for t in range (72):
    for i in range(33):
        cons.append({'type':'ineq', 'fun': f(t)})

While I am getting the right number of constraints (i.e. len(cons) = 72*33 = 2376), the optimization results do not satisfy the constraints that I had in mind, meaning it results in values for x[0], x[1] and x[2] for which

A.iloc[t,i]+(x[0]*B.iloc[t,i]+x[1]*C.iloc[t,i]+x[2]*D.iloc[t,i])/33

is smaller than zero for many t, i. I have ascertained that result.success = True, so the optimization suddenly stopping can be ruled out as a potential problem. While looking for a solution to this problem, I have found this case of someone trying to iterate constraints in scipy aswell, but they only iterated over one range rather than over two and I was not able to modify their solution to work for my case.

Edit:
As per request, I have added the whole optimization problem:

def objective(x):
    list1 = []
    for t in range(72):
        k = sum([(A.iloc[t,i]+(x[0]*B.iloc[t,i]+x[1]*C.iloc[t,i]+x[2]*D.iloc[t,i])/33) for i in range(33)])
        u = ((1+k)**(1-5))/(1-5)
        list1.append(u)
    list2 = [x / (-73) for x in list1]
    return sum(list2)

cons=[]
def f(a):
    def g(x):
        return A.iloc[t,i]+(x[0]*B.iloc[t,i]+x[1]*C.iloc[t,i]+x[2]*D.iloc[t,i])/33
    return g

for t in range (72):
    for i in range(33):
        cons.append({'type':'ineq', 'fun': f(t)})

# For all three x variables, define 1.0 as an initial guess for the optimization algorithm to work with
n = 3
x0 = np.zeros(n)
x0[0] = 1.0
x0[1] = 1.0
x0[2] = 1.0

# Print the function value that is obtained by plugging in the initial guesses
print('Initial Function Value: ' + str(objective(x0)))

solution = minimize(objective,x0,method='SLSQP',constraints=cons)
x = solution.x

# Print the optimized function value
print('Final Function Value: ' + str(objective(x)))

# Print the x for which the function is optimized
print('Solution')
print('x1 = ' + str(x[0]))
print('x2 = ' + str(x[1]))
print('x3 = ' + str(x[2]))

>Solution :

Your function f doesn’t make any sense since the function g doesn’t depend on a. If you really want f to return a new function depending on the indices i and t, f should be a function of the two indices:

cons=[]
def f(t, i):
    def g(x):
        return A.iloc[t,i]+(x[0]*B.iloc[t,i]+x[1]*C.iloc[t,i]+x[2]*D.iloc[t,i])/33
    return g

for t in range (72):
    for i in range(33):
        cons.append({'type':'ineq', 'fun': f(t, i)})

Note also that you could easily define the constraint functions on the fly thanks to lambda expressions:

cons = []
for t in range(72):
    for i in range(33):
        cons.append({'type': 'ineq', 'fun': lambda x, t=t, i=i: A.iloc[t,i]+(x[0]*B.iloc[t,i]+x[1]*C.iloc[t,i]+x[2]*D.iloc[t,i])/33}) 
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading