pystochastic 0.2.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. benchmarks/bench_montecarlo.py +107 -0
  2. benchmarks/bench_processes.py +163 -0
  3. benchmarks/bench_pyrandom.py +95 -0
  4. benchmarks/bench_sde.py +185 -0
  5. pystochastic/__init__.py +7 -0
  6. pystochastic/dist/__init__.py +25 -0
  7. pystochastic/dist/dist.py +2275 -0
  8. pystochastic/montecarlo/__init__.py +3 -0
  9. pystochastic/montecarlo/montecarlo.py +965 -0
  10. pystochastic/processes/CIR.py +284 -0
  11. pystochastic/processes/GeometricBrownianMotion.py +443 -0
  12. pystochastic/processes/OrnsteinUhlenbeck.py +462 -0
  13. pystochastic/processes/__init__.py +6 -0
  14. pystochastic/processes/brownian.py +461 -0
  15. pystochastic/processes/poisson.py +202 -0
  16. pystochastic/processes/vasicek.py +463 -0
  17. pystochastic/pyrandom/__init__.py +5 -0
  18. pystochastic/pyrandom/crandom.py +567 -0
  19. pystochastic/pyrandom/drandom.py +424 -0
  20. pystochastic/pyrandom/setseed.py +11 -0
  21. pystochastic/sde/__init__.py +4 -0
  22. pystochastic/sde/eulermaruyama.py +365 -0
  23. pystochastic/sde/milstein.py +177 -0
  24. pystochastic/utils.py +57 -0
  25. pystochastic-0.2.0.dist-info/METADATA +404 -0
  26. pystochastic-0.2.0.dist-info/RECORD +43 -0
  27. pystochastic-0.2.0.dist-info/WHEEL +5 -0
  28. pystochastic-0.2.0.dist-info/licenses/LICENSE +22 -0
  29. pystochastic-0.2.0.dist-info/top_level.txt +3 -0
  30. tests/api/test_api.py +53 -0
  31. tests/api/test_conftest.py +10 -0
  32. tests/api/test_utils.py +26 -0
  33. tests/distributions/test_continuous.py +200 -0
  34. tests/distributions/test_discrete.py +219 -0
  35. tests/distributions/test_dist_general.py +165 -0
  36. tests/distributions/test_interface.py +51 -0
  37. tests/distributions/test_pyrandom.py +93 -0
  38. tests/montecarlo/test_montecarlo1.py +609 -0
  39. tests/montecarlo/test_montecarlo2.py +207 -0
  40. tests/processes/test_processes.py +450 -0
  41. tests/solvers/test_eulermaruyama.py +325 -0
  42. tests/solvers/test_milstein.py +298 -0
  43. tests/solvers/test_sde.py +128 -0
@@ -0,0 +1,107 @@
1
+ """
2
+ Benchmark for pystochastic.montecarlo (MonteCarloEstimator, MonteCarloProcess).
3
+ """
4
+
5
+ import time
6
+ import numpy as np
7
+
8
+ from pystochastic.pyrandom import crandom
9
+ from pystochastic.processes.vasicek import Vasicek
10
+ from pystochastic.montecarlo.montecarlo import MonteCarloEstimator, MonteCarloProcess
11
+
12
+
13
+ # ---------------------------------------------------------------------
14
+ # Benchmark helper
15
+ # ---------------------------------------------------------------------
16
+
17
+ def time_call(fn, n_runs=5):
18
+ times = []
19
+ for _ in range(n_runs):
20
+ start = time.perf_counter()
21
+ fn()
22
+ end = time.perf_counter()
23
+ times.append(end - start)
24
+ return np.mean(times), np.min(times), np.max(times)
25
+
26
+
27
+ # ---------------------------------------------------------------------
28
+ # MonteCarloEstimator benchmark
29
+ # ---------------------------------------------------------------------
30
+
31
+ def run_estimator_benchmark(sample_sizes, n_runs=5):
32
+ print("=" * 70)
33
+ print("MonteCarloEstimator benchmark")
34
+ print("=" * 70)
35
+ print(f"Runs : {n_runs}")
36
+ print("-" * 70)
37
+
38
+ for n in sample_sizes:
39
+ print(f"n_simulations = {n:,}")
40
+ samples = crandom.gamma(3, 2, n)
41
+ mc = MonteCarloEstimator(samples)
42
+
43
+ for name, fn in {
44
+ "estimate": lambda: mc.estimate(),
45
+ "mean_estimator": lambda: mc.mean_estimator(),
46
+ "confidence_interval": lambda: mc.confidence_interval(),
47
+ "confidence_curve": lambda: mc.confidence_curve(),
48
+ }.items():
49
+ try:
50
+ mean_t, min_t, max_t = time_call(fn, n_runs=n_runs)
51
+ print(f" {name:<20s} : {mean_t*1000:8.3f} ms (min={min_t*1000:.3f}, max={max_t*1000:.3f})")
52
+ except Exception as e:
53
+ print(f" {name:<20s} : ERROR ({type(e).__name__}: {e})")
54
+ print("-" * 70)
55
+
56
+
57
+ # ---------------------------------------------------------------------
58
+ # MonteCarloProcess benchmark
59
+ # ---------------------------------------------------------------------
60
+
61
+ def run_process_benchmark(sample_sizes, n_runs=3):
62
+ print("=" * 70)
63
+ print("MonteCarloProcess benchmark (Vasicek, method='exact')")
64
+ print("=" * 70)
65
+ print(f"Runs : {n_runs}")
66
+ print("-" * 70)
67
+
68
+ for n in sample_sizes:
69
+ print(f"n_simulations = {n:,}")
70
+
71
+ def build():
72
+ process = Vasicek(reversion_speed=2, mu=1.5, volatility=0.3, r_0=0, n_steps=200)
73
+ return MonteCarloProcess(process, n_simulations=n)
74
+
75
+ try:
76
+ mean_t, min_t, max_t = time_call(build, n_runs=n_runs)
77
+ print(f" construction (incl. simulate) : {mean_t:8.4f} s (min={min_t:.4f}, max={max_t:.4f})")
78
+ except Exception as e:
79
+ print(f" construction (incl. simulate) : ERROR ({type(e).__name__}: {e})")
80
+ print("-" * 70)
81
+ continue
82
+
83
+ mc = build()
84
+
85
+ for name, fn in {
86
+ "estimate": lambda: mc.estimate(),
87
+ "mean_path": lambda: mc.mean_path(plot_sim=False),
88
+ }.items():
89
+ try:
90
+ mean_t, min_t, max_t = time_call(fn, n_runs=n_runs)
91
+ print(f" {name:<28s} : {mean_t:8.4f} s (min={min_t:.4f}, max={max_t:.4f})")
92
+ except Exception as e:
93
+ print(f" {name:<28s} : ERROR ({type(e).__name__}: {e})")
94
+ print("-" * 70)
95
+
96
+
97
+ # ---------------------------------------------------------------------
98
+ # Main benchmark
99
+ # ---------------------------------------------------------------------
100
+
101
+ def main():
102
+ run_estimator_benchmark(sample_sizes=[1_000, 10_000, 100_000, 1_000_000], n_runs=5)
103
+ run_process_benchmark(sample_sizes=[100, 1_000, 5_000], n_runs=3)
104
+
105
+
106
+ if __name__ == "__main__":
107
+ main()
@@ -0,0 +1,163 @@
1
+ """
2
+ Benchmark for pystochastic.processes (Vasicek, CIR, OrnsteinUhlenbeck,
3
+ GeometricBrownianMotion, Poisson, Brownian).
4
+
5
+ Measures simulation time as a function of the number of simulations and
6
+ time steps, for each available method ("exact", "euler-maruyama",
7
+ "milstein" when applicable).
8
+ """
9
+
10
+ import time
11
+ import numpy as np
12
+
13
+ from pystochastic.processes.vasicek import Vasicek
14
+ from pystochastic.processes.CIR import CIR
15
+ from pystochastic.processes.OrnsteinUhlenbeck import OrnsteinUhlenbeck
16
+ from pystochastic.processes.GeometricBrownianMotion import GeometricBrownianMotion
17
+ from pystochastic.processes.poisson import Poisson
18
+ from pystochastic.processes.brownian import Brownian
19
+
20
+
21
+ # ---------------------------------------------------------------------
22
+ # Benchmark helper
23
+ # ---------------------------------------------------------------------
24
+
25
+ def benchmark_simulate(build_process, n_simulations, method=None, n_runs=3, **simulate_kwargs):
26
+ """
27
+ build_process : callable() -> a fresh process instance (rebuilt each run,
28
+ so that internal caches -- if any -- don't distort the timing).
29
+ """
30
+ times = []
31
+ for _ in range(n_runs):
32
+ process = build_process()
33
+ start = time.perf_counter()
34
+ if method is not None:
35
+ process.simulate(n_simulations=n_simulations, method=method, plot=False,**simulate_kwargs)
36
+ else:
37
+ process.simulate(n_simulations=n_simulations, plot=False,**simulate_kwargs)
38
+ end = time.perf_counter()
39
+ times.append(end - start)
40
+ return np.mean(times), np.min(times), np.max(times)
41
+
42
+
43
+ def run_process_group(label, build_process, methods, simulations, time_steps, n_runs=3):
44
+ print("=" * 70)
45
+ print(f"processes benchmark -- {label}")
46
+ print("=" * 70)
47
+ print(f"Runs : {n_runs}")
48
+ print("-" * 70)
49
+
50
+ for n_steps in time_steps:
51
+ print(f"Number of time steps : {n_steps}")
52
+ print("-" * 70)
53
+
54
+ for n_simulations in simulations:
55
+ print(f"Simulations : {n_simulations:,}")
56
+ for method in methods:
57
+ try:
58
+ mean_t, min_t, max_t = benchmark_simulate(
59
+ lambda: build_process(n_steps),
60
+ n_simulations=n_simulations,
61
+ method=method,
62
+ n_runs=n_runs,
63
+ )
64
+ print(f" {method:<16s} : {mean_t:8.4f} s (min={min_t:.4f}, max={max_t:.4f})")
65
+ except Exception as e:
66
+ print(f" {method:<16s} : ERROR ({type(e).__name__}: {e})")
67
+ print("-" * 70)
68
+
69
+
70
+ def run_no_method_group(label, build_process, simulations, time_steps, n_runs=3):
71
+ """For processes without a `method` argument (Poisson, Brownian)."""
72
+ print("=" * 70)
73
+ print(f"processes benchmark -- {label}")
74
+ print("=" * 70)
75
+ print(f"Runs : {n_runs}")
76
+ print("-" * 70)
77
+
78
+ for n_steps in time_steps:
79
+ print(f"Number of time steps : {n_steps}")
80
+ print("-" * 70)
81
+
82
+ for n_simulations in simulations:
83
+ try:
84
+ mean_t, min_t, max_t = benchmark_simulate(
85
+ lambda: build_process(n_steps),
86
+ n_simulations=n_simulations,
87
+ method=None,
88
+ n_runs=n_runs,
89
+ )
90
+ print(f"Simulations : {n_simulations:<8,} : {mean_t:8.4f} s (min={min_t:.4f}, max={max_t:.4f})")
91
+ except Exception as e:
92
+ print(f"Simulations : {n_simulations:<8,} : ERROR ({type(e).__name__}: {e})")
93
+ print("-" * 70)
94
+
95
+
96
+ # ---------------------------------------------------------------------
97
+ # Main benchmark
98
+ # ---------------------------------------------------------------------
99
+
100
+ def main():
101
+
102
+ simulations = [100, 1_000, 5_000, 10_000]
103
+ time_steps = [100, 500]
104
+ methods = ["exact", "euler-maruyama", "milstein"]
105
+ n_runs = 3
106
+
107
+ run_process_group(
108
+ "Vasicek",
109
+ build_process=lambda n_steps: Vasicek(reversion_speed=2, mu=1.5, volatility=0.3, r_0=0, n_steps=n_steps),
110
+ methods=methods,
111
+ simulations=simulations,
112
+ time_steps=time_steps,
113
+ n_runs=n_runs,
114
+ )
115
+
116
+ run_process_group(
117
+ "CIR",
118
+ build_process=lambda n_steps: CIR(a=2, b=0.05, sigma=0.1, r_0=0.03, n_steps=n_steps),
119
+ methods=methods,
120
+ simulations=simulations,
121
+ time_steps=time_steps,
122
+ n_runs=n_runs,
123
+ )
124
+
125
+ run_process_group(
126
+ "OrnsteinUhlenbeck",
127
+ build_process=lambda n_steps: OrnsteinUhlenbeck(mu=2, sigma=0.5, theta=1.5, r_0=0, n_steps=n_steps),
128
+ methods=methods,
129
+ simulations=simulations,
130
+ time_steps=time_steps,
131
+ n_runs=n_runs,
132
+ )
133
+
134
+ run_process_group(
135
+ "GeometricBrownianMotion",
136
+ build_process=lambda n_steps: GeometricBrownianMotion(mu=0.05, sigma=0.2, S_0=100, n_steps=n_steps),
137
+ methods=methods,
138
+ simulations=simulations,
139
+ time_steps=time_steps,
140
+ n_runs=n_runs,
141
+ )
142
+
143
+ # Poisson has not been vectorized yet (see conversation) -- expect this
144
+ # to scale much more slowly than the processes above.
145
+ run_no_method_group(
146
+ "Poisson",
147
+ build_process=lambda n_steps: Poisson(intensity=3, n_steps=n_steps),
148
+ simulations=[100, 1_000, 5_000],
149
+ time_steps=time_steps,
150
+ n_runs=n_runs,
151
+ )
152
+
153
+ run_no_method_group(
154
+ "Brownian",
155
+ build_process=lambda n_steps: Brownian(1, n_steps=n_steps),
156
+ simulations=simulations,
157
+ time_steps=time_steps,
158
+ n_runs=n_runs,
159
+ )
160
+
161
+
162
+ if __name__ == "__main__":
163
+ main()
@@ -0,0 +1,95 @@
1
+ """
2
+ Benchmark for pystochastic.pyrandom (crandom + drandom).
3
+
4
+ Measures generation time for each distribution as a function of the
5
+ number of samples requested. Errors on individual distributions are
6
+ reported but do not stop the benchmark.
7
+ """
8
+
9
+ import time
10
+ import numpy as np
11
+
12
+ from pystochastic.pyrandom import crandom
13
+ from pystochastic.pyrandom import drandom
14
+
15
+
16
+ # ---------------------------------------------------------------------
17
+ # Benchmark helper
18
+ # ---------------------------------------------------------------------
19
+
20
+ def benchmark_call(fn, n_runs=5):
21
+ """Times a zero-argument callable n_runs times."""
22
+ times = []
23
+ for _ in range(n_runs):
24
+ start = time.perf_counter()
25
+ fn()
26
+ end = time.perf_counter()
27
+ times.append(end - start)
28
+ return np.mean(times), np.min(times), np.max(times)
29
+
30
+
31
+ def run_group(label, functions, sample_sizes, n_runs=5):
32
+ """
33
+ functions : dict {name: callable(n) -> samples}
34
+ """
35
+ print("=" * 70)
36
+ print(f"pyrandom benchmark -- {label}")
37
+ print("=" * 70)
38
+ print(f"Runs : {n_runs}")
39
+ print("-" * 70)
40
+
41
+ for n in sample_sizes:
42
+ print(f"n = {n:,}")
43
+ for name, fn in functions.items():
44
+ try:
45
+ mean_t, min_t, max_t = benchmark_call(lambda: fn(n), n_runs=n_runs)
46
+ print(f" {name:<18s} : {mean_t*1000:8.3f} ms (min={min_t*1000:.3f}, max={max_t*1000:.3f})")
47
+ except Exception as e:
48
+ print(f" {name:<18s} : ERROR ({type(e).__name__}: {e})")
49
+ print("-" * 70)
50
+
51
+
52
+ # ---------------------------------------------------------------------
53
+ # Main benchmark
54
+ # ---------------------------------------------------------------------
55
+
56
+ def main():
57
+
58
+ sample_sizes = [1_000, 10_000, 100_000, 1_000_000]
59
+ n_runs = 5
60
+
61
+ continuous_laws = {
62
+ "uniform": lambda n: crandom.uniform(0, 1, n),
63
+ "exponential": lambda n: crandom.exponential(1, n),
64
+ "normal": lambda n: crandom.normal(0, 1, n),
65
+ "gamma (int shape)": lambda n: crandom.gamma(3, 1, n),
66
+ "gamma (frac shape)": lambda n: crandom.gamma(2.5, 1, n),
67
+ "beta": lambda n: crandom.beta(2, 3, n),
68
+ "weibull": lambda n: crandom.weibull(1.5, 1, n),
69
+ "frechet": lambda n: crandom.frechet(2, 1, 0, n),
70
+ "cauchy": lambda n: crandom.cauchy(0, 1, n),
71
+ "gumbel": lambda n: crandom.gumbel(0, 1, n),
72
+ "kumaraswamy": lambda n: crandom.kumaraswamy(2, 3, n),
73
+ "fisher": lambda n: crandom.fisher(4, 10, n),
74
+ "pareto": lambda n: crandom.pareto(1, 3, n),
75
+ "rayleigh": lambda n: crandom.rayleigh(1, n),
76
+ }
77
+
78
+ discrete_laws = {
79
+ "duniform": lambda n: drandom.duniform(10, n),
80
+ "bernoulli": lambda n: drandom.bernoulli(0.3, n),
81
+ "rademacher": lambda n: drandom.rademacher(0.5, n),
82
+ "binomial": lambda n: drandom.binomial(0.3, 20, n),
83
+ "poisson": lambda n: drandom.poisson(3, n),
84
+ "hypergeometric": lambda n: drandom.hypergeometric(50, 20, 10, n),
85
+ "geometric": lambda n: drandom.geometric(0.3, n),
86
+ "negative_binomial": lambda n: drandom.negative_binomial(0.3, 5, n),
87
+ "yule_simon": lambda n: drandom.yule_simon(2, n),
88
+ }
89
+
90
+ run_group("continuous laws (crandom)", continuous_laws, sample_sizes, n_runs=n_runs)
91
+ run_group("discrete laws (drandom)", discrete_laws, sample_sizes, n_runs=n_runs)
92
+
93
+
94
+ if __name__ == "__main__":
95
+ main()
@@ -0,0 +1,185 @@
1
+ """
2
+ Benchmark for pystochastic.sde (EulerMaruyama, Milstein).
3
+
4
+ Compares the vectorized path (diagonal diffusion) against the sequential
5
+ path (full matrix diffusion) for EulerMaruyama, with and without
6
+ parallelization (multiprocess) on the sequential path, and benchmarks
7
+ Milstein (always vectorized, restricted to autonomous 1D SDEs).
8
+ """
9
+
10
+ import time
11
+ import numpy as np
12
+
13
+ from pystochastic.sde.eulermaruyama import EulerMaruyama
14
+ from pystochastic.sde.milstein import Milstein
15
+
16
+
17
+ # ---------------------------------------------------------------------
18
+ # Test functions -- matrix form (sequential path)
19
+ # ---------------------------------------------------------------------
20
+
21
+ def cheap_drift(x, t):
22
+ return x
23
+
24
+
25
+ def cheap_diffusion_matrix(x, t):
26
+ return 0.1 * np.eye(len(x))
27
+
28
+
29
+ def normal_drift(x, t):
30
+ return np.sin(x) + 0.5 * x
31
+
32
+
33
+ def normal_diffusion_matrix(x, t):
34
+ return np.diag(0.1 + 0.05 * np.abs(x))
35
+
36
+
37
+ # ---------------------------------------------------------------------
38
+ # Test functions -- diagonal form (vectorized path), same underlying SDE
39
+ # ---------------------------------------------------------------------
40
+
41
+ def cheap_diffusion_diag(x, t):
42
+ return 0.1 * np.ones_like(x)
43
+
44
+
45
+ def normal_diffusion_diag(x, t):
46
+ return 0.1 + 0.05 * np.abs(x)
47
+
48
+
49
+ # ---------------------------------------------------------------------
50
+ # Milstein test functions (autonomous, 1D only)
51
+ # ---------------------------------------------------------------------
52
+
53
+ def milstein_drift(x):
54
+ return -x
55
+
56
+
57
+ def milstein_diffusion(x):
58
+ return 0.3 * np.ones_like(x)
59
+
60
+
61
+ # ---------------------------------------------------------------------
62
+ # Benchmark helpers
63
+ # ---------------------------------------------------------------------
64
+
65
+ def benchmark_euler(n_simulations, n_steps, mu, sigma, n_runs=3, dim=1, parallel=False, n_workers=None):
66
+ x_0 = np.ones(dim)
67
+ times = []
68
+ for _ in range(n_runs):
69
+ solver = EulerMaruyama(mu=mu, sigma=sigma, x_0=x_0, t_0=0, t_n=1,
70
+ n_steps=n_steps, n_simulations=n_simulations)
71
+ start = time.perf_counter()
72
+ solver.solve(plot=False, parallel=parallel, n_workers=n_workers)
73
+ end = time.perf_counter()
74
+ times.append(end - start)
75
+ return np.mean(times), np.min(times), np.max(times)
76
+
77
+
78
+ def benchmark_milstein(n_simulations, n_steps, mu, sigma, n_runs=3):
79
+ times = []
80
+ for _ in range(n_runs):
81
+ solver = Milstein(mu=mu, sigma=sigma, x_0=1.0, t_0=0, t_n=1,
82
+ n_steps=n_steps, n_simulations=n_simulations)
83
+ start = time.perf_counter()
84
+ solver.solve(plot=False)
85
+ end = time.perf_counter()
86
+ times.append(end - start)
87
+ return np.mean(times), np.min(times), np.max(times)
88
+
89
+
90
+ # ---------------------------------------------------------------------
91
+ # Comparison runner (Euler-Maruyama : matrix vs diagonal vs matrix+parallel)
92
+ # ---------------------------------------------------------------------
93
+
94
+ def run_euler_comparison(label, mu, sigma_matrix, sigma_diag, simulations, time_steps, n_runs=3, n_workers=None):
95
+
96
+ print("=" * 70)
97
+ print(f"EulerMaruyama benchmark -- {label}")
98
+ print("=" * 70)
99
+ print(f"Runs : {n_runs}")
100
+ print("-" * 70)
101
+
102
+ for n_steps in time_steps:
103
+ print(f"Number of time steps : {n_steps}")
104
+ print("-" * 70)
105
+
106
+ for n_simulations in simulations:
107
+
108
+ mat_mean, mat_min, mat_max = benchmark_euler(
109
+ n_simulations, n_steps, mu, sigma_matrix, n_runs=n_runs, parallel=False,
110
+ )
111
+ par_mean, par_min, par_max = benchmark_euler(
112
+ n_simulations, n_steps, mu, sigma_matrix, n_runs=n_runs, parallel=True, n_workers=n_workers,
113
+ )
114
+ diag_mean, diag_min, diag_max = benchmark_euler(
115
+ n_simulations, n_steps, mu, sigma_diag, n_runs=n_runs, parallel=False,
116
+ )
117
+
118
+ speedup_par = mat_mean / par_mean if par_mean > 0 else float("inf")
119
+ speedup_vec = mat_mean / diag_mean if diag_mean > 0 else float("inf")
120
+
121
+ print(
122
+ f"Simulations : {n_simulations:,}\n"
123
+ f" Matrix (sequential) : {mat_mean:.4f} s (min={mat_min:.4f}, max={mat_max:.4f})\n"
124
+ f" Matrix (parallel) : {par_mean:.4f} s (min={par_min:.4f}, max={par_max:.4f})"
125
+ f" -> speedup x{speedup_par:.1f}\n"
126
+ f" Diagonal (vectorized) : {diag_mean:.4f} s (min={diag_min:.4f}, max={diag_max:.4f})"
127
+ f" -> speedup x{speedup_vec:.1f}"
128
+ )
129
+
130
+ print("-" * 70)
131
+
132
+
133
+ def run_milstein_benchmark(simulations, time_steps, n_runs=3):
134
+ print("=" * 70)
135
+ print("Milstein benchmark (always vectorized)")
136
+ print("=" * 70)
137
+ print(f"Runs : {n_runs}")
138
+ print("-" * 70)
139
+
140
+ for n_steps in time_steps:
141
+ print(f"Number of time steps : {n_steps}")
142
+ print("-" * 70)
143
+ for n_simulations in simulations:
144
+ mean_t, min_t, max_t = benchmark_milstein(
145
+ n_simulations, n_steps, milstein_drift, milstein_diffusion, n_runs=n_runs,
146
+ )
147
+ print(f"Simulations : {n_simulations:<8,} : {mean_t:.4f} s (min={min_t:.4f}, max={max_t:.4f})")
148
+ print("-" * 70)
149
+
150
+
151
+ # ---------------------------------------------------------------------
152
+ # Main benchmark
153
+ # ---------------------------------------------------------------------
154
+
155
+ def main():
156
+
157
+ simulations = [100, 1_000, 5_000, 10_000]
158
+ time_steps = [100, 500]
159
+ n_runs = 3
160
+
161
+ run_euler_comparison(
162
+ "cheap drift/diffusion",
163
+ mu=cheap_drift,
164
+ sigma_matrix=cheap_diffusion_matrix,
165
+ sigma_diag=cheap_diffusion_diag,
166
+ simulations=simulations,
167
+ time_steps=time_steps,
168
+ n_runs=n_runs,
169
+ )
170
+
171
+ run_euler_comparison(
172
+ "normal drift/diffusion",
173
+ mu=normal_drift,
174
+ sigma_matrix=normal_diffusion_matrix,
175
+ sigma_diag=normal_diffusion_diag,
176
+ simulations=simulations,
177
+ time_steps=time_steps,
178
+ n_runs=n_runs,
179
+ )
180
+
181
+ run_milstein_benchmark(simulations, time_steps, n_runs=n_runs)
182
+
183
+
184
+ if __name__ == "__main__":
185
+ main()
@@ -0,0 +1,7 @@
1
+ from . import pyrandom
2
+ from . import processes
3
+ from . import sde
4
+ from . import dist
5
+ from . import montecarlo
6
+
7
+ __version__ = "0.1.0"
@@ -0,0 +1,25 @@
1
+ from .dist import Distribution, Uniform, Exponential, Normal, Gamma, Beta, Weibull, Frechet, Cauchy, Gumbel, Kumaraswamy, Fisher, Pareto, Rayleigh, DiscreteDistribution, DUniform, Bernoulli, Rademacher, Binomial, Poisson, Hypergeometric, Geometric, NegativeBinomial, YuleSimon
2
+
3
+ __all__ = ["Distribution",
4
+ "Uniform",
5
+ "Exponential",
6
+ "Normal",
7
+ "Gamma",
8
+ "Beta",
9
+ "Weibull",
10
+ "Frechet",
11
+ "Cauchy",
12
+ "Gumbel",
13
+ "Kumaraswamy",
14
+ "Fisher",
15
+ "Pareto",
16
+ "Rayleigh",
17
+ "DiscreteDistribution",
18
+ "DUniform",
19
+ "Bernoulli",
20
+ "Poisson",
21
+ "Hypergeometric",
22
+ "Geometric",
23
+ "NegativeBinomial",
24
+ "YuleSimon"
25
+ ]