math
math

Reputation: 2022

failing scipy.minimize for multiple constraints

I would like to minimize the following function using scipy.minimize

def lower_bound(x, mu, r, sigma):
    mu_h = mu_hat(x, mu, r)
    sigma_h = sigma_hat(x, sigma)
    gauss = np.polynomial.hermite.hermgauss(10)
    return (1 + mu_h + math.sqrt(2) * sigma_h * min(gauss[1]))

all the involved function are tested and return values as expected. Now for setting up the minimization process, I defined

cons = ({"type": "ineq",
             "fun": mu_hat,
             "args": (mu, r)},
            {"type": "ineq",
             "fun": lambda x, sigma: -1.0*sigma_hat(x, sigma),
             "args": (sigma)},
            {"type": "ineq",
             "fun": lambda x: x},
            {"type": "ineq",
             "fun": lambda x: 1-np.dot(np.ones(x.size), x)})

as the constraints. When I run this code scipy.minimize gives me the following error message for the constraints:

File "/usr/local/lib/python3.5/dist-packages/scipy/optimize/slsqp.py", line 312, in <listcomp>
    mieq = sum(map(len, [atleast_1d(c['fun'](x, *c['args'])) for c in cons['ineq']]))
TypeError: <lambda>() argument after * must be an iterable, not float

what is not correct with the defined constraints?

Upvotes: 0

Views: 1287

Answers (1)

John Zwinck
John Zwinck

Reputation: 249123

The error message says:

mieq = sum(map(len, [atleast_1d(c['fun'](x, *c['args'])) for c in cons['ineq']]))
TypeError: <lambda>() argument after * must be an iterable, not float

So we can infer that c['args'] is of type float, because c['args'] is the only variable with * applied to it. Clearly the lookup of 'args' in c has succeeded, so we know that c is a float where an iterable (list, tuple, etc.) was expected.

If we now look at your constraints, the args passed are (mu, r) in one case and (sigma) in the other. The problem is clear now: (sigma) is equivalent to sigma, and is not a tuple. To make a 1-tuple in Python, you must say (sigma,).

Upvotes: 1

Related Questions