1
#-----------------------------------------------------------------------------
3
# Purpose: Implements the Latin Hypercube Sampling technique as described by
4
# Iman and Conover, 1982, including correlation control both for no
5
# correlation or for a specified correlation matrix for the sampled
8
# Author: Antonio Guilherme Pacheco, Flavio Codeco Coelho
11
# RCS-ID: $Id: lhs.py $
15
#-----------------------------------------------------------------------------
18
Implements the Latin Hypercube Sampling technique as described
19
by Iman and Conover, 1982, including correlation control
20
both for no correlation or for a specified correlation matrix
21
for the sampled parameters
23
from pylab import plot, figure,hist,show
25
import scipy.stats as stats
27
from numpy.linalg import cholesky,inv
31
valid_dists = ['Normal','Triangular','Uniform']
32
def rank_restr(nparms=4, Iter=100, noCorrRestr=True, matCorr=None):
34
Does the correlation control.
36
x=[numpy.arange(1,Iter+1)for i in xrange(nparms)]
39
for i in xrange(nparms):
40
numpy.random.shuffle(x[i])
41
#x.append(numpy.array(random.sample(xrange(1,Iter+1), Iter)))
45
C=numpy.core.numeric.identity(nparms)
47
C=numpy.matrix(matCorr)
48
s0=numpy.arange(1.,Iter+1)/(Iter+1.)
49
s=stats.norm().ppf(s0)
51
for i in xrange(nparms):
52
numpy.random.shuffle(s)
59
Final=S.transpose()*inv(Q).transpose()*P.transpose()
60
for i in xrange(nparms):
61
x.append(stats.stats.rankdata(Final.transpose()[i,]))
64
def sample_cum(Iter=100):
66
Calculates samples on the quantile axis
67
One sample per quantile
69
perc = numpy.arange(0,1,1./Iter)
70
smp = [stats.uniform(i,1./Iter).rvs()[0] for i in perc]
75
def sample_dist(cum, dist='Normal', parms=[0,1]):
77
Return a sample from from the given distribution
78
by inverting the cumulative prob. density function
82
n = stats.norm(parms[0],1./parms[1])
84
elif dist=='Triangular':
85
if len(parms) ==3 and parms[0]<=parms[1]<=parms[2]:
87
scale=parms[2]-parms[0]
88
t = stats.triang((float(parms[1])-loc)/scale,loc=loc,scale=scale)
90
elif dist == 'Uniform':
92
scale = parms[1]-parms[0]
93
d = stats.uniform(loc,scale).ppf(cum)
95
print '%s is an unsupported distribution!'%dist
101
def lhs(Pars, dists, parms, Iter=100, noCorrRestr=True, matCorr=None):
103
Returns tuple of vectors
104
Pars: list of strings with parameter names
105
dists: List of strings with distribution names
107
defaults to no correlation between sampled parameters
110
if len(Pars)==len(dists):
111
indexes=rank_restr(nparms=len(dists), Iter=Iter, noCorrRestr=noCorrRestr, matCorr=matCorr)
112
for i in xrange(len(dists)):
113
v=sample_dist(sample_cum(Iter), dist=dists[i], parms=parms[i])
114
index=map(int,indexes[i]-1)
115
ParsList.append(v[index])
120
if __name__=='__main__':
121
#c=lhs(['Par1', 'Par2', 'Par3'],['Normal','Triangular','Uniform'], [[0,1], [1,5,8], [1,2]],100000)
122
c=lhs(['Par1', 'Par2', 'Par3'],['Normal','Triangular','Uniform'], [[0,1], [1,5,8], [1,2]],10000, noCorrRestr=True)
123
# m=[[1,.3595,-.2822],[.3595,1,-.1024],[-.2822,-.1024,1]]
124
# c=lhs(['Par1', 'Par2', 'Par3'],['Normal','Triangular','Uniform'], [[0,1], [1,5,8], [1,2]],100000, noCorrRestr=False, matCorr=m)
125
print stats.spearmanr(c[0],c[1])
126
print stats.spearmanr(c[0],c[2])
127
print stats.spearmanr(c[1],c[2])
132
#b=sample_dist(a, dist='Triangular', parms=[1,5,8])
135
## print c[0].shape,c[1].shape,c[2].shape
136
## print c[0][0], type(c[0][0])