Kdog
Kdog

Reputation: 513

Scipy Optimize constraints

Can someone please share how to properly set the constraints for Scipy Optimize?

This is for setting the sum to >=100:

 def constraint1(x):
        return (x[0]+x[1]-100)

How would you set it to be =100 or <=100 I just haven't seen these cases in the docs or other examples.

When I try to do the following, I get a syntax error but I've seen it work in other people examples.

def constraint2(x):
    return (x[0]%=0)

This is the full example:

import numpy as np
from scipy.optimize import minimize
profit_0=50
profit_1=25

# initial guesses
n = 2
x0 = np.zeros(n)
x[0]=0
x[1]=0

def objective(x):
    return -1*(x[0]*profit_0 + x[1]*profit_1)

def constraint1(x):
    return (x[0]+x[1]-100)

def constraint2(x):
    return (x[0]%=0)

def constraint3(x):
    return (x[1]%=0)

b = (0,100)
bnds = (b, b)

con1 = {'type': 'ineq', 'fun': constraint1} 
con2 = {'type': 'eq', 'fun': constraint2} 
con3 = {'type': 'eq', 'fun': constraint3} 
cons = ([con1,con2,con3])

solution = minimize(objective,x0,method='SLSQP',bounds=bnds,constraints=cons)#constraints=cons
x=solution.x
print (solution)

Upvotes: 1

Views: 6302

Answers (1)

astoeriko
astoeriko

Reputation: 900

I will explain in more detail @sascha's comment. First, let's look at the difference between inequality and equality constraints. The documentation says:

Equality constraint means that the constraint function result is to be zero whereas inequality means that it is to be non-negative.

So for the constraint that x[0] + x[1] <= 100 you can use an inequality constraint and define the constraint function as follows:

def constraint(x):
    return 100 - x[0] - x[1]

which is non-negative if the condition is met.

For the condition that x[0] + x[1] == 100 you have two possibilities:

  1. You can use two inequality constraints:
def constraint1(x):
  return 100 - x[0] - x[1]
def constraint2(x):
  return x[0] + x[1] - 100
con1 = {'type': 'ineq', 'fun': constraint1}
con2 = {'type': 'ineq', 'fun': constraint2}
  1. You can use an equality constraint:
def constraint(x):
    return x[0] + x[1] - 100
con = {'type': 'eq', 'fun': constraint}

You could also consider using if statements in your constraint function if that seems more intuitive to you:

def constraint(x):
    return 1 if x[0] + x[1] <= 100 else 0
con = {'type': 'ineq', 'fun':constraint}

Concerning your constraint 2 and 3, note that x[0]%=0 is short for x[0] = x[0]%0. That means, it is an assignment. Trying to return an assignment gives you a syntax error. Furthermore, you should be careful: The modulo by zero is not defined. For example 5%0 will give you an error. (Although it seems that for a numpy array x x[0]%0 only gives a warning and return 0.)

Can you explain what you want to achieve with that constraint?

Upvotes: 3

Related Questions