Sign glitch in `detect_simple_bounds`?
Hi
When using the new detect_simple_bounds, I experienced a glitch when casadi derives simple bounds from constraints. Here is a stylized example that replicates the problem:
opti = casadi.Opti();
x = opti.variable(1,1);
opti.minimize((x+1)^2)
opti.subject_to((-2:-1:-3)*x-(-1:-1:-2)*x >= 0)
opti.solver('ipopt')
sol1 = opti.solve()
opti.solver('ipopt',struct('detect_simple_bounds', true))
sol2 = opti.solve()
sol1.value(opti.x) - sol2.value(opti.x)
In the latter case (sol2), the monotonicity constraint translates to a lower bound, while it should be an upper bound instead. The minus signs in the constraint (i.e., in (-2:-1:-3) and (-1:-1:-2)) seem crucial for reproducibility.
Best, Gregor.
Even simpler example:
import casadi as ca
x = ca.MX.sym("x",1)
p = ca.MX.sym("p",1)
g = -x
print(ca.detect_simple_bounds(x,p,g,ca.MX([-2]),ca.MX([-2])))
g = x
print(ca.detect_simple_bounds(x,p,g,ca.MX([-2]),ca.MX([-2])))
Half assed hacky fix?
x = ca.MX.sym("x",2)
p = ca.MX.sym("p",2)
lbg = ca.MX([-2, -2])
ubg = ca.MX([2, -1])
g = p[0] * x + p[1]
[gi,lbx,ubx,lam_f,lam_b] = ca.detect_simple_bounds(x,p,g,lbg,ubg)
dx = 1.
simple_bounds_idx = list(set(range(g.numel())) - set(gi))
f_g = ca.Function('x',[x,p], [g[simple_bounds_idx]],)
f_lbg = ca.Function('x',[x,p], [lbg[simple_bounds_idx]],)
f_ubg = ca.Function('x',[x,p], [ubg[simple_bounds_idx]],)
constant = f_g(0,p)
coeff = (f_g(dx,p) - constant)/dx
lbg = f_lbg(0,p)
ubg = f_ubg(0,p)
lbx_f = ca.Function('lbx',[p],[ca.if_else(coeff >= 0, (lbg - constant)/coeff,(ubg - constant)/coeff)])
ubx_f = ca.Function('ubx',[p],[ca.if_else(coeff >= 0, (ubg - constant)/coeff,(lbg - constant)/coeff)])
p0 = [-1,2]
print(lbx_f(p0))
print(ubx_f(p0))
p0 = [1,2]
print(lbx_f(p0))
print(ubx_f(p0))
I am commenting to express support for prioritizing this issue. I’d like to build on the great detect_simple_bounds feature, but this bug is limiting.
Fix pending push