2020-03-06 02:24:32 +01:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
2020-04-26 00:11:39 +02:00
|
|
|
#include <string.h>
|
2020-03-06 02:24:32 +01:00
|
|
|
#include <gsl/gsl_randist.h>
|
2020-03-24 02:41:45 +01:00
|
|
|
#include <gsl/gsl_statistics_double.h>
|
2020-03-24 02:17:39 +01:00
|
|
|
|
|
|
|
#include "landau.h"
|
2020-06-08 18:03:04 +02:00
|
|
|
#include "moyal.h"
|
2020-03-24 02:17:39 +01:00
|
|
|
#include "tests.h"
|
2020-04-03 03:16:47 +02:00
|
|
|
#include "bootstrap.h"
|
2020-03-06 02:24:32 +01:00
|
|
|
|
|
|
|
|
2020-04-08 15:43:16 +02:00
|
|
|
/* Here we generate random numbers following
|
2020-06-08 18:03:04 +02:00
|
|
|
* the Landau or the Moyal distribution and run a
|
|
|
|
* series of test to check if they seem to belong
|
|
|
|
* to the Landau distribution.
|
2020-03-06 02:24:32 +01:00
|
|
|
*/
|
|
|
|
int main(int argc, char** argv) {
|
2020-04-26 00:11:39 +02:00
|
|
|
size_t samples = 50000;
|
2020-06-08 18:03:04 +02:00
|
|
|
char* distr = "lan";
|
2020-06-09 13:46:51 +02:00
|
|
|
double m_params[2] = {-0.22278298, 1.1191486};
|
2020-04-26 00:11:39 +02:00
|
|
|
|
|
|
|
/* Process CLI arguments */
|
2020-06-09 13:46:51 +02:00
|
|
|
for (size_t i = 1; i < (size_t)argc; i++) {
|
2020-06-08 18:03:04 +02:00
|
|
|
if (!strcmp(argv[i], "-n")) samples = atol(argv[++i]);
|
|
|
|
else if (!strcmp(argv[i], "-m")) distr = argv[++i];
|
2020-04-26 00:11:39 +02:00
|
|
|
else {
|
2020-06-08 18:03:04 +02:00
|
|
|
fprintf(stderr, "Usage: %s -[hnmp]\n", argv[0]);
|
|
|
|
fprintf(stderr, " -h\t\tShow this message.\n");
|
|
|
|
fprintf(stderr, " -n N\t\tThe size of sample to generate. (default: 50000)\n");
|
|
|
|
fprintf(stderr, " -m MODE\tUse Landau 'lan' or Moyal 'moy' distribution. "
|
|
|
|
"(default: 'lan')\n");
|
2020-04-26 00:11:39 +02:00
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-06 02:24:32 +01:00
|
|
|
// initialize an RNG
|
|
|
|
gsl_rng_env_setup();
|
|
|
|
gsl_rng *r = gsl_rng_alloc(gsl_rng_default);
|
|
|
|
|
2020-06-08 18:03:04 +02:00
|
|
|
// prepare data storage
|
2020-03-06 02:24:32 +01:00
|
|
|
double* sample = calloc(samples, sizeof(double));
|
2020-04-08 12:33:11 +02:00
|
|
|
double min = -10;
|
|
|
|
double max = 10;
|
2020-03-06 02:24:32 +01:00
|
|
|
|
2020-03-24 02:17:39 +01:00
|
|
|
|
|
|
|
/* Sample generation
|
2020-03-06 02:24:32 +01:00
|
|
|
*/
|
2020-03-24 02:17:39 +01:00
|
|
|
fprintf(stderr, "# Sampling\n");
|
|
|
|
fprintf(stderr, "generating %ld points... ", samples);
|
2020-06-09 13:46:51 +02:00
|
|
|
|
|
|
|
/* Sample points from the Landau distribution
|
|
|
|
* using the GSL Landau generator or from the
|
|
|
|
* Moyal distribution using inverse sampling.
|
2020-06-08 18:03:04 +02:00
|
|
|
*/
|
|
|
|
for(size_t i=0; i < samples; i++){
|
2020-06-09 13:46:51 +02:00
|
|
|
if (!strcmp(distr, "lan"))
|
|
|
|
sample[i] = gsl_ran_landau(r);
|
|
|
|
if (!strcmp(distr, "moy"))
|
|
|
|
sample[i] = moyal_qdf(gsl_rng_uniform(r), m_params);
|
2020-03-06 02:24:32 +01:00
|
|
|
}
|
2020-03-24 02:17:39 +01:00
|
|
|
fprintf(stderr, "done\n");
|
2020-03-06 02:24:32 +01:00
|
|
|
|
2020-06-09 13:46:51 +02:00
|
|
|
// sort the sample: needed for HSM and KS tests
|
2020-03-06 02:24:32 +01:00
|
|
|
qsort(sample, samples, sizeof(double), &cmp_double);
|
|
|
|
|
2020-03-24 02:17:39 +01:00
|
|
|
|
|
|
|
/* Kolmogorov-Smirnov test
|
|
|
|
*
|
|
|
|
* Compute the D statistic and its
|
|
|
|
* associated probability.
|
|
|
|
*/
|
2020-04-08 15:43:16 +02:00
|
|
|
fprintf(stderr, "\n\n# Kolmogorov-Smirnov test\n");
|
2020-03-06 02:24:32 +01:00
|
|
|
double D = 0;
|
|
|
|
double d;
|
2020-06-08 18:03:04 +02:00
|
|
|
for(size_t i = 0; i < samples; i++) {
|
2020-03-06 02:24:32 +01:00
|
|
|
d = fabs(landau_cdf(sample[i], NULL) - ((double)i+1)/samples);
|
|
|
|
if (d > D)
|
|
|
|
D = d;
|
|
|
|
}
|
|
|
|
double beta = kolmogorov_cdf(D, samples);
|
2020-03-24 02:17:39 +01:00
|
|
|
|
|
|
|
// print the results
|
|
|
|
fprintf(stderr, "\n## Results\n");
|
2020-04-08 12:43:14 +02:00
|
|
|
fprintf(stderr, "D=%g\n", D);
|
|
|
|
fprintf(stderr, "p=%.3f\n", 1 - beta);
|
2020-03-06 02:24:32 +01:00
|
|
|
|
2020-03-24 02:17:39 +01:00
|
|
|
|
|
|
|
/* Mode comparison
|
|
|
|
*
|
2020-04-06 20:43:00 +02:00
|
|
|
* Compute the half-sample mode by bootstrapping
|
|
|
|
* and compare the result with the value found by
|
|
|
|
* numerical maximisation of the PDF.
|
2020-03-24 02:17:39 +01:00
|
|
|
*/
|
|
|
|
fprintf(stderr, "\n\n# Mode comparison\n");
|
2020-03-06 02:24:32 +01:00
|
|
|
|
2020-04-06 16:57:00 +02:00
|
|
|
/* A structure used by the optimisation
|
|
|
|
* routines in numeric_mode and others
|
|
|
|
* functions below.
|
|
|
|
*/
|
|
|
|
gsl_function pdf;
|
|
|
|
pdf.function = &landau_pdf;
|
|
|
|
pdf.params = NULL;
|
|
|
|
|
2020-05-07 23:18:59 +02:00
|
|
|
// number of bootstrap samples
|
2020-04-08 15:43:57 +02:00
|
|
|
const size_t boots = 100;
|
|
|
|
|
2020-04-08 12:33:11 +02:00
|
|
|
double mode_e = numeric_mode(min, max, &pdf, 1);
|
2020-04-08 15:43:57 +02:00
|
|
|
uncert mode_o = bootstrap_mode(r, sample, samples, boots);
|
2020-04-06 16:57:00 +02:00
|
|
|
|
|
|
|
// print the results
|
2020-03-24 02:17:39 +01:00
|
|
|
fprintf(stderr, "\n## Results\n");
|
2020-04-11 19:29:38 +02:00
|
|
|
fprintf(stderr, "expected mode: %.8f\n", mode_e);
|
2020-04-06 10:32:26 +02:00
|
|
|
fprintf(stderr, "observed mode: %.4f±%.4f\n", mode_o.n, mode_o.s);
|
|
|
|
|
2020-04-08 12:33:11 +02:00
|
|
|
// t-test
|
2020-04-06 10:32:26 +02:00
|
|
|
double t = fabs(mode_e - mode_o.n)/mode_o.s;
|
|
|
|
double p = 1 - erf(t/sqrt(2));
|
|
|
|
fprintf(stderr, "\n## t-test\n");
|
|
|
|
fprintf(stderr, "t=%.3f\n", t);
|
|
|
|
fprintf(stderr, "p=%.3f\n", p);
|
2020-03-06 02:24:32 +01:00
|
|
|
|
2020-03-24 02:17:39 +01:00
|
|
|
|
|
|
|
/* FWHM comparison
|
|
|
|
*
|
2020-04-06 20:43:00 +02:00
|
|
|
* Estimate the FWHM of the sample by constructing
|
|
|
|
* an empirical PDF via a KDE method and applying
|
|
|
|
* the definition on it (numerical solution of
|
|
|
|
* `f(x) = max/2` ⇒ x₁-x₀). This is again bootstrapped
|
|
|
|
* to estimate the standard errors and compared against
|
|
|
|
* the numerical value of FWHM from the true PDF.
|
2020-03-24 02:17:39 +01:00
|
|
|
*/
|
2020-04-06 20:43:00 +02:00
|
|
|
fprintf(stderr, "\n\n# FWHM comparison\n");
|
|
|
|
|
2020-04-08 12:33:11 +02:00
|
|
|
double fwhm_e = numeric_fwhm(min, max, &pdf, 1);
|
2020-04-08 15:43:57 +02:00
|
|
|
uncert fwhm_o = bootstrap_fwhm(r, min, max, sample, samples, boots);
|
2020-04-06 20:43:00 +02:00
|
|
|
|
|
|
|
// print the results
|
|
|
|
fprintf(stderr, "\n## Results\n");
|
|
|
|
fprintf(stderr, "expected fwhm: %.7f\n", fwhm_e);
|
2020-04-08 12:33:11 +02:00
|
|
|
fprintf(stderr, "observed fwhm: %.4f±%.4f\n", fwhm_o.n, fwhm_o.s);
|
2020-04-06 20:43:00 +02:00
|
|
|
|
2020-04-08 12:33:11 +02:00
|
|
|
// t-test
|
|
|
|
t = fabs(fwhm_e - fwhm_o.n)/fwhm_o.s;
|
|
|
|
p = 1 - erf(t/sqrt(2));
|
2020-04-06 20:43:00 +02:00
|
|
|
fprintf(stderr, "\n## t-test\n");
|
|
|
|
fprintf(stderr, "t=%.3f\n", t);
|
|
|
|
fprintf(stderr, "p=%.3f\n", p);
|
2020-03-06 02:24:32 +01:00
|
|
|
|
|
|
|
|
2020-03-24 02:41:45 +01:00
|
|
|
/* Median comparison
|
|
|
|
*
|
2020-04-03 03:16:47 +02:00
|
|
|
* Compute the median of the sample by bootstrapping
|
|
|
|
* it and comparing it with the QDF(1/2).
|
2020-03-24 02:41:45 +01:00
|
|
|
*/
|
|
|
|
fprintf(stderr, "\n\n# Median comparison\n");
|
|
|
|
double med_e = landau_qdf(0.5);
|
2020-04-08 15:43:57 +02:00
|
|
|
uncert med_o = bootstrap_median(r, sample, samples, boots);
|
2020-03-24 02:41:45 +01:00
|
|
|
|
|
|
|
// print the results
|
2020-04-01 01:34:57 +02:00
|
|
|
fprintf(stderr, "\n## Results\n");
|
2020-03-24 02:41:45 +01:00
|
|
|
fprintf(stderr, "expected median: %.7f\n", med_e);
|
2020-04-03 03:16:47 +02:00
|
|
|
fprintf(stderr, "observed median: %.4f±%.4f\n", med_o.n, med_o.s);
|
|
|
|
|
2020-04-08 12:33:11 +02:00
|
|
|
// t-test
|
2020-04-06 10:32:26 +02:00
|
|
|
t = fabs(med_e - med_o.n)/med_o.s;
|
|
|
|
p = 1 - erf(t/sqrt(2));
|
2020-04-03 03:16:47 +02:00
|
|
|
fprintf(stderr, "\n## t-test\n");
|
|
|
|
fprintf(stderr, "t=%.3f\n", t);
|
|
|
|
fprintf(stderr, "p=%.3f\n", p);
|
|
|
|
|
2020-03-06 02:24:32 +01:00
|
|
|
|
2020-06-09 13:46:51 +02:00
|
|
|
/* Infinite moments test
|
|
|
|
*
|
|
|
|
* Apply the Trapani test for infinite moment
|
|
|
|
* to the mean and variance.
|
|
|
|
*
|
|
|
|
* Use r=n^0.75 points in both cases and rescale
|
|
|
|
* the variance by the ψ=2 moment. The mean is not
|
|
|
|
* rescaled.
|
|
|
|
*/
|
|
|
|
fprintf(stderr, "\n\n# Infinite moments test\n");
|
|
|
|
double p_mean = trapani(r, 0.75, 0, 1, sample, samples);
|
|
|
|
double p_var = trapani(r, 0.75, 1, 2, sample, samples);
|
|
|
|
|
|
|
|
// print the results
|
|
|
|
fprintf(stderr, "\n## Results\n");
|
|
|
|
fprintf(stderr, "mean: p=%.3f\n", p_mean);
|
|
|
|
fprintf(stderr, "variance: p=%.3f\n", p_var);
|
|
|
|
|
2020-03-06 02:24:32 +01:00
|
|
|
// clean up and exit
|
|
|
|
gsl_rng_free(r);
|
|
|
|
free(sample);
|
|
|
|
return EXIT_SUCCESS;
|
|
|
|
}
|