From 05322ecdd7dfbbb19ace824754eabbff188ad060 Mon Sep 17 00:00:00 2001 From: Arun Isaac Date: Sat, 8 Jan 2022 11:43:01 +0530 Subject: Port volume experiments to python. * python/distribution-volumes.py: New file. --- python/distribution-volumes.py | 77 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 python/distribution-volumes.py diff --git a/python/distribution-volumes.py b/python/distribution-volumes.py new file mode 100644 index 0000000..57e6c03 --- /dev/null +++ b/python/distribution-volumes.py @@ -0,0 +1,77 @@ +# nsmc --- n-sphere Monte Carlo method +# Copyright © 2022 Arun I +# Copyright © 2022 Murugesan Venkatapathi +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# . + +import nsmc +from numpy import linspace +from statistics import mean +import matplotlib.pyplot as plt + +def mean_thunk(f, trials): + return mean([f() for i in range(trials)]) + +def samples_for_dimension_rtol(oracle, true_volume, n, rtol): + print(n, end=' ', flush=True) + volume, samples = nsmc.volume(oracle(n), true_volume(n), n, rtol) + return samples + +def average_samples_for_rtol(oracle, true_volume, rtol, trials, dimension): + for n in dimension: + yield mean_thunk(lambda: samples_for_dimension_rtol(oracle, true_volume, n, rtol), trials) + +def experiment(oracle, true_volume, rtols, trials, dimension, filename): + print(filename) + for rtol in rtols: + print(f'rtol = {rtol}:', end=' ', flush=True) + samples = list(average_samples_for_rtol(oracle, true_volume, rtol, trials, dimension)) + plt.plot(dimension, samples, '-x', label=f'rtol = {rtol}') + print() + plt.yscale('log') + plt.xlabel('Dimension') + plt.ylabel('Average number of samples') + plt.legend() + plt.savefig(filename) + plt.close() + +# Number of trials to average each dimension, rtol point over +trials = 2 + +# Dimensions and relative error tolerances to plot +dimension = linspace(10, 100, 10, dtype=int) +rtols = [0.2, 0.1, 0.05] + +# uniform(0,1) +oracle = lambda n: nsmc.make_uniform_extent_oracle(0, 1) +true_volume = lambda n: nsmc.uniform_true_volume(0, 1, n) +experiment(oracle, true_volume, rtols, trials, dimension, 'uniform.png') + +# beta(2,2) +oracle = lambda n: nsmc.make_beta_extent_oracle(2, 2) +true_volume = lambda n: nsmc.beta_true_volume(2, 2, n) +experiment(oracle, true_volume, rtols, trials, dimension, 'beta.png') + +# arcsine +oracle = lambda n: nsmc.make_beta_extent_oracle(0.5, 0.5) +true_volume = lambda n: nsmc.beta_true_volume(0.5, 0.5, n) +experiment(oracle, true_volume, rtols, trials, dimension, 'arcsine.png') + +# cube (pretty slow for large dimensions and tight tolerances) +oracle = lambda n: nsmc.make_cube_extent_oracle(n, 1.0) +true_volume = lambda n: nsmc.cube_true_volume(n, 1.0) +dimension = linspace(10, 40, 4, dtype=int) +rtols = [0.2, 0.1] +experiment(oracle, true_volume, rtols, trials, dimension, 'cube.png') -- cgit v1.2.3