Sure, attached is the simplest program I can get to demonstrate the nan
result (on my computer - perhaps this is hardware-dependent). It took me a
little while to come up with it, as the bug seems somewhat difficult to
trigger. Hopefully this helps.
:) David
On Sat, Mar 21, 2015 at 11:17 PM, Patrick Alken <[email protected]>
wrote:
> Thanks for the report David. Do you have a simple program which
> demonstrates the bug?
>
> Patrick
>
> On 03/21/2015 01:59 AM, David Zaslavsky wrote:
> > I'm fairly sure I've identified a small bug in the VEGAS implementation:
> in
> > lines 280-283 of vegas.c on the master branch,
> >
> > if (var > 0) { wgt = 1.0 / var; }
> >
> > very small but nonzero values of var (like 1e-322) will cause wgt to be
> set
> > to inf, and that in turn causes gsl_monte_vegas_integrate to return nan.
> > The logical fix seems to be to treat any value of var satisfying
> > 1.0/var==inf as zero, i.e.
> >
> > - if (var > 0)
> > + if (var > 0 && gsl_finite(1.0 / var))
> >
> > I don't know if that would break anything else, but I can't imagine how.
> > Thoughts?
> >
> > I can send a proper patch file if desired (it's on my other computer).
> >
> > :) David
> >
>
>
>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include "gsl/gsl_math.h"
#include "gsl/gsl_monte.h"
#include "gsl/gsl_monte_vegas.h"
#define check_finite(v) assert(gsl_finite(v) && !gsl_isnan(v))
static const double inf = 100;
double hypot_sq(double x, double y) {
return gsl_pow_2(x) + gsl_pow_2(y);
}
double integrand(double* coords, size_t ndims, void* params) {
double k = 0.8;
double k2 = k*k;
double lx = coords[0];
double ly = coords[1];
double lpx = coords[2];
double lpy = coords[3];
double lppx = coords[4];
double lppy = coords[5];
double F1 = exp(-hypot_sq(lppx, lppy));
double F2 = exp(-hypot_sq(k - lpx - lppx, -lpy - lppy));
double F3 = exp(-hypot_sq(k - lx - lppx, -ly - lppy));
double result;
assert(ndims == 6);
result = F1 * F2 * F3;
check_finite(result);
return result;
}
int main(const int argc, const char** argv) {
double res, err;
double min[] = {-inf, -inf, -inf, -inf, -inf, -inf};
double max[] = { inf, inf, inf, inf, inf, inf};
const size_t ndim = 6;
const gsl_rng_type* T;
gsl_rng *r;
T = gsl_rng_default;
r = gsl_rng_alloc(T);
gsl_rng_set(r, 100);
gsl_monte_function function_package;
function_package.f = integrand;
function_package.dim = ndim;
function_package.params = NULL;
gsl_monte_vegas_state *s = gsl_monte_vegas_alloc(ndim);
gsl_monte_vegas_integrate (&function_package, (double*)min, (double*)max, (size_t)ndim, 50000, r, s, &res, &err);
fprintf(stderr, "Expected output to demonstrate bug:\n result = -nan; errbound = 0.000000; chisq/dof = nan\n");
fprintf(stderr, "Actual output:\n result = % .6f; errbound = % .6f; chisq/dof = %.2f\n", res, err, gsl_monte_vegas_chisq(s));
gsl_monte_vegas_free(s);
gsl_rng_free(r);
return 0;
}