Muller
sample Muller's potential
|
00001 /* 00002 * This work is licensed under a Creative Commons 00003 * Attribution-Noncommercial-Share Alike 3.0 United States License. 00004 * 00005 * http://creativecommons.org/licenses/by-nc-sa/3.0/us/ 00006 * 00007 * You are free: 00008 * 00009 * to Share - to copy, distribute, display, and perform the work 00010 * to Remix - to make derivative works 00011 * 00012 * Under the following conditions: 00013 * 00014 * Attribution. You must attribute the work in the manner specified by the 00015 * author or licensor (but not in any way that suggests that they endorse you 00016 * or your use of the work). 00017 * 00018 * Noncommercial. You may not use this work for commercial purposes. 00019 * 00020 * Share Alike. If you alter, transform, or build upon this work, you may 00021 * distribute the resulting work only under the same or similar license to 00022 * this one. 00023 * 00024 * For any reuse or distribution, you must make clear to others the license 00025 * terms of this work. The best way to do this is by including this header. 00026 * 00027 * Any of the above conditions can be waived if you get permission from the 00028 * copyright holder. 00029 * 00030 * Apart from the remix rights granted under this license, nothing in this 00031 * license impairs or restricts the author's moral rights. 00032 */ 00033 00034 00087 #include <config.h> 00088 00089 #include <stdlib.h> 00090 #include <stdio.h> 00091 #include <inttypes.h> 00092 #include <string.h> 00093 00094 #include <jwsc/base/error.h> 00095 #include <jwsc/base/option.h> 00096 #include <jwsc/math/constants.h> 00097 #include <jwsc/stat/dynamics.h> 00098 00099 #include "sampler.h" 00100 00101 00102 #define NUM_OPTS_NO_ARG 2 00103 #define NUM_OPTS_WITH_ARG 15 00104 00105 #define DEFAULT_SEED 289375 00106 #define DEFAULT_ITERATIONS 1000 00107 #define DEFAULT_HYBRID_LEAP_ITER 100 00108 #define DEFAULT_START_X 0 00109 #define DEFAULT_START_Y 0 00110 #define DEFAULT_X_SIGMA 0.1 00111 #define DEFAULT_X_MIN -3.0 00112 #define DEFAULT_X_MAX 1.5 00113 #define DEFAULT_Y_SIGMA 0.1 00114 #define DEFAULT_Y_MIN -1.0 00115 #define DEFAULT_Y_MAX 3.0 00116 #define DEFAULT_DELTA_T 0.01 00117 #define DEFAULT_ALPHA 0.9 00118 #define DEFAULT_KICK 0 00119 #define DEFAULT_HYPER_GAMMA 1.0e-5 00120 #define DEFAULT_HYPER_ETA 1.0e-2 00121 #define DEFAULT_HYPER_BIAS 150.0 00122 #define DEFAULT_HYPER_SCALE 0.25 00123 #define DEFAULT_SAMPLER MH 00124 00125 00129 typedef enum 00130 { 00131 MH, 00132 LANGE, 00133 HYPER, 00134 STOCH, 00135 HYBRID 00136 } 00137 Sampler_type; 00138 00139 00141 static Option_no_arg opts_no_arg[NUM_OPTS_NO_ARG]; 00142 00144 static Option_with_arg opts_with_arg[NUM_OPTS_WITH_ARG]; 00145 00147 static uint32_t seed = DEFAULT_SEED; 00148 00150 static uint32_t iterations = DEFAULT_ITERATIONS; 00151 00153 static uint32_t hybrid_leap_iter = DEFAULT_HYBRID_LEAP_ITER; 00154 00156 static double start_x = DEFAULT_START_X; 00157 00159 static double start_y = DEFAULT_START_Y; 00160 00162 static double x_sigma = DEFAULT_X_SIGMA; 00163 00165 static double x_min = DEFAULT_X_MIN; 00166 00168 static double x_max = DEFAULT_X_MAX; 00169 00171 static double y_sigma = DEFAULT_Y_SIGMA; 00172 00174 static double y_min = DEFAULT_Y_MIN; 00175 00177 static double y_max = DEFAULT_Y_MAX; 00178 00180 static double delta_t = DEFAULT_DELTA_T; 00181 00183 static double alpha = DEFAULT_ALPHA; 00184 00189 static uint32_t kick = DEFAULT_KICK; 00190 00192 static double hyper_bias = DEFAULT_HYPER_BIAS; 00193 00195 static double hyper_scale = DEFAULT_HYPER_SCALE; 00196 00198 static double hyper_gamma = DEFAULT_HYPER_GAMMA; 00199 00201 static double hyper_eta = DEFAULT_HYPER_ETA; 00202 00204 static Sampler_type sampler = DEFAULT_SAMPLER; 00205 00206 00207 00209 static void print_usage(void) 00210 { 00211 fprintf(stderr, "usage: muller OPTIONS\n"); 00212 fprintf(stderr, "where OPTIONS is one or more of the following:\n"); 00213 print_options(stderr, 25, NUM_OPTS_NO_ARG, opts_no_arg, NUM_OPTS_WITH_ARG, 00214 opts_with_arg); 00215 } 00216 00218 static Error* process_help_opt(void) 00219 { 00220 print_usage(); 00221 exit(EXIT_SUCCESS); 00222 } 00223 00225 static Error* process_version_opt(void) 00226 { 00227 fprintf(stderr, "%s\n", MULLER_PACKAGE_STRING); 00228 exit(EXIT_SUCCESS); 00229 } 00230 00232 static Error* process_seed_opt(Option_arg arg) 00233 { 00234 if (arg == NULL) 00235 { 00236 return JWSC_EARG("Option 'seed' requires an argument"); 00237 } 00238 if (sscanf(arg, "%u", &seed) != 1) 00239 { 00240 return JWSC_EARG("Option 'seed' requires an argument"); 00241 } 00242 return NULL; 00243 } 00244 00246 static Error* process_iterations_opt(Option_arg arg) 00247 { 00248 if (arg == NULL) 00249 { 00250 return JWSC_EARG("Option 'iterations' requires an argument"); 00251 } 00252 if (sscanf(arg, "%u", &iterations) != 1) 00253 { 00254 return JWSC_EARG("Option 'iterations' requires an argument"); 00255 } 00256 return NULL; 00257 } 00258 00260 static Error* process_hybrid_leap_iter_opt(Option_arg arg) 00261 { 00262 if (arg == NULL) 00263 { 00264 return JWSC_EARG("Option 'hybrid-leap-iter' requires an argument"); 00265 } 00266 if (sscanf(arg, "%u", &hybrid_leap_iter) != 1) 00267 { 00268 return JWSC_EARG("Option 'hybrid-leap-iter' requires an argument"); 00269 } 00270 return NULL; 00271 } 00272 00274 static Error* process_start_x_opt(Option_arg arg) 00275 { 00276 if (arg == NULL) 00277 { 00278 return JWSC_EARG("Option 'start-x' requires an argument"); 00279 } 00280 if (sscanf(arg, "%lf", &start_x) != 1) 00281 { 00282 return JWSC_EARG("Option 'start-x' must be > 0"); 00283 } 00284 return NULL; 00285 } 00286 00288 static Error* process_start_y_opt(Option_arg arg) 00289 { 00290 if (arg == NULL) 00291 { 00292 return JWSC_EARG("Option 'start-y' requires an argument"); 00293 } 00294 if (sscanf(arg, "%lf", &start_y) != 1) 00295 { 00296 return JWSC_EARG("Option 'start-y' must be > 0"); 00297 } 00298 return NULL; 00299 } 00300 00302 static Error* process_delta_t_opt(Option_arg arg) 00303 { 00304 if (arg == NULL) 00305 { 00306 return JWSC_EARG("Option 'delta-t' requires an argument"); 00307 } 00308 if (sscanf(arg, "%lf", &delta_t) != 1 || delta_t <= 0) 00309 { 00310 return JWSC_EARG("Option 'delta-t' must be > 0"); 00311 } 00312 return NULL; 00313 } 00314 00316 static Error* process_alpha_opt(Option_arg arg) 00317 { 00318 if (arg == NULL) 00319 { 00320 return JWSC_EARG("Option 'alpha' requires an argument"); 00321 } 00322 if (sscanf(arg, "%lf", &alpha) != 1 || alpha < 0 || alpha > 1) 00323 { 00324 return JWSC_EARG("Option 'alpha' must be in [0,1]"); 00325 } 00326 return NULL; 00327 } 00328 00330 static Error* process_kick_opt(Option_arg arg) 00331 { 00332 if (arg == NULL) 00333 { 00334 return JWSC_EARG("Option 'kick' requires an argument"); 00335 } 00336 if (sscanf(arg, "%u", &kick) != 1) 00337 { 00338 return JWSC_EARG("Option 'kick' requires an argument"); 00339 } 00340 return NULL; 00341 } 00342 00344 static Error* process_x_lim_opt(Option_arg arg) 00345 { 00346 if (arg == NULL) 00347 { 00348 return JWSC_EARG("Option 'x-lim' requires an argument"); 00349 } 00350 if (sscanf(arg, "%lf,%lf", &x_min, &x_max) != 2) 00351 { 00352 return JWSC_EARG("Option 'x-lim' has format min,max"); 00353 } 00354 if (x_max < x_min) 00355 { 00356 return JWSC_EARG("Option 'x-lim' max must be >= min"); 00357 } 00358 return NULL; 00359 } 00360 00362 static Error* process_x_sigma_opt(Option_arg arg) 00363 { 00364 if (arg == NULL) 00365 { 00366 return JWSC_EARG("Option 'x-sigma' requires an argument"); 00367 } 00368 if (sscanf(arg, "%lf", &x_sigma) != 1 || x_sigma <= 1.0e-8) 00369 { 00370 return JWSC_EARG("Option 'x-sigma' must be > 0"); 00371 } 00372 return NULL; 00373 } 00374 00376 static Error* process_y_lim_opt(Option_arg arg) 00377 { 00378 if (arg == NULL) 00379 { 00380 return JWSC_EARG("Option 'y-lim' requires an argument"); 00381 } 00382 if (sscanf(arg, "%lf,%lf", &y_min, &y_max) != 2) 00383 { 00384 return JWSC_EARG("Option 'y-lim' has format min,max"); 00385 } 00386 if (y_max < y_min) 00387 { 00388 return JWSC_EARG("Option 'y-lim' max must be >= min"); 00389 } 00390 return NULL; 00391 } 00392 00394 static Error* process_y_sigma_opt(Option_arg arg) 00395 { 00396 if (arg == NULL) 00397 { 00398 return JWSC_EARG("Option 'y-sigma' requires an argument"); 00399 } 00400 if (sscanf(arg, "%lf", &y_sigma) != 1 || y_sigma <= 1.0e-8) 00401 { 00402 return JWSC_EARG("Option 'y-sigma' must be > 0"); 00403 } 00404 return NULL; 00405 } 00406 00408 static Error* process_hyper_bias_opt(Option_arg arg) 00409 { 00410 if (arg == NULL) 00411 { 00412 return JWSC_EARG("Option 'hyper-bias' requires an argument"); 00413 } 00414 if (sscanf(arg, "%lf", &hyper_bias) != 1) 00415 { 00416 return JWSC_EARG("Option 'hyper-bias' requires an argument"); 00417 } 00418 return NULL; 00419 } 00420 00422 static Error* process_hyper_scale_opt(Option_arg arg) 00423 { 00424 if (arg == NULL) 00425 { 00426 return JWSC_EARG("Option 'hyper-scale' requires an argument"); 00427 } 00428 if (sscanf(arg, "%lf", &hyper_scale) != 1 || hyper_scale <= 1.0e-8) 00429 { 00430 return JWSC_EARG("Option 'hyper-scale' must be > 0"); 00431 } 00432 return NULL; 00433 } 00434 00436 static Error* process_sampler_opt(Option_arg arg) 00437 { 00438 if (arg == NULL) 00439 { 00440 return JWSC_EARG("Option 'sampler' requires an argument"); 00441 } 00442 if (strncmp(arg, "mh", 2) == 0) 00443 { 00444 sampler = MH; 00445 } 00446 else if (strncmp(arg, "lange", 5) == 0) 00447 { 00448 sampler = LANGE; 00449 } 00450 else if (strncmp(arg, "hyper", 5) == 0) 00451 { 00452 sampler = HYPER; 00453 } 00454 else if (strncmp(arg, "stoch", 5) == 0) 00455 { 00456 sampler = STOCH; 00457 } 00458 else if (strncmp(arg, "hybrid", 6) == 0) 00459 { 00460 sampler = HYBRID; 00461 } 00462 else 00463 { 00464 return JWSC_EARG("Option 'sampler' must be one of {mh, lange, hyper, stoch, hybrid}"); 00465 } 00466 return NULL; 00467 } 00468 00469 00470 00471 00473 int main(int argc, const char** argv) 00474 { 00475 int argi; 00476 uint32_t i; 00477 00478 Params p; 00479 00480 Error* err; 00481 00482 Option_string l_name; 00483 Option_flag s_name; 00484 Option_desc desc; 00485 Option_func_no_arg fnoarg; 00486 Option_func_with_arg farg; 00487 00488 00489 i = 0; 00490 l_name = "help"; 00491 s_name = 'h'; 00492 desc = "Prints program usage."; 00493 fnoarg = process_help_opt; 00494 init_option_no_arg(&(opts_no_arg[i++]), l_name, s_name, desc, fnoarg); 00495 00496 l_name = "version"; 00497 s_name = 'v'; 00498 desc = "Prints program version."; 00499 fnoarg = process_version_opt; 00500 init_option_no_arg(&(opts_no_arg[i++]), l_name, s_name, desc, fnoarg); 00501 00502 i = 0; 00503 l_name = "seed"; 00504 s_name = 0; 00505 desc = "Random seed."; 00506 farg = process_seed_opt; 00507 init_option_with_arg(&(opts_with_arg[i++]), l_name, s_name, desc, farg); 00508 00509 l_name = "iterations"; 00510 s_name = 0; 00511 desc = "Number of sampling iterations."; 00512 farg = process_iterations_opt; 00513 init_option_with_arg(&(opts_with_arg[i++]), l_name, s_name, desc, farg); 00514 00515 l_name = "hybrid-leap-iter"; 00516 s_name = 0; 00517 desc = "Number of hybrid Monte Carlo leapfrog iterations."; 00518 farg = process_hybrid_leap_iter_opt; 00519 init_option_with_arg(&(opts_with_arg[i++]), l_name, s_name, desc, farg); 00520 00521 l_name = "start-x"; 00522 s_name = 0; 00523 desc = "Starting x-coord position."; 00524 farg = process_start_x_opt; 00525 init_option_with_arg(&(opts_with_arg[i++]), l_name, s_name, desc, farg); 00526 00527 l_name = "start-y"; 00528 s_name = 0; 00529 desc = "Starting y-coord position."; 00530 farg = process_start_y_opt; 00531 init_option_with_arg(&(opts_with_arg[i++]), l_name, s_name, desc, farg); 00532 00533 l_name = "delta-t"; 00534 s_name = 0; 00535 desc = "Stochastic dynamics integration step-size for Langevin Monte Carlo."; 00536 farg = process_delta_t_opt; 00537 init_option_with_arg(&(opts_with_arg[i++]), l_name, s_name, desc, farg); 00538 00539 l_name = "alpha"; 00540 s_name = 0; 00541 desc = "Stochastic dynamics step-size for Langevin Monte Carlo."; 00542 farg = process_alpha_opt; 00543 init_option_with_arg(&(opts_with_arg[i++]), l_name, s_name, desc, farg); 00544 00545 l_name = "kick"; 00546 s_name = 0; 00547 desc = "Stochastic dynamics frequency to kick the particle by resetting the momenta. Zero disables any kicking. Must be > 0."; 00548 farg = process_kick_opt; 00549 init_option_with_arg(&(opts_with_arg[i++]), l_name, s_name, desc, farg); 00550 00551 l_name = "x-sigma"; 00552 s_name = 0; 00553 desc = "Gaussian sigma for MH proposal of x. Must be > 0."; 00554 farg = process_x_sigma_opt; 00555 init_option_with_arg(&(opts_with_arg[i++]), l_name, s_name, desc, farg); 00556 00557 l_name = "x-lim"; 00558 s_name = 0; 00559 desc = "Limits over the range of x. Has format min,max"; 00560 farg = process_x_lim_opt; 00561 init_option_with_arg(&(opts_with_arg[i++]), l_name, s_name, desc, farg); 00562 00563 l_name = "y-sigma"; 00564 s_name = 0; 00565 desc = "Gaussian sigma for MH proposal of y. Must be > 0."; 00566 farg = process_y_sigma_opt; 00567 init_option_with_arg(&(opts_with_arg[i++]), l_name, s_name, desc, farg); 00568 00569 l_name = "y-lim"; 00570 s_name = 0; 00571 desc = "Limits over the range of y. Has format min,max."; 00572 farg = process_y_lim_opt; 00573 init_option_with_arg(&(opts_with_arg[i++]), l_name, s_name, desc, farg); 00574 00575 l_name = "sampler"; 00576 s_name = 0; 00577 desc = "Type of sampler to use. Must be one of {mh, lange, hyper, stoch, hybrid}."; 00578 farg = process_sampler_opt; 00579 init_option_with_arg(&(opts_with_arg[i++]), l_name, s_name, desc, farg); 00580 00581 l_name = "hyper-bias"; 00582 s_name = 0; 00583 desc = "Bias parameter for hyper sampling."; 00584 farg = process_hyper_bias_opt; 00585 init_option_with_arg(&(opts_with_arg[i++]), l_name, s_name, desc, farg); 00586 00587 l_name = "hyper-scale"; 00588 s_name = 0; 00589 desc = "Scale parameter for hyper sampling."; 00590 farg = process_hyper_scale_opt; 00591 init_option_with_arg(&(opts_with_arg[i++]), l_name, s_name, desc, farg); 00592 00593 00594 if ((err = process_options(argc, argv, &argi, NUM_OPTS_NO_ARG, opts_no_arg, 00595 NUM_OPTS_WITH_ARG, opts_with_arg)) != NULL) 00596 { 00597 print_error_msg_exit("muller", err->msg); 00598 } 00599 00600 srand(seed); rand(); rand(); 00601 00602 if (start_x == DEFAULT_START_X) 00603 { 00604 start_x = sample_uniform_pdf_d(x_min, x_max); 00605 } 00606 if (start_y == DEFAULT_START_Y) 00607 { 00608 start_y = sample_uniform_pdf_d(y_min, y_max); 00609 } 00610 00611 p.x = start_x; 00612 p.y = start_y; 00613 00614 if (sampler == MH) 00615 { 00616 if ((err = metropolis_hastings(iterations, start_x, start_y, x_sigma, 00617 x_min, x_max, y_sigma, y_min, y_max)) != NULL) 00618 { 00619 print_error_msg_exit("muller", err->msg); 00620 } 00621 } 00622 else if (sampler == LANGE) 00623 { 00624 if ((err = langevin_1_d(iterations, delta_t, &p, get_pt_from_params, 00625 grad_energy_func, langevin_accept_sample)) 00626 != NULL) 00627 { 00628 print_error_msg_exit("muller", err->msg); 00629 } 00630 } 00631 else if (sampler == HYPER) 00632 { 00633 if ((err = langevin_hyperdynamics_1_d(iterations, delta_t, hyper_gamma, 00634 hyper_eta, hyper_bias, hyper_scale, &p, 00635 get_pt_from_params, set_params_from_pt, energy_func, 00636 grad_energy_func, hyper_accept_sample)) != NULL) 00637 { 00638 print_error_msg_exit("muller", err->msg); 00639 } 00640 } 00641 else if (sampler == STOCH) 00642 { 00643 if ((err = stochastic_dynamics_1_d(iterations, delta_t, alpha, kick, &p, 00644 get_pt_from_params, grad_energy_func, 00645 stochastic_dynamics_accept_sample)) != NULL) 00646 { 00647 print_error_msg_exit("muller", err->msg); 00648 } 00649 } 00650 else if (sampler == HYBRID) 00651 { 00652 if ((err = hybrid_monte_carlo_1_d(iterations, hybrid_leap_iter, 00653 delta_t, alpha, kick, &p, get_pt_from_params, 00654 set_params_from_pt, energy_func, grad_energy_func, 00655 hybrid_mc_accept_sample, NULL)) != NULL) 00656 { 00657 print_error_msg_exit("muller", err->msg); 00658 } 00659 } 00660 00661 if (get_num_unhandled_errors() > 0) 00662 { 00663 print_error_msg_exit("muller", "Unhandled errors"); 00664 } 00665 00666 return EXIT_SUCCESS; 00667 }