1

I am trying to minimize a function with 2 variables x[0],x[1]. A, B, and C are dataframes with dimensions 10x10. 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[i,j]*x[0]*B.iloc[i,j]*x[1]*C.iloc[i,j]

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

cons=[]
def f(a):
    def g(x):
        return A.iloc[i,j]*x[0]*B.iloc[i,j]*x[1]*C.iloc[i,j]
    return g

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

While I am getting the right number of constraints (i.e. len(cons) = 100), 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[i,j]*x[0]*B.iloc[i,j]*x[1]*C.iloc[i,j]

is smaller than zero for many j,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.

  • Your `f(a)` function returns a `g` function that is independent from `a`, but it depends on `A`. Is it a typo? – nonDucor Mar 09 '22 at 09:08
  • Also, could you share the code for the whole optimisation problem? – nonDucor Mar 09 '22 at 09:09
  • It causes problem and the code on the other question you linked is correct, it doesn't use any global variable or anything. Also, your code does not run (`A` and `B` are undefined). Please make sure that your code can be executed without errors. – nonDucor Mar 09 '22 at 09:24

1 Answers1

2

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}) 
joni
  • 6,840
  • 2
  • 13
  • 20