Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sign glitch in detect_simple_bounds? #3667

Open
gregreich opened this issue Apr 23, 2024 · 1 comment
Open

Sign glitch in detect_simple_bounds? #3667

gregreich opened this issue Apr 23, 2024 · 1 comment

Comments

@gregreich
Copy link

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.

@ernestds
Copy link

ernestds commented May 12, 2024

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))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants