13

My MWE is as follows

def obj(e, p):
    S = f(e) + g(p)
    return S

I would like to minimize this function over only e and pass p as an argument to the function. However, I also would like a constraint that depends on p and e that is of the form p + e < 1

I tried

cons = {'type': 'ineq',
       'fun': lambda e, p: -e -p + 1,
       'args': (p)}

And then, I try to minimize this for the case of p = 0.5

minimize(obj, initial_guess, method = 'SLSQP', args = 0.5, constraints = cons)

but this doesn't work. I get the error name 'p' is not defined in the line where I define cons. How do I pass the argument p to both the objective function and the constraint?


Full code below

from scipy.optimize import minimize
from scipy.stats import entropy
import numpy as np

#Create a probability vector
def p_vector(x):
    v = np.array([x, 1-x])
    return v


#Write the objective function 
def obj(e, p):
    S = -1*entropy(p_vector(p + e), base = 2) 
    return S

##Constraints
cons = {'type': 'ineq',
       'fun': lambda e: -p - e + 1,
       'args': (p,)
       }

initial_guess = 0

result = minimize(obj, initial_guess, method = 'SLSQP', args = (0.5, ), constraints = cons)
print(result)
user1936752
  • 756
  • 1
  • 9
  • 25
  • To pass `args` as tuples use `(p,)` and `(0.5,)`. In some cases it may turn a scalar into a tuple for you, but just be safe I'd do that myself. – hpaulj Feb 09 '19 at 23:20
  • I tried it with 'args': (p,) when defining cons but I still have an error that says name 'p' is not defined in that line. Also, if it wasn't clear p = 0.5 is the case I'm trying to run – user1936752 Feb 09 '19 at 23:28
  • `args=(0.5,)` sets `p` within the calls made to `obj`. But looking at `minimize` docs, it looks like `args` in `cons`, defines what's passed to the lambda. So I'd try `'args': (0.5,)`. I haven't used `cons` much, so am working entirely from the docs, not experience. – hpaulj Feb 10 '19 at 02:16
  • Hmm it now gives me a new error "() takes 1 positional argument but 2 were given". I've attached my full code to the question for clarity – user1936752 Feb 10 '19 at 11:23

1 Answers1

18

Okay, I figured that it's a mix of syntax errors on my part and how arguments should be passed. For those who may have the same question, I will post an answer here.

The objective function is obj(e, p). We only want to minimize e so we create a tuple of the other arguments arguments = (0.5,). That is, a specific value of p=0.5 is set. Next define the constraint function

def prob_bound(e, p):
    return -e - p + 1

Now one writes the constraints dictionary to be

cons = ({'type': 'ineq',
       'fun': prob_bound,
       'args': arguments       
       })

And finally, one calls the minimizer

result = minimize(obj, initial_guess, method = 'SLSQP', args = arguments, constraints = cons)
user1936752
  • 756
  • 1
  • 9
  • 25
  • Hi @user1936752 , I have a problem that has constraints very similar to your constraint. I am trying to write down the constrain in the problem that I have explained here https://stackoverflow.com/q/72835244/2379433 in scipy. do you know how I can implement my constraint? – Shahrooz Pooryousef Jul 12 '22 at 16:30