Skip to content

Commit cd5cbf0

Browse files
authored
Merge pull request #41 from sandialabs/40-normalized-pc
implemented normalized LU and PC, as well as quadratic Genz function
2 parents 4393e29 + 782c668 commit cd5cbf0

File tree

2 files changed

+54
-6
lines changed

2 files changed

+54
-6
lines changed

src/pytuq/func/genz.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,36 @@ def intgl(self):
6666
return np.cos(2. * np.pi * self.shift + 0.5 * np.sum(self.weights) ) * \
6767
np.prod(2. * np.sin(0.5 * self.weights) / self.weights)
6868

69+
class GenzQuadOscillatory(GenzBase):
70+
r"""Genz Quadratic Oscillatory function
71+
72+
.. math::
73+
f(x) = \cos\left(2 \pi s + w^T x^2 \right)
74+
75+
Default values are :math:`s = 0` and :math:`w = [1.0]`.
76+
77+
"""
78+
def __init__(self, shift=0.0, weights=[1.0], domain=None,
79+
name='GenzQuadOscillatory'):
80+
super().__init__(weights=weights, domain=domain, name=name)
81+
self.shift = shift
82+
83+
def __call__(self, x):
84+
85+
self.checkDim(x)
86+
87+
y = np.cos(2. * np.pi * self.shift + np.dot(x**2, self.weights))
88+
89+
return y.reshape(-1,1)
90+
91+
def grad(self, x):
92+
self.checkDim(x)
93+
94+
grad = np.empty((x.shape[0], self.outdim, self.dim))
95+
for i in range(x.shape[1]):
96+
grad[:, 0, i] = -2.*self.weights[i]*x[:, i]*np.sin(2. * np.pi * self.shift + np.dot(x**2, self.weights))
97+
98+
return grad
6999

70100
class GenzSum(GenzBase):
71101
r"""Genz Summation function

src/pytuq/rv/pcrv.py

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -738,15 +738,15 @@ class PC1d():
738738
domain (np.ndarray): A 1d array of size :math:`2` indicating the domain of definition.
739739
p0 (callable): The 0th order basis evaluator from 1d np.ndarray to 1d np.ndarray.
740740
p1 (callable): The 1rd order basis evaluator from 1d np.ndarray to 1d np.ndarray.
741-
pctype (str): The PC type. Only 'LU' and 'HG' are implemented.
741+
pctype (str): The PC type. Only 'LU', 'nLU', 'HG' and 'nHG' are implemented.
742742
sample (callable): int->float sampling function, where the input is a number of samples requested, and the output is an 1d array of the corresponding size.
743743
"""
744744

745745
def __init__(self, pctype='LU'):
746746
"""Initialization.
747747
748748
Args:
749-
pctype (str): The PC type. Only 'LU' and 'HG' are implemented. Defaults to 'LU'.
749+
pctype (str): The PC type. Only 'LU', 'nLU', 'HG' and 'nHG'are implemented. Defaults to 'LU'.
750750
"""
751751
self.pctype = pctype
752752
if self.pctype == 'LU':
@@ -756,13 +756,27 @@ def __init__(self, pctype='LU'):
756756
self.b = lambda n: -n / (n + 1.)
757757
self.sample = lambda m: 2.*np.random.rand(m)-1.
758758
self.domain = np.array([-1., 1.])
759+
elif self.pctype == 'nLU':
760+
self.p0 = lambda x: np.ones_like(x)
761+
self.p1 = lambda x: x * np.sqrt(3.)
762+
self.a = lambda n: np.sqrt((2.*n+3.)/(2.*n+1.)) * (2. * n + 1.) / (n + 1.)
763+
self.b = lambda n: - np.sqrt((2.*n+3.)/(2.*n-1.)) * n / (n + 1.)
764+
self.sample = lambda m: 2.*np.random.rand(m)-1.
765+
self.domain = np.array([-1., 1.])
759766
elif self.pctype == 'HG':
760767
self.p0 = lambda x: np.ones_like(x)
761768
self.p1 = lambda x: x
762769
self.a = lambda n: 1.
763770
self.b = lambda n: -n
764771
self.sample = lambda m: np.random.randn(m)
765772
self.domain = np.array([-np.inf, np.inf])
773+
elif self.pctype == 'nHG':
774+
self.p0 = lambda x: np.ones_like(x)
775+
self.p1 = lambda x: x
776+
self.a = lambda n: 1./(n+1.)
777+
self.b = lambda n: -1./(n+1.)
778+
self.sample = lambda m: np.random.randn(m)
779+
self.domain = np.array([-np.inf, np.inf])
766780
else:
767781
print(f'PC1d type {self.pctype} is not recognized. Exiting.')
768782
sys.exit()
@@ -799,11 +813,11 @@ def germCdf(self, x):
799813
Returns:
800814
np.ndarray: A size :math:`M` 1d array of outputs containing CDF evaluations.
801815
"""
802-
if self.pctype == 'LU':
816+
if self.pctype == 'LU' or self.pctype == 'nLU':
803817
cdf = (x+1.)/2.
804818
cdf[cdf>1]=1.0
805819
cdf[cdf<=-1]=0.0
806-
elif self.pctype == 'HG':
820+
elif self.pctype == 'HG' or self.pctype == 'nHG':
807821
cdf = (1.0 + erf(x / np.sqrt(2.0))) / 2.0
808822
else:
809823
print(f'PC1d type {self.pctype} is not recognized. Exiting.')
@@ -820,9 +834,9 @@ def germSample(self, nsam):
820834
Returns:
821835
np.ndarray: A 1d array of size :math:`M` containing the germ samples.
822836
"""
823-
if self.pctype == 'LU':
837+
if self.pctype == 'LU' or self.pctype == 'nLU':
824838
germ_sam = np.random.rand(nsam)*2.0-1.0
825-
elif self.pctype == 'HG':
839+
elif self.pctype == 'HG' or self.pctype == 'nHG':
826840
germ_sam = np.random.randn(nsam)
827841
else:
828842
print(f'PC1d type {self.pctype} is not recognized. Exiting.')
@@ -841,11 +855,15 @@ def normsq(self, ord):
841855
"""
842856
if self.pctype == 'LU':
843857
val = 1./(2.*float(ord)+1.)
858+
elif self.pctype == 'nLU':
859+
val = 1.0
844860
elif self.pctype == 'HG':
845861
if ord == 0:
846862
val = 1.0
847863
else:
848864
val = float(np.prod(np.arange(1, ord+1)))
865+
elif self.pctype == 'nHG':
866+
val = 1.0
849867
else:
850868
print(f'PC1d type {self.pctype} is not recognized. Exiting.')
851869
sys.exit()

0 commit comments

Comments
 (0)