analistica/ex-3/main.c

159 lines
4.7 KiB
C
Raw Normal View History

2020-03-06 02:24:32 +01:00
#include <stdlib.h>
#include <string.h>
#include "common.h"
#include "likelihood.h"
#include "chisquared.h"
#include <gsl/gsl_rng.h>
#include <gsl/gsl_histogram2d.h>
/* Options for the program */
struct options {
int show_hist; // whether to print the 2D histogram
int only_hist; // whether to skip the minimisations
size_t num_events; // number of generated events
size_t bins_theta; // number of bins for θ
size_t bins_phi; // number of bins for φ
};
int main(int argc, char **argv) {
/* Set default options */
struct options opts;
opts.num_events = 50000;
opts.show_hist = 0;
opts.only_hist = 0;
opts.bins_theta = 30;
opts.bins_phi = 60;
/* Process CLI arguments */
for (size_t i = 1; i < argc; i++) {
if (!strcmp(argv[i], "-i")) opts.show_hist = 1;
2020-04-27 23:33:43 +02:00
else if (!strcmp(argv[i], "-I")) opts.only_hist = 1;
2020-03-06 02:24:32 +01:00
else if (!strcmp(argv[i], "-n")) opts.num_events = atol(argv[++i]);
else if (!strcmp(argv[i], "-t")) opts.bins_theta = atol(argv[++i]);
else if (!strcmp(argv[i], "-p")) opts.bins_phi = atol(argv[++i]);
else {
fprintf(stderr, "Usage: %s -[hiIntp]\n", argv[0]);
fprintf(stderr, "\t-h\tShow this message.\n");
fprintf(stderr, "\t-i\tPrint the histogram to stdout.\n");
fprintf(stderr, "\t-I\tPrint *only* the histogram.\n");
fprintf(stderr, "\t-n N\tThe number of events to generate.\n");
fprintf(stderr, "\t-t N\tThe number of θ bins.\n");
fprintf(stderr, "\t-p N\tThe number of φ bins.\n");
return EXIT_FAILURE;
}
}
/* Initialize an RNG. */
gsl_rng_env_setup();
gsl_rng *r = gsl_rng_alloc(gsl_rng_default);
/* Initialise the sample data structure with
* the number of events and allocate an array
* for the events.
*/
struct sample s = { opts.num_events, NULL };
s.events = calloc(s.size, sizeof(struct event));
/* Prepare a 2D histogram of the sample
* with 30x60 bins.
*/
gsl_histogram2d* hist =
gsl_histogram2d_alloc(opts.bins_theta, opts.bins_phi);
// set the ranges θ∈[0, π] and φ∈[0, 2π]
gsl_histogram2d_set_ranges_uniform(hist, 0,M_PI, 0,2*M_PI);
/* F(θ.φ) parameters we will generate
* a sample with, and later try to recover.
* Note: for this choice max F(θ,φ) 0.179.
*/
gsl_vector *def_par = gsl_vector_alloc(3);
gsl_vector_set(def_par, 0, 0.65); // α
gsl_vector_set(def_par, 1, 0.06); // β
gsl_vector_set(def_par, 2, -0.18); // γ
/* Generate the points (θ, φ) on the unit sphere
* using the inverse transform:
* θ = acos(1 - 2X)
* φ = 2πY
* where X,Y are random uniform variables in [0,1).
* This ensures that θ,φ are uniformly distributed, then we
* proceed to reject the events as follow:
* 1. generate a y [0, max F(θ,φ)] uniformly
* 2. reject the sample if y > F(θ,φ) else save it.
*/
fputs("# event sampling\n\n", stderr);
fprintf(stderr, "generating %ld events...", opts.num_events);
struct event *e;
for (size_t i = 0; i < s.size; i++){
e = &s.events[i];
do {
e->th = acos(1 - 2*gsl_rng_uniform(r));
e->ph = 2 * M_PI * gsl_rng_uniform(r);
} while(0.2 * gsl_rng_uniform(r) > distr(def_par, e));
// update the histogram
gsl_histogram2d_increment(hist, e->th, e->ph);
}
fputs("done\n", stderr);
// print histogram to stdout
if (opts.show_hist || opts.only_hist) {
fputs("\n# histogram\n", stderr);
gsl_histogram2d_fprintf(stdout, hist, "%g", "%g");
}
if (!opts.only_hist) {
/* Estimate the parameters α,β,γ by
* the maximum likelihood method.
*/
min_result like = maxLikelihood(&s);
/* Estimate the parameters α,β,γ by
* a minimum χ² method.
*/
struct hist data;
data.h = hist;
data.n = s.size;
min_result chi2 = minChiSquared(data);
/* Compare the results with the original ones
* and check whether they are compatible.
*/
fputs("\n# vector decay compatibility\n", stderr);
fputs("\n## likelihood results\n\n", stderr);
compatibility(def_par, like);
fputs("\n## χ² results\n\n", stderr);
compatibility(def_par, chi2);
/* Test the isotropic decay hypothesys
* with the χ² results
*/
fputs("\n# isotropic hypotesys\n\n", stderr);
/* If the decay is isotropic then F = 1/4π.
* Solving for α,β,γ yields α=1/3,β=γ=0.
*/
gsl_vector *iso_par = gsl_vector_alloc(3);
gsl_vector_set(iso_par, 0, 0.33); // α
gsl_vector_set(iso_par, 1, 0.00); // β
gsl_vector_set(iso_par, 2, 0.00); // γ
compatibility(iso_par, chi2);
// free memory
min_result_free(like);
min_result_free(chi2);
};
// free memory
gsl_rng_free(r);
free(s.events);
gsl_histogram2d_free(hist);
gsl_vector_free(def_par);
return EXIT_SUCCESS;
}