Skip to content

Commit

Permalink
Merge pull request #208 from mdhaber/bind_NOW
Browse files Browse the repository at this point in the history
MAINT: minimize_ipopt: fix late binding bug when defining constraint Jacobians
  • Loading branch information
moorepants authored May 20, 2023
2 parents 619b1d2 + 3b2b273 commit 0157f2f
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 2 deletions.
7 changes: 5 additions & 2 deletions cyipopt/scipy_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,11 @@ def __init__(self,
con_hessian = con.get('hess', None)
con_kwargs = con.get('kwargs', {})
if con_jac is None:
con_jac = lambda x0, *args, **kwargs: approx_fprime(
x0, con_fun, eps, *args, **kwargs)
# beware of late binding!
def con_jac(x, *args, con_fun=con_fun, **kwargs):
def wrapped(x):
return con_fun(x, *args, **kwargs)
return approx_fprime(x, wrapped, eps)
elif con_jac is True:
con_fun = MemoizeJac(con_fun)
con_jac = con_fun.derivative
Expand Down
20 changes: 20 additions & 0 deletions cyipopt/tests/unit/test_scipy_optional.py
Original file line number Diff line number Diff line change
Expand Up @@ -365,3 +365,23 @@ def con_ineq_hess(x, v):
assert res.get("success") is True
expected_res = np.array([0.99999999, 4.74299964, 3.82114998, 1.3794083])
np.testing.assert_allclose(res.get("x"), expected_res)


@pytest.mark.skipif("scipy" not in sys.modules,
reason="Test only valid if Scipy available.")
def test_minimize_late_binding_bug():
# `IpoptProblemWrapper` had a late binding bug when constraint Jacobians
# were defined with `optimize.approx_fprime`. Check that this is resolved.
from scipy.optimize import minimize

fun = lambda x: (x[0] - 1)**2 + (x[1] - 2.5)**2
cons = ({'type': 'ineq', 'fun': lambda x: x[0] - 2 * x[1] + 2},
{'type': 'ineq', 'fun': lambda x: -x[0] - 2 * x[1] + 6},
{'type': 'ineq', 'fun': lambda x: -x[0] + 2 * x[1] + 2})
bnds = ((0, None), (0, None))

res = cyipopt.minimize_ipopt(fun, (2, 0), bounds=bnds, constraints=cons)
ref = minimize(fun, (2, 0), bounds=bnds, constraints=cons)
assert res.success
np.testing.assert_allclose(res.x, ref.x)
np.testing.assert_allclose(res.fun, ref.fun)

0 comments on commit 0157f2f

Please sign in to comment.