Lhsmdu
This is an implementation of Deutsch and Deutsch, "Latin hypercube sampling with multidimensional uniformity", Journal of Statistical Planning and Inference 142 (2012) , 763-772
Install / Use
/learn @sahilm89/LhsmduREADME
LHS-MDU
Installation
You can install lhsmdu using pip::
$ pip install lhsmdu
Alternatively, you can clone on github and then install the package locally::
$ git clone https://github.com/sahilm89/lhsmdu
$ cd lhsmdu
$ python setup.py install --user # for this user only.
or::
$ pip install git+https://github.com/sahilm89/lhsmdu --user
Basics
This is a package for generating latin hypercube samples with multi-dimensional uniformity.
To use, simply do::
>>> import lhsmdu
>>> k = lhsmdu.sample(2, 20) # Latin Hypercube Sampling with multi-dimensional uniformity
This will generate a nested list with 2 variables, with 20 samples each.
To plot and see the difference between Monte Carlo and LHS-MDU sampling for a 2 dimensional system::
>>> l = lhsmdu.createRandomStandardUniformMatrix(2, 20) # Monte Carlo sampling
>>> k = lhsmdu.sample(2, 20) # Latin Hypercube Sampling with multi-dimensional uniformity
>>> k = np.array(k)
>>> l = np.array(l)
>>> import matplotlib.pyplot as plt
>>> fig = plt.figure()
>>> ax = fig.gca()
>>> ax.set_xticks(numpy.arange(0,1,0.1))
>>> ax.set_yticks(numpy.arange(0,1,0.1))
>>> plt.scatter(k[0], k[1], color="g", label="LHS-MDU")
>>> plt.scatter(l[0], l[1], color="r", label="MC")
>>> plt.grid()
>>> plt.show()
You can use the strata generated by the algorithm to sample again, if you so desire. For this, you can do::
>>> m = lhsmdu.resample()
>>> n = lhsmdu.resample()
>>> o = lhsmdu.resample()
This will again generate the same number of samples as before, a nested list with 2 variables, with 20 samples each.
You can plot these together and see the sampling from the strata:: >>> m = np.array(m) >>> n = np.array(n) >>> o = np.array(o)
>>> fig = plt.figure()
>>> ax = fig.gca()
>>> ax.set_xticks(numpy.arange(0,1,0.1))
>>> ax.set_yticks(numpy.arange(0,1,0.1))
>>> plt.title("LHS-MDU")
>>> plt.scatter(k[0], k[1], c="g", label="sample 1")
>>> plt.scatter(m[0], m[1], c="r", label="resample 2")
>>> plt.scatter(n[0], n[1], c="b", label="resample 3")
>>> plt.scatter(o[0], o[1], c="y", label="resample 4")
>>> plt.grid()
>>> plt.show()
Alternatively, you can choose to get new strata each time, and see the sampling hence::
>>> p = lhsmdu.sample(2, 20) # Latin Hypercube Sampling with multi-dimensional uniformity
>>> q = lhsmdu.sample(2, 20) # Latin Hypercube Sampling with multi-dimensional uniformity
>>> r = lhsmdu.sample(2, 20) # Latin Hypercube Sampling with multi-dimensional uniformity
>>> p = np.array(p)
>>> q = np.array(q)
>>> r = np.array(r)
>>> fig = plt.figure()
>>> ax = fig.gca()
>>> ax.set_xticks(numpy.arange(0,1,0.1))
>>> ax.set_yticks(numpy.arange(0,1,0.1))
>>> plt.title("LHS-MDU")
>>> plt.scatter(k[0], k[1], c="g", label="sample 1")
>>> plt.scatter(p[0], p[1], c="r", label="sample 2")
>>> plt.scatter(q[0], q[1], c="b", label="sample 3")
>>> plt.scatter(r[0], r[1], c="y", label="sample 4")
>>> plt.grid()
>>> plt.show()
===========================================================================================
Changing the random seed
You will notice that the strata generated are the same each time you run the program again. This is because the random seed is a global constant set to a default value by design, so that simulations can be replicated. In order to change this behavior, you can set a new random seed using the following code::
>>> randSeed = 11 # random number of choice
>>> lhsmdu.setRandomSeed(randSeed) # Latin Hypercube Sampling with multi-dimensional uniformity
>>> lhsmdu.sample(2, 20) # Latin Hypercube Sampling with multi-dimensional uniformity
Alternatively, you can also set the seed by using sample with a new seed::
>>> lhsmdu.sample(2, 20, randomSeed=randSeed) # Latin Hypercube Sampling with multi-dimensional uniformity
To change the random seed in every run, you can set on top of the program::
>>> lhsmdu.setRandomSeed(None)
Sampling from arbitrary CDFs
After uniformly distributed samples have been generated from LHSMDU, you can convert these to samples from arbitrary distributions using inverse tranform sampling. In this, the CDF [0,1] of the distribution of interest is inverted, and then data points corresponding to the uniformly sampled points are picked up. To do this, you must have a rv_contiuous or rv_discrete distribution instance taken from scipy.stats. You can also use frozen distributions (after setting loc and scale parameters). Following is an example for normal distribution.::
>>> import scipy.stats.distributions as ssd
>>> p = ssd.norm
>>> new_samples = lhsmdu.inverseTransformSample(p, k[0])
>>> plt.hist(new_samples[0])
>>> plt.show()
Citing this repository
To cite, please cite both the repository using DOI https://dx.doi.org/10.5281/zenodo.2578780 and the original paper from Deutsch and Deutsch: http://dx.doi.org/10.1016%2Fj.jspi.2011.09.016.
Related Skills
node-connect
339.1kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
claude-opus-4-5-migration
83.8kMigrate prompts and code from Claude Sonnet 4.0, Sonnet 4.5, or Opus 4.1 to Opus 4.5
frontend-design
83.8kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
model-usage
339.1kUse CodexBar CLI local cost usage to summarize per-model usage for Codex or Claude, including the current (most recent) model or a full model breakdown. Trigger when asked for model-level usage/cost data from codexbar, or when you need a scriptable per-model summary from codexbar cost JSON.
