-
Notifications
You must be signed in to change notification settings - Fork 590
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
RFC: Per-variable relative tolerance criteria for x #183
Conversation
Sorry to bump this, but it's been two months and I would really like to clarify a few things:
|
I'm a bit skeptical about this. My inclination would be something like:
|
Thank you for your reply! I like the fact that your approach manages to preserve existing API and express what I need. I'll try to implement it without disturbing existing |
Sorry to produce so many mistakes in the code I submit here. I modified Couldn't help but notice that |
That seems like a bug. Fixed in #258. |
…e it const-correct
- use the weights when checking relative x stopping criterion - allow setting the weights like it's implemented for xtol_abs - weights default to 1
Thank you for clarifying the intent of What else needs to be done here? |
src/api/options.c
Outdated
@@ -157,10 +163,14 @@ nlopt_opt NLOPT_STDCALL nlopt_copy(const nlopt_opt opt) | |||
nopt->xtol_abs = (double *) malloc(sizeof(double) * (opt->n)); | |||
if (!opt->xtol_abs) | |||
goto oom; | |||
nopt->x_weights = (double *) malloc(sizeof(double) * (opt->n)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd rather have these initialized to NULL unless they are actually used — i.e. in the common case where the weights are equal they are not allocated. But I guess we should do the same thing for xtol_abs
as well, so that could be done in a separate PR.
It will also need an update to the documentation. |
Unallocated (NULL) x_weights behave as if all weigths are set to 1.
TODO: add *_x_weights functions to C++, Fortran, Python interface, document those
src/api/options.c
Outdated
return NLOPT_OUT_OF_MEMORY; | ||
} | ||
} | ||
memcpy(opt->x_weights, x_weights, opt->n * sizeof(double)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should probably check that all of the weights are > 0 or return an INVALID_ARGS
This includes Guile and Python.
src/api/options.c
Outdated
unsigned i; | ||
for (i = 0; i < opt->n; i++) { | ||
if (x_weights[i] <= 0) | ||
return NLOPT_INVALID_ARGS; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return ERR(NLOPT_INVALID_ARGS, opt, "invalid negative weight");
src/api/options.c
Outdated
@@ -654,7 +659,7 @@ nlopt_result NLOPT_STDCALL nlopt_set_x_weights(nlopt_opt opt, const double *x_we | |||
|
|||
nlopt_result NLOPT_STDCALL nlopt_set_x_weights1(nlopt_opt opt, double x_weights) | |||
{ | |||
if (opt) { | |||
if (opt && x_weights > 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better to have
if (x_weights < 0) return ERR(NLOPT_INVALID_ARGS, opt, "invalid negative weight");
so that there is an informative error message.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we make x_weights == 0
an error, too? I am assuming we should, since there already is xtol_rel = 0
to disable the stopping criterion.
Looks good, I'll merge once tests are green. Thanks for sticking with this! |
As discussed in stevengj#183, it is benefitical to avoid allocating potentially huge buffers of size `n` unless `x`-tolerance criteria are used.
As discussed in stevengj#183, it is beneficial to avoid allocating potentially huge buffers of size `n` unless `x`-tolerance criteria are used.
As discussed in stevengj#183, it is beneficial to avoid allocating potentially huge buffers of size `n` unless `x`-tolerance criteria are used.
* xtol_rel: L1 norm for whole-vector stopping criterion * vector_norm: fix uninitialized ret, move branch outside for loop, make it const-correct * diff_norm: like vector_norm, but for x-oldx * xtol_abs: test directly when diff_norm tests for weighted xtol_rel * add double * x_weights to nlopt and nlopt_stopping structures - use the weights when checking relative x stopping criterion - allow setting the weights like it's implemented for xtol_abs - weights default to 1 * don't forget to free the weights; actually declare the weight-related functions * provide scale support for vector_norm and diff_norm * add argument checks to nlopt_get_x_weights * do not allocate x_weights unless requested by Unallocated (NULL) x_weights behave as if all weigths are set to 1. * start documenting the new functions TODO: add *_x_weights functions to C++, Fortran, Python interface, document those * fixes, add equations * Update NLopt_Reference.md * param names * check for w < 0 in set_x_weights * add x_weights to C++ interface and document them * add x_weights to F77 interface and document them * add & document x_weights to SWIG-based interfaces This includes Guile and Python. * add and document x_weights to Octave&Matlab * set_x_weights: ISO C90 compatibility * set_x_weights: provide informative error on w <= 0 * tweaks
* do not allocate xtol_abs unless needed As discussed in #183, it is beneficial to avoid allocating potentially huge buffers of size `n` unless `x`-tolerance criteria are used. * bobyqa: handle xtol_abs == NULL * cdirect: handle xtol_abs == NULL * cdirect/hybrid: handle xtol_abs == NULL * cobyla: handle xtol_abs == NULL * sbplx: handle xtol_abs == NULL * newuoa: handle xtol_abs == NULL * praxis: handle xtol_abs == NULL * optimize.c: handle xtol_abs == NULL
Dear Steven,
Thank you for your excellent library; my specialist's thesis would be much sadder without it.
I realized that I needed different relative tolerances for the variables I was optimizing (I wanted to be sure about plasma temperature and electron density, but had much less confidence in element concentrations), so I went on and implemented that.
Why you wouldn't want to merge this right away:
set_xtol_abs
andset_xtol_abs1
vsset_xtol_relv
andset_xtol_rel
), some of them may return what can be considered lies (what shoulddouble get_xtol_rel()
return when xtol_rel is a vector?), but the old behaviour is fully preserved (i.e. code using onlyset_xtol_rel(double)
wouldn't notice any difference).stop->xtol_rel
being a vector. Some of the changes are nastyFIXME
s which still work when allxtol_rel
elements are same but may cause suboptimal behaviour otherwise. I would need some help to decide, for example, whether it's appropriate to allocate memory for temporary copy ofxtol_rel
to multiply it by10
.If you are interested, can we try to work out the rest of the changes I need to implement for this to be mergeable?