-
Notifications
You must be signed in to change notification settings - Fork 200
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
Lbfgsb with box constraints failing #32
Comments
Another remark: In src/test/verify.cpp you have some cases to test the Lbfgsb class, but in all those examples, you didn't set a lower/upper bound. I think one should not allow to use Lbfgsb when hasLowerBound or hasUpperBound is false, since for these cases, the library provides other classes. |
I almost forgot: I find it always very confusing that you have to set the lower/upper bounds on the problem object and not on the Lbfgsb object. This doesn't make much sense to me. If you add the upper/lower bound as mandatory constructor argument to the solver, the remark above would also be resolved. |
Aren't bounds problem specific? |
Hmm, I see your point, but since the bounds are only used in a few solvers and control the behaviour of the minimization it makes more sense to me to move these properties into the solver where needed. However, this is just a small remark. |
Hello, I agree with @hugandr - because not all the solvers have bounds, it makes more sense for the bounds to be set on the solver not the problem. A user might set bounds on a problem and then use an unbound solver! In practice I don't think it is common to re-use solvers for multiple problems (I don't). |
I think this projection is correct: auto noConvergence =
[&](Vector<Dtype> & x, Vector<Dtype> & g)->bool {
return (((x - g).cwiseMax(lboundTemplate).cwiseMin(uboundTemplate) - x).template lpNorm<Eigen::Infinity>() >= 1e-4);
}; This is essentially projecting the deepest descent direction (see eq. 2.2 in the pdf)
See eq. 2.2
Make sense. Ok. |
In the case of simple box constraints, why can't you simply clamp the values of the variables to their respective lower & upper boxes as a default behavior? If the user function is not defined outside the box domain anyway, I imagine the result of a gradient descent or conjugate gradient would still be quite reasonable? The solver class can also issue a warning, or throw an error, if it can really not handle boxed constraints. That way you keep the |
While this seems practical I think this is a bad workaround, since the entire optimization iterations can run along the constraints without hitting the minima. A projection seems to be the better way. But I am open, if this solves the problem. Is there any simple objective, that causes this issue? If I have to guess the error, I think it will be inside the step-size function. |
I can't think of a real example right now. But at the very least, if want to keep the bound definition tied to the |
Okay - how about we provide a BoundedProblem subclass, and move the upper/lower bounds to that. Then solvers that can cope with bounds can provide a minimise() that takes a BoundedProblem. This would remove the need for the hasLowerBounds/hasUpperBounds checks as well. I can work on this but it will take a couple of days. |
Sounds reasonable to me. However, you'll probably need to keep the hasLowerBounds/hasUpperBounds check for partially bounded problem (e.g. with only a lower bound). Or the unset bound could default to +/- infinity, and the solver should recognize that. |
What about implementing a log-barrier method to support box-constraints for solvers that do not support these constraints by default? |
Closing this because of @43. Let me know if there's problems. |
It looks like the L-BFGS-B solver doesn't work properly. I added a simple test case in my fork:
The problem is this check:
I don't really understand what it does, but it looks like it's not correct.
To check if the current value is still inside the box, one could just use something like this: (here with tolerance)
I guess the step/step-size in the algorithm is chosen s.t. the new position is still inside the box, so there must be an error in the algorithm implementation.
The text was updated successfully, but these errors were encountered: