funcsim 0.2.2__tar.gz → 0.2.4__tar.gz

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 (38) hide show
  1. {funcsim-0.2.2/funcsim.egg-info → funcsim-0.2.4}/PKG-INFO +25 -17
  2. funcsim-0.2.4/README.md +47 -0
  3. {funcsim-0.2.2 → funcsim-0.2.4}/funcsim/__init__.py +2 -2
  4. {funcsim-0.2.2 → funcsim-0.2.4}/funcsim/core.py +36 -16
  5. {funcsim-0.2.2 → funcsim-0.2.4}/funcsim/cpt.py +2 -2
  6. {funcsim-0.2.2 → funcsim-0.2.4}/funcsim/dependence.py +72 -26
  7. funcsim-0.2.4/funcsim/distfit.py +725 -0
  8. {funcsim-0.2.2 → funcsim-0.2.4}/funcsim/ecdfgof.py +21 -9
  9. {funcsim-0.2.2 → funcsim-0.2.4}/funcsim/eut.py +2 -2
  10. {funcsim-0.2.2 → funcsim-0.2.4}/funcsim/imanconover.py +3 -3
  11. {funcsim-0.2.2 → funcsim-0.2.4}/funcsim/plotting.py +17 -12
  12. {funcsim-0.2.2 → funcsim-0.2.4}/funcsim/rdarrays.py +15 -2
  13. {funcsim-0.2.2 → funcsim-0.2.4}/funcsim/screen.py +17 -4
  14. {funcsim-0.2.2 → funcsim-0.2.4}/funcsim/shrinkage.py +20 -6
  15. {funcsim-0.2.2 → funcsim-0.2.4/funcsim.egg-info}/PKG-INFO +25 -17
  16. {funcsim-0.2.2 → funcsim-0.2.4}/setup.py +1 -1
  17. funcsim-0.2.2/README.md +0 -39
  18. funcsim-0.2.2/funcsim/distfit.py +0 -307
  19. {funcsim-0.2.2 → funcsim-0.2.4}/LICENSE +0 -0
  20. {funcsim-0.2.2 → funcsim-0.2.4}/MANIFEST.in +0 -0
  21. {funcsim-0.2.2 → funcsim-0.2.4}/funcsim/addist.py +0 -0
  22. {funcsim-0.2.2 → funcsim-0.2.4}/funcsim/conversions.py +0 -0
  23. {funcsim-0.2.2 → funcsim-0.2.4}/funcsim/copfit.py +0 -0
  24. {funcsim-0.2.2 → funcsim-0.2.4}/funcsim/cvmdist.py +0 -0
  25. {funcsim-0.2.2 → funcsim-0.2.4}/funcsim/edf.py +0 -0
  26. {funcsim-0.2.2 → funcsim-0.2.4}/funcsim/kde.py +0 -0
  27. {funcsim-0.2.2 → funcsim-0.2.4}/funcsim/ksdist.py +0 -0
  28. {funcsim-0.2.2 → funcsim-0.2.4}/funcsim/multicore.py +0 -0
  29. {funcsim-0.2.2 → funcsim-0.2.4}/funcsim/nearby.py +0 -0
  30. {funcsim-0.2.2 → funcsim-0.2.4}/funcsim/shapiro.py +0 -0
  31. {funcsim-0.2.2 → funcsim-0.2.4}/funcsim/testsim.py +0 -0
  32. {funcsim-0.2.2 → funcsim-0.2.4}/funcsim/utests.py +0 -0
  33. {funcsim-0.2.2 → funcsim-0.2.4}/funcsim/vect.py +0 -0
  34. {funcsim-0.2.2 → funcsim-0.2.4}/funcsim.egg-info/SOURCES.txt +0 -0
  35. {funcsim-0.2.2 → funcsim-0.2.4}/funcsim.egg-info/dependency_links.txt +0 -0
  36. {funcsim-0.2.2 → funcsim-0.2.4}/funcsim.egg-info/requires.txt +0 -0
  37. {funcsim-0.2.2 → funcsim-0.2.4}/funcsim.egg-info/top_level.txt +0 -0
  38. {funcsim-0.2.2 → funcsim-0.2.4}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: funcsim
3
- Version: 0.2.2
3
+ Version: 0.2.4
4
4
  Summary: functional, simple stochastic simulation
5
5
  Home-page: https://github.com/h-bryant/funcsim
6
6
  Author: Henry Bryant
@@ -46,35 +46,43 @@ Dynamic: summary
46
46
  # funcsim
47
47
  Lightweight, functional stochastic simulation
48
48
 
49
+ Documentation: https://funcsim.readthedocs.io/
50
+
49
51
  Features:
50
- - cross-sectional and recursive dynamic simulations
51
- - pseudo-random numbers (so that results are comparable across multiple runs or scenarios)
52
+ - static (cross-sectional) and recursive-dynamic simulations from a single user-written function
53
+ - pseudo-random numbers with an explicit seed (so that results are reproducible and comparable across runs or scenarios)
52
54
  - stratified/Latin hypercube sampling
53
55
  - painless multi-core simulations
56
+ - fitting and comparison of univariate distributions, kernel density estimates, and goodness-of-fit tests
57
+ - multivariate normal and KDE distributions; Gaussian, Student's t, Clayton, Gumbel, and Frank copulas (implemented natively, no additional packages required); Iman-Conover
58
+ - expected utility and cumulative prospect theory calculations
59
+ - plotly-based fan charts and diagnostic plots
54
60
  - highly flexible, and as simple as possible (but no more)
55
61
  - functional paradigm
56
62
 
57
- Developed using:
58
- - python >= 3.10
59
- - numpy 2.2.0
60
- - scipy 1.16.0
61
- - pandas 2.2.0 (pandas 2.2+ and 3.x are both supported)
62
- - xarray 2025.4.0
63
-
64
- Copulas (Gaussian, Student's t, Clayton, Gumbel, and Frank) are supported
65
- natively; no additional packages are required.
63
+ Requirements:
64
+ - python >= 3.11
65
+ - numpy >= 2.2.0
66
+ - scipy >= 1.16.0
67
+ - pandas >= 2.2.0 (pandas 2.2+ and 3.x are both supported)
68
+ - xarray >= 2025.4.0
66
69
 
67
- For optional functionality, additinoal packages are needed:
68
- - plotting: plotly
70
+ For optional functionality, additional packages are needed:
71
+ - plotting: plotly (`pip install "funcsim[plotting]"`); kaleido for static image export
69
72
 
70
- Additionally, to run the demos, run tests, and build docs:
73
+ Additionally, to run the tests and build the docs:
71
74
  - pytest
72
- - sphinx, sphinx-autodoc-typehints
75
+ - sphinx, sphinx-autodoc-typehints (`pip install "funcsim[docs]"`)
76
+
77
+ ### installation
78
+ ```bash
79
+ pip install funcsim
80
+ ```
73
81
 
74
82
  ### building html docs
75
83
  From the top-level funcsim directory...
76
84
  ```bash
77
- sphinx-build -b html docs/source/ docs/build/
85
+ sphinx-build -W -b html docs/source/ docs/build/
78
86
  ```
79
87
 
80
88
  ### running tests
@@ -0,0 +1,47 @@
1
+ # funcsim
2
+ Lightweight, functional stochastic simulation
3
+
4
+ Documentation: https://funcsim.readthedocs.io/
5
+
6
+ Features:
7
+ - static (cross-sectional) and recursive-dynamic simulations from a single user-written function
8
+ - pseudo-random numbers with an explicit seed (so that results are reproducible and comparable across runs or scenarios)
9
+ - stratified/Latin hypercube sampling
10
+ - painless multi-core simulations
11
+ - fitting and comparison of univariate distributions, kernel density estimates, and goodness-of-fit tests
12
+ - multivariate normal and KDE distributions; Gaussian, Student's t, Clayton, Gumbel, and Frank copulas (implemented natively, no additional packages required); Iman-Conover
13
+ - expected utility and cumulative prospect theory calculations
14
+ - plotly-based fan charts and diagnostic plots
15
+ - highly flexible, and as simple as possible (but no more)
16
+ - functional paradigm
17
+
18
+ Requirements:
19
+ - python >= 3.11
20
+ - numpy >= 2.2.0
21
+ - scipy >= 1.16.0
22
+ - pandas >= 2.2.0 (pandas 2.2+ and 3.x are both supported)
23
+ - xarray >= 2025.4.0
24
+
25
+ For optional functionality, additional packages are needed:
26
+ - plotting: plotly (`pip install "funcsim[plotting]"`); kaleido for static image export
27
+
28
+ Additionally, to run the tests and build the docs:
29
+ - pytest
30
+ - sphinx, sphinx-autodoc-typehints (`pip install "funcsim[docs]"`)
31
+
32
+ ### installation
33
+ ```bash
34
+ pip install funcsim
35
+ ```
36
+
37
+ ### building html docs
38
+ From the top-level funcsim directory...
39
+ ```bash
40
+ sphinx-build -W -b html docs/source/ docs/build/
41
+ ```
42
+
43
+ ### running tests
44
+ From the top-level funcsim directory...
45
+ ```bash
46
+ python3 -m pytest
47
+ ```
@@ -46,6 +46,6 @@ def version():
46
46
  Returns
47
47
  -------
48
48
  str
49
- The version string of the package (e.g., '0.1.5').
49
+ The version string of the package (e.g., '0.2.4').
50
50
  """
51
- return "0.2.2"
51
+ return "0.2.4"
@@ -183,17 +183,20 @@ def simulate(f: Callable[[Generator[int, float, None],
183
183
 
184
184
  Parameters
185
185
  ----------
186
- f : function
187
- Function that performs a single trial in a static simulation or a s
188
- single step through time in a recursive dynamic simulation. Should take
189
- 'ugen' as a first argument in either case, where 'ugen' will be a
190
- generator that emits standard uniform draws (or standard normal draws,
191
- if `stdnorm` is True) that will be passed to f by ``simulate``.
192
- In the case of a recursive dynamic simulation that employs past values,
193
- f should take 'data' as a second argument, where this will be a type of
194
- array that is also provided by ``simulate.`` This function should return
195
- a dict with variable names (as strings) as keys and values for those
196
- variables (as floats) as values.
186
+ f : callable
187
+ Function that performs a single trial in a static simulation, or a
188
+ single step through time in a recursive-dynamic simulation. Its first
189
+ argument (conventionally ``ugen``) receives a generator that emits
190
+ independent standard uniform draws (or standard normal draws, if
191
+ `stdnorm` is True); obtain each draw with ``next(ugen)``. If `f`
192
+ takes a second argument (conventionally ``hist``), it receives a
193
+ per-trial history object whose ``recall(varname, lag)`` method returns
194
+ the value of a variable `lag` steps earlier; see
195
+ :class:`funcsim.rdarrays.RDdata`. `f` must return a dict with
196
+ variable names (strings) as keys and floats as values. The number of
197
+ times `f` calls ``next(ugen)`` must be the same in every trial and
198
+ step, because draws are pre-allocated across trials for stratified
199
+ sampling.
197
200
  ntrials : int, optional
198
201
  The number of trials to perform. Default is 500.
199
202
  nsteps : int, optional
@@ -207,12 +210,14 @@ def simulate(f: Callable[[Generator[int, float, None],
207
210
  Use multiple processes/cores for the simulation. Default is False.
208
211
  When True, `f` must be picklable (e.g., defined at the top level of
209
212
  a module, not inside another function), because worker processes
210
- are spawned on most platforms.
213
+ are spawned on most platforms. For the same reason, a script that
214
+ calls ``simulate(..., multi=True)`` must guard the call with
215
+ ``if __name__ == "__main__":``.
211
216
  seed : int, optional
212
217
  Seed for pseudo-random number generation. Default is 6.
213
- stdnorm : book, optional
214
- If False, ``next(draw)`` within `trialf` will return standard uniform
215
- random draws. If True, ``next(draw)`` will return standard normal draws.
218
+ stdnorm : bool, optional
219
+ If False, ``next(ugen)`` within `f` returns standard uniform random
220
+ draws. If True, ``next(ugen)`` returns standard normal draws.
216
221
  Default is False.
217
222
  sampling : {'lh', 'mc'}, optional
218
223
  If 'lh', Latin Hypercube sampling is employed. If 'mc', simple
@@ -221,7 +226,22 @@ def simulate(f: Callable[[Generator[int, float, None],
221
226
  Returns
222
227
  -------
223
228
  xarray.DataArray
224
- 3-D xarray.DataArray with dimensions 'trials', 'variables', and 'steps'.
229
+ 3-D xarray.DataArray with dimensions 'trials', 'variables', and
230
+ 'steps'. The 'steps' coordinate continues the index of `hist0` (or
231
+ counts from 0 when `hist0` is not given), and includes any historical
232
+ steps from `hist0` ahead of the `nsteps` simulated steps.
233
+
234
+ Raises
235
+ ------
236
+ ValueError
237
+ If `hist0` is malformed, `f` is not callable or takes more than two
238
+ arguments, `f` does not return a dict keyed by strings, or `sampling`
239
+ is not one of 'lh' or 'mc'.
240
+ RuntimeError
241
+ If `f` consumes a different number of draws in some trial or step
242
+ than it did when first probed.
243
+ funcsim.rdarrays.MissingValue
244
+ If `f` recalls a lagged value that is not available.
225
245
  """
226
246
  if hist0 is not None:
227
247
  _checkhist0(hist0)
@@ -315,7 +315,7 @@ def cpt(utilFunc: Callable,
315
315
  Sequence of possible stochastic outcomes.
316
316
  refOutcome : float
317
317
  Reference point for gains and losses.
318
- probabilities : float or Iterable, optional
318
+ probabilities : Iterable of float, optional
319
319
  Probabilities for each outcome. If None, outcomes are assumed
320
320
  equally likely.
321
321
  precision : float, optional
@@ -436,7 +436,7 @@ def cptBV(outcomes: Iterable,
436
436
  Sequence of possible stochastic outcomes.
437
437
  refOutcome : float
438
438
  Reference point for gains and losses.
439
- probabilities : float or Iterable, optional
439
+ probabilities : Iterable of float, optional
440
440
  Probabilities for each outcome. If None, outcomes are assumed equally
441
441
  likely.
442
442
 
@@ -191,12 +191,17 @@ class MvKde():
191
191
  Parameters
192
192
  ----------
193
193
  data : ArrayLike
194
- Input data array of with variables in columns and observations
194
+ Input data array with variables in columns and observations
195
195
  in rows.
196
196
  bw : str or ArrayLike, optional
197
197
  Bandwidth selection method ('scott' or 'silverman'), or a K-by-K
198
198
  bandwidth covariance matrix in the units of the data.
199
199
  Default is 'scott'.
200
+
201
+ Notes
202
+ -----
203
+ Each call to :meth:`draw` consumes K + 1 values from ``ugen``, where K
204
+ is the number of variables.
200
205
  """
201
206
  def __init__(self,
202
207
  data: conversions.ArrayLike,
@@ -287,8 +292,14 @@ class MvNorm():
287
292
  Parameters
288
293
  ----------
289
294
  data : ArrayLike
290
- Input data array of with variables in columns and observations
295
+ Input data array with variables in columns and observations
291
296
  in rows.
297
+
298
+ Notes
299
+ -----
300
+ Each call to :meth:`draw` consumes K values from ``ugen``, where K is
301
+ the number of variables. A warning is issued for any variable whose
302
+ Shapiro-Wilk test rejects normality at the 5% level.
292
303
  """
293
304
  def __init__(self,
294
305
  data: conversions.ArrayLike,
@@ -330,11 +341,12 @@ class MvNorm():
330
341
  Returns
331
342
  -------
332
343
  pd.Series
333
- A pandas Series representing a joint draw from the KDE. The index
334
- values are the variable names, and the values are the random
335
- values. If no variable names were provided in the input data,
344
+ A pandas Series representing a joint draw from the multivariate
345
+ normal distribution. The index values are the variable names,
346
+ and the values are the random values. If no variable names were
347
+ provided in the input data,
336
348
  the variables will be named 'v0', 'v1', ..., reflecting the
337
- oreder of the columns in the input data.
349
+ order of the columns in the input data.
338
350
  """
339
351
  uvec = [next(ugen) for i in range(self._K)]
340
352
  retA = self._mu + np.dot(self._A, stats.norm.ppf(uvec))
@@ -353,10 +365,15 @@ class CopulaGauss():
353
365
  columns and observations in rows. That is, each column
354
366
  represents the result of applying the fitted CDF of some marginal
355
367
  distribution to the raw data for that variable. The
356
- values in each column should be in the range [0, 1]. The parameters
357
- are fit using the method of moments. If the sample covariance
358
- matrix is not positive definite, the Higham method is used to
359
- calculate the nearest positive definite matrix.
368
+ values in each column should be in the range (0, 1). The correlation
369
+ matrix is fit using the method of moments on the normal scores of
370
+ the pseudo-observations. If it is not positive definite, the Higham
371
+ method is used to calculate the nearest positive definite matrix.
372
+
373
+ Notes
374
+ -----
375
+ Each call to :meth:`draw` consumes K values from ``ugen``, where K is
376
+ the number of variables.
360
377
  """
361
378
 
362
379
  def __init__(self,
@@ -412,7 +429,7 @@ class CopulaGauss():
412
429
  standard uniform draws are the values in the Series.
413
430
  If no variable names were provided in the input data,
414
431
  the variables will be named 'v0', 'v1', ..., reflecting the
415
- oreder of the columns in the input data.
432
+ order of the columns in the input data.
416
433
 
417
434
  """
418
435
  uvec = [next(ugen) for i in range(self._K)]
@@ -432,9 +449,14 @@ class CopulaStudent():
432
449
  columns and observations in rows. That is, each column
433
450
  represents the result of applying the fitted CDF of some marginal
434
451
  distribution to the raw data for that variable. The
435
- values in each column should be in the range [0, 1]. The correlation
452
+ values in each column should be in the range (0, 1). The correlation
436
453
  matrix is fit by pairwise Kendall's-tau inversion, and the degrees
437
- of freedom are then fit by profile maximum likelihood.
454
+ of freedom are then fit by profile maximum pseudo-likelihood.
455
+
456
+ Notes
457
+ -----
458
+ Each call to :meth:`draw` consumes K + 1 values from ``ugen``, where K
459
+ is the number of variables.
438
460
  """
439
461
 
440
462
  def __init__(self,
@@ -477,7 +499,7 @@ class CopulaStudent():
477
499
  standard uniform draws are the values in the Series.
478
500
  If no variable names were provided in the input data,
479
501
  the variables will be named 'v0', 'v1', ..., reflecting the
480
- oreder of the columns in the input data.
502
+ order of the columns in the input data.
481
503
 
482
504
  """
483
505
  uvec = [next(ugen) for i in range(self._K)]
@@ -500,10 +522,18 @@ class CopulaClayton():
500
522
  columns and observations in rows. That is, each column
501
523
  represents the result of applying the fitted CDF of some marginal
502
524
  distribution to the raw data for that variable. The
503
- values in each column should be in the range [0, 1]. Parameters are
504
- fit using maximum likelihood. This implementation accomodates
525
+ values in each column should be in the range (0, 1). The dependence
526
+ parameter theta is fit by maximum pseudo-likelihood, starting from
527
+ the Kendall's-tau inversion estimate. This implementation accommodates
505
528
  only positive dependence, so the fitted value for theta is
506
529
  constrained to be > 0.
530
+
531
+ Notes
532
+ -----
533
+ Each call to :meth:`draw` consumes K + 1 values from ``ugen``, where K
534
+ is the number of variables. If the data exhibit negative dependence
535
+ (mean pairwise Kendall's tau <= 0), theta is set to its minimum
536
+ (near independence) and a warning is issued.
507
537
  """
508
538
 
509
539
  def __init__(self,
@@ -525,7 +555,7 @@ class CopulaClayton():
525
555
  (self._theta, taub, clamped) = copfit.fit_clayton(self._data)
526
556
  if clamped:
527
557
  warnings.warn(f"The Clayton copula implementation in funcsim "
528
- f"accomodates only positive dependence, but the "
558
+ f"accommodates only positive dependence, but the "
529
559
  f"data exhibit negative dependence (mean pairwise "
530
560
  f"Kendall's tau = {taub:.3f}). A theta value of "
531
561
  f"{copfit.THETA_MIN_CLAYTON} is being used rather "
@@ -557,7 +587,7 @@ class CopulaClayton():
557
587
  standard uniform draws are the values in the Series.
558
588
  If no variable names were provided in the input data,
559
589
  the variables will be named 'v0', 'v1', ..., reflecting the
560
- oreder of the columns in the input data.
590
+ order of the columns in the input data.
561
591
 
562
592
  """
563
593
  # floor the gamma frailty: for large theta the shape parameter is
@@ -582,10 +612,18 @@ class CopulaGumbel():
582
612
  columns and observations in rows. That is, each column
583
613
  represents the result of applying the fitted CDF of some marginal
584
614
  distribution to the raw data for that variable. The
585
- values in each column should be in the range [0, 1]. Parameters are
586
- fit using maximum likelihood. This implementation accomodates
615
+ values in each column should be in the range (0, 1). The dependence
616
+ parameter theta is fit by maximum pseudo-likelihood, starting from
617
+ the Kendall's-tau inversion estimate. This implementation accommodates
587
618
  only positive dependence, so the fitted value for theta is
588
619
  constrained to be > 1.0.
620
+
621
+ Notes
622
+ -----
623
+ Each call to :meth:`draw` consumes K + 2 values from ``ugen``, where K
624
+ is the number of variables. If the data exhibit negative dependence
625
+ (mean pairwise Kendall's tau <= 0), theta is set to its minimum
626
+ (near independence) and a warning is issued.
589
627
  """
590
628
 
591
629
  def __init__(self,
@@ -607,7 +645,7 @@ class CopulaGumbel():
607
645
  (self._theta, taub, clamped) = copfit.fit_gumbel(self._data)
608
646
  if clamped:
609
647
  warnings.warn(f"The Gumbel copula implementation in funcsim "
610
- f"accomodates only positive dependence, but the "
648
+ f"accommodates only positive dependence, but the "
611
649
  f"data exhibit negative dependence (mean pairwise "
612
650
  f"Kendall's tau = {taub:.3f}). A theta value of "
613
651
  f"(approximately) 1.0 is being used rather than a "
@@ -639,7 +677,7 @@ class CopulaGumbel():
639
677
  standard uniform draws are the values in the Series.
640
678
  If no variable names were provided in the input data,
641
679
  the variables will be named 'v0', 'v1', ..., reflecting the
642
- oreder of the columns in the input data.
680
+ order of the columns in the input data.
643
681
 
644
682
  """
645
683
  gamma = math.cos(0.5 * math.pi / self._theta)**self._theta
@@ -662,10 +700,18 @@ class CopulaFrank():
662
700
  columns and observations in rows. That is, each column
663
701
  represents the result of applying the fitted CDF of some marginal
664
702
  distribution to the raw data for that variable. The
665
- values in each column should be in the range [0, 1]. Parameters are
666
- fit using maximum likelihood. This implementation accomodates
703
+ values in each column should be in the range (0, 1). The dependence
704
+ parameter theta is fit by maximum pseudo-likelihood, starting from
705
+ the Kendall's-tau inversion estimate. This implementation accommodates
667
706
  only positive dependence, so the fitted value for theta is
668
707
  constrained to be > 0.
708
+
709
+ Notes
710
+ -----
711
+ Each call to :meth:`draw` consumes K + 2 values from ``ugen``, where K
712
+ is the number of variables. If the data exhibit negative dependence
713
+ (mean pairwise Kendall's tau <= 0), theta is set to its minimum
714
+ (near independence) and a warning is issued.
669
715
  """
670
716
 
671
717
  def __init__(self,
@@ -687,7 +733,7 @@ class CopulaFrank():
687
733
  (self._theta, taub, clamped) = copfit.fit_frank(self._data)
688
734
  if clamped:
689
735
  warnings.warn(f"The Frank copula implementation in funcsim "
690
- f"accomodates only positive dependence, but the "
736
+ f"accommodates only positive dependence, but the "
691
737
  f"data exhibit negative dependence (mean pairwise "
692
738
  f"Kendall's tau = {taub:.3f}). A theta value of "
693
739
  f"{copfit.THETA_MIN_FRANK} is being used rather "
@@ -716,7 +762,7 @@ class CopulaFrank():
716
762
  standard uniform draws are the values in the Series.
717
763
  If no variable names were provided in the input data,
718
764
  the variables will be named 'v0', 'v1', ..., reflecting the
719
- oreder of the columns in the input data.
765
+ order of the columns in the input data.
720
766
 
721
767
  """
722
768
  # Generate d uniform random variables