Use of uninitialized variable in bobyqa altmov_()
gddl opened this issue · 4 comments
Under some circumstances the variable ibdsav
is used uninitialized.
altmov_()
in bobyqa.c
997 if (ibdsav < 0) {
998 xnew[-ibdsav] = sl[-ibdsav];
999 }
The following test code shows the situation that causes lots of NANs in altmov_()
and leaves the ibdsav
uninitialized. I have no idea, how the correct result for this input should look like - at least it shouldn't segfault. Tested on 64 Bit Linux architectures, gcc 4.8.2.
nlopt-test.cc
/* LN_BOBYQA test causing use of unitialized variable (64 Bit architecture only).
*/
#include <nlopt.hpp>
#include <vector>
#include <limits>
#include <xmmintrin.h>
#include <cstdio>
double callback(const std::vector<double>& x, std::vector<double>& grad, void* data)
{
return 0.0010540095162719094;
}
int main()
{
_mm_setcsr(_mm_getcsr() | (_MM_FLUSH_ZERO_ON));
std::vector<double> lowerBounds(2, 0.0);
std::vector<double> upperBounds(2, 0.0);
lowerBounds[0] = -3.1415926535897931;
lowerBounds[1] = -2.2250738585072014e-307;
upperBounds[0] = 3.1415926535897931;
upperBounds[1] = 2.4475812443579215e-307;
nlopt::opt opt(nlopt::LN_BOBYQA, 2);
opt.set_lower_bounds(lowerBounds);
opt.set_upper_bounds(upperBounds);
opt.set_min_objective(callback, 0);
opt.set_xtol_rel(1.0e-8);
double minf;
std::vector<double> x(2, 0.0);
x[0] = -0.59243378920273182;
x[1] = -1.9140531208103923e-307;
opt.optimize(x, minf);
return 0;
}
Hmm, digging through the BOBYQA spaghetti code, it seems like if (predsq > presav)
on line 975 should be if (predsq >= presav)
. Can you see if this fixes your problem?
Maybe what is happening here is that BOBYQA doesn't handle the case where the lower and upper bounds are equal. Normally, NLopt checks for this case and eliminates empty dimensions (fixed parameters) before calling BOBYQA. However, because you have set _MM_FLUSH_ZERO_ON
, computations involving upperBounds[1] - lowerBounds[1]
give zero even though upperBounds[1] != lowerBounds[1]
— the latter means that NLopt is passing the dimensions to BOBYQA, but the former means BOBYQA is dividing zero by zero at some point and getting NaNs and other confusion.
Or rather, I think that it may be the default step size that is subnormal in this case.
Should be fixed now, thanks.