Meng
Meng

Reputation: 1188

scipy.optimize compact constraints

I have a np.array A of length 9 and it is the variable in the objective function.

A =  [ a1, a2, a3,
       b1, b2, b3,
       c1, c2, c3], where a1...c3 are real numbers.
with constraints: a1 > a2, a2 > a3,
                  b1 > b2, b2 > b3,
                  c1 > c2, c2 > c3

Is there any easy way to write the constraints? currently I have the following code, but as the array size gets larger, it is difficult to write them all.

cons = (
        {'type':'ineq',
         'fun': lambda x : np.array([x[0]-x[1]])
        }
    ,
        {'type':'ineq',
         'fun': lambda x : np.array([x[1]-x[2]])
        }
    ,
        {'type':'ineq',
         'fun': lambda x : np.array([x[3]-x[4]])
        }    
    ,
        {'type':'ineq',
         'fun': lambda x : np.array([x[4]-x[5]])
        }   
    ,
        {'type':'ineq',
         'fun': lambda x : np.array([x[6]-x[7]])
        }    
    ,
        {'type':'ineq',
         'fun': lambda x : np.array([x[7]-x[8]])
        }    
   )

Upvotes: 2

Views: 313

Answers (2)

Stelios
Stelios

Reputation: 5521

Apparently, your constraint is that each column of A should be (element-wise) greater than or equal to the column to its right.

You can formulate a single, vector-outpur constraint as follows:

def cons_fun(x):
    A = x.reshape(3,3) # change "(3,3)" according to the dimensions of A

    return np.array([A[:,i]-A[:,i+1] for i in range(3-1)]).ravel() # change "3" accordingly

cons = ({'type':'ineq',
         'fun' : cons_fun},)

From my experience with SLSQP, vector-output constraints result in a faster optimization time than providing multiple scalar-output constraints.

Upvotes: 1

Aaron
Aaron

Reputation: 11075

I would imagine scipy likes a numeric output from each of these functions rather than boolean, so that rules out more than two inputs per function... (degrees of freedom and all that isht) what you can do is write a list comprehension to make the functions for you...

cons = ({'type':'ineq', 'fun': lambda x: x[i] - x[i+1]} for i in range(len(A)-1))

I'm not sure why you would need to cast the result of subtraction to a 1-length array, so I left it out.. it's easy to put back in

Upvotes: 0

Related Questions