mosaictools 0.1.0__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.
- mosaictools-0.1.0/PKG-INFO +17 -0
- mosaictools-0.1.0/README.md +2 -0
- mosaictools-0.1.0/mosaictools/__init__.py +2 -0
- mosaictools-0.1.0/mosaictools/distributions.py +115 -0
- mosaictools-0.1.0/mosaictools/gpc_functions.py +15 -0
- mosaictools-0.1.0/mosaictools/gpc_surrogate.py +150 -0
- mosaictools-0.1.0/mosaictools/main.py +937 -0
- mosaictools-0.1.0/mosaictools/multiindex.py +100 -0
- mosaictools-0.1.0/mosaictools/polysys.py +203 -0
- mosaictools-0.1.0/mosaictools/simparameter.py +60 -0
- mosaictools-0.1.0/mosaictools/simparameter_set.py +134 -0
- mosaictools-0.1.0/mosaictools.egg-info/PKG-INFO +17 -0
- mosaictools-0.1.0/mosaictools.egg-info/SOURCES.txt +16 -0
- mosaictools-0.1.0/mosaictools.egg-info/dependency_links.txt +1 -0
- mosaictools-0.1.0/mosaictools.egg-info/requires.txt +5 -0
- mosaictools-0.1.0/mosaictools.egg-info/top_level.txt +1 -0
- mosaictools-0.1.0/setup.cfg +4 -0
- mosaictools-0.1.0/setup.py +27 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: mosaictools
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Surrogate modelling of modal properties using MOSAIC method
|
|
5
|
+
Home-page: https://github.com/blazkurent/mosaictools/
|
|
6
|
+
Author: Blaž Kurent
|
|
7
|
+
Author-email: blaz.kurent@fgg.uni-lj.si
|
|
8
|
+
License: UNKNOWN
|
|
9
|
+
Description: # mosaictools
|
|
10
|
+
Python library for surrogate modelling of modal properties according to the Mode-Shape-Adapted Input parameter domain Curring (MOSAIC) method.
|
|
11
|
+
|
|
12
|
+
Platform: UNKNOWN
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Development Status :: 3 - Alpha
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# from polysys import LegendrePolynomials
|
|
2
|
+
import numpy as np
|
|
3
|
+
from scipy.stats.qmc import Halton as ghalton
|
|
4
|
+
|
|
5
|
+
# class Distributin():
|
|
6
|
+
# def sample(self, n):
|
|
7
|
+
# xi = np.random.rand(n)
|
|
8
|
+
# return self.invcdf(xi)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class UniformDistribution():
|
|
12
|
+
def __init__(self, a=0, b=1):
|
|
13
|
+
self.a = a
|
|
14
|
+
self.b = b
|
|
15
|
+
|
|
16
|
+
def __repr__(self):
|
|
17
|
+
return 'U({}, {})'.format(self.a, self.b)
|
|
18
|
+
|
|
19
|
+
def pdf(self, x):
|
|
20
|
+
a = self.a
|
|
21
|
+
b = self.b
|
|
22
|
+
y = 1 / (b - a) * np.ones(x.shape)
|
|
23
|
+
y[x < a] = 0
|
|
24
|
+
y[x > b] = 0
|
|
25
|
+
return y
|
|
26
|
+
|
|
27
|
+
def cdf(self, x):
|
|
28
|
+
a = self.a
|
|
29
|
+
b = self.b
|
|
30
|
+
y = (x - a) / (b - a)
|
|
31
|
+
y[x < a] = 0
|
|
32
|
+
y[x > b] = 1
|
|
33
|
+
return y
|
|
34
|
+
|
|
35
|
+
def invcdf(self, y):
|
|
36
|
+
a = self.a
|
|
37
|
+
b = self.b
|
|
38
|
+
x = np.full(y.shape, np.nan)
|
|
39
|
+
ind = (y >= 0) & (y <= 1)
|
|
40
|
+
|
|
41
|
+
x[ind] = a + (b - a) * y[ind]
|
|
42
|
+
return x
|
|
43
|
+
|
|
44
|
+
def sample(self, n, method='MC'):
|
|
45
|
+
if method == 'MC':
|
|
46
|
+
xi = np.random.rand(n)
|
|
47
|
+
elif method == 'QMC':
|
|
48
|
+
gen = ghalton.Halton(1)
|
|
49
|
+
xi = np.array(gen.get(n)) # dummy generation to avoid sample point q = 0
|
|
50
|
+
return self.invcdf(xi)
|
|
51
|
+
|
|
52
|
+
def moments(self):
|
|
53
|
+
return self.mean(), self.var(), self.skew(), self.kurt()
|
|
54
|
+
|
|
55
|
+
def mean(self):
|
|
56
|
+
return 0.5 * (self.a + self.b)
|
|
57
|
+
|
|
58
|
+
def var(self):
|
|
59
|
+
return (self.b - self.a) ** 2 / 12
|
|
60
|
+
|
|
61
|
+
def skew(self):
|
|
62
|
+
return 0
|
|
63
|
+
|
|
64
|
+
def kurt(self):
|
|
65
|
+
return -6 / 5
|
|
66
|
+
|
|
67
|
+
def translate(self, shift, scale):
|
|
68
|
+
m = (self.a + self.b) / 2
|
|
69
|
+
v = scale * (self.b - self.a) / 2
|
|
70
|
+
|
|
71
|
+
self.a = m + shift - v
|
|
72
|
+
self.b = m + shift + v
|
|
73
|
+
|
|
74
|
+
def get_base_dist(self):
|
|
75
|
+
dist_germ = UniformDistribution(-1, 1)
|
|
76
|
+
return dist_germ
|
|
77
|
+
|
|
78
|
+
def base2dist(self, y):
|
|
79
|
+
return self.mean() + y * (self.b - self.a) / 2
|
|
80
|
+
|
|
81
|
+
def dist2base(self, x):
|
|
82
|
+
return (x - self.mean()) * 2 / (self.b - self.a)
|
|
83
|
+
|
|
84
|
+
# def orth_polysys(self, normalized):
|
|
85
|
+
# if self.a == -1 & self.b == 1:
|
|
86
|
+
# if normalized:
|
|
87
|
+
# polysys = LegendrePolynomials()
|
|
88
|
+
# else:
|
|
89
|
+
# polysys = LegendrePolynomials().normalized()
|
|
90
|
+
# else:
|
|
91
|
+
# polysys = []
|
|
92
|
+
# return polysys
|
|
93
|
+
|
|
94
|
+
def orth_polysys_syschar(self, normalized):
|
|
95
|
+
if self.a == -1 and self.b == 1:
|
|
96
|
+
if normalized:
|
|
97
|
+
polysys_char = 'p'
|
|
98
|
+
else:
|
|
99
|
+
polysys_char = 'P'
|
|
100
|
+
else:
|
|
101
|
+
polysys_char = []
|
|
102
|
+
return polysys_char
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
if __name__ == "__main__":
|
|
106
|
+
dist = UniformDistribution(-2,2)
|
|
107
|
+
print(dist.moments())
|
|
108
|
+
print(dist.pdf(np.array([-3,-2,-1,0,1,2,3])))
|
|
109
|
+
print(dist.cdf(np.array([-3, -2, -1, 0, 1, 2, 3])))
|
|
110
|
+
print(dist.get_base_dist().a, dist.get_base_dist().b)
|
|
111
|
+
print(dist.dist2base(np.array([-3, -2, -1, 0, 1, 2, 3])))
|
|
112
|
+
print(dist.base2dist(np.array([-2, -1, -0.5, 0, 0.5, 1, 2])))
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from polysys import *
|
|
2
|
+
|
|
3
|
+
def syschar_to_polysys(syschar):
|
|
4
|
+
poly_dict = {'H': HermitePolynomials,
|
|
5
|
+
'h': HermitePolynomials.normalized(),
|
|
6
|
+
'P': LegendrePolynomials,
|
|
7
|
+
'p': LegendrePolynomials.normalized(),
|
|
8
|
+
'T': ChebyshevTPolynomials,
|
|
9
|
+
't': ChebyshevTPolynomials.normalized(),
|
|
10
|
+
'U': ChebyshevUPolynomials,
|
|
11
|
+
'u': ChebyshevUPolynomials.normalized(),
|
|
12
|
+
'L': LaguerrePolynomials,
|
|
13
|
+
'l': LaguerrePolynomials.normalized(),
|
|
14
|
+
'M': Monomials}
|
|
15
|
+
return poly_dict[syschar]
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
from multiindex import *
|
|
3
|
+
from gpc_functions import syschar_to_polysys
|
|
4
|
+
|
|
5
|
+
# ##########################################################################################
|
|
6
|
+
# GPC SURROGATE MODEL
|
|
7
|
+
# ##########################################################################################
|
|
8
|
+
class GpcSurrogateModel:
|
|
9
|
+
def __init__(self, Q, p=0, I="default", full_tensor=False, **kwargs):
|
|
10
|
+
self.basis = GpcBasis(Q, p=p, I="default", full_tensor=False)
|
|
11
|
+
self.Q = Q
|
|
12
|
+
self.u_i_alpha = []
|
|
13
|
+
|
|
14
|
+
def __repr__(self):
|
|
15
|
+
attrs = vars(self)
|
|
16
|
+
return ', '.join("%s: %s" % item for item in attrs.items())
|
|
17
|
+
|
|
18
|
+
def compute_coeffs_by_regression(self, q_j_k, u_i_k):
|
|
19
|
+
xi_j_k = self.Q.params2germ(q_j_k)
|
|
20
|
+
phi_alpha_k = self.basis.evaluate(xi_j_k)
|
|
21
|
+
u_i_alpha = np.matmul(u_i_k, np.linalg.pinv(phi_alpha_k))
|
|
22
|
+
self.u_i_alpha = u_i_alpha
|
|
23
|
+
|
|
24
|
+
def compute_coeffs_by_projection(self, q_j_k, u_i_k, w_k):
|
|
25
|
+
xi_j_k = self.Q.params2germ(q_j_k)
|
|
26
|
+
phi_alpha_k = self.basis.evaluate(xi_j_k)
|
|
27
|
+
u_i_alpha = np.matmul(u_i_k, np.diag(w_k), phi_alpha_k.transpose())
|
|
28
|
+
self.u_i_alpha = u_i_alpha
|
|
29
|
+
|
|
30
|
+
def predict_response(self, q_j_k):
|
|
31
|
+
xi_j_k = self.Q.params2germ(q_j_k)
|
|
32
|
+
phi_alpha_k = self.basis.evaluate(xi_j_k)
|
|
33
|
+
u_i_j = np.matmul(self.u_i_alpha, phi_alpha_k)
|
|
34
|
+
return u_i_j
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
# ##########################################################################################
|
|
39
|
+
# GPC BASIS
|
|
40
|
+
# ##########################################################################################
|
|
41
|
+
class GpcBasis:
|
|
42
|
+
# ---------------------Initialization---------------------------------------------------
|
|
43
|
+
def __init__(self, Q, p=0, I="default", full_tensor=False, **kwargs):
|
|
44
|
+
m = Q.num_params()
|
|
45
|
+
self.m = m
|
|
46
|
+
|
|
47
|
+
self.syschars = Q.get_gpc_syschars()
|
|
48
|
+
self.p = p
|
|
49
|
+
|
|
50
|
+
if I == "default":
|
|
51
|
+
self.I = multiindex(self.m, p, full_tensor=full_tensor)
|
|
52
|
+
else:
|
|
53
|
+
self.I = I
|
|
54
|
+
|
|
55
|
+
# ---------------------set how gpc looks when printed ---------------------------------------------------
|
|
56
|
+
def __repr__(self):
|
|
57
|
+
attrs = vars(self)
|
|
58
|
+
return ', '.join("%s: %s" % item for item in attrs.items())
|
|
59
|
+
|
|
60
|
+
# ----------------------------------------- size --------------------------------------------------
|
|
61
|
+
def size(self):
|
|
62
|
+
return [self.I.shape]
|
|
63
|
+
|
|
64
|
+
# ----------------------------Evaluate basis functions ---------------------------------------------------
|
|
65
|
+
def evaluate(self, xi, dual=False):
|
|
66
|
+
syschars = self.syschars
|
|
67
|
+
I = self.I
|
|
68
|
+
m = self.m
|
|
69
|
+
M = self.I.shape[0]
|
|
70
|
+
if xi.ndim == 1:
|
|
71
|
+
xi = xi.reshape(-1, 1)
|
|
72
|
+
k = xi.shape[1]
|
|
73
|
+
deg = max(self.I.flatten())
|
|
74
|
+
|
|
75
|
+
p = np.zeros([m, k, deg + 2])
|
|
76
|
+
p[:, :, 0] = np.zeros(xi.shape)
|
|
77
|
+
p[:, :, 1] = np.ones(xi.shape)
|
|
78
|
+
|
|
79
|
+
if len(syschars) == 1:
|
|
80
|
+
polysys = syschar_to_polysys(syschars)
|
|
81
|
+
r = polysys.recur_coeff(syschars, deg)
|
|
82
|
+
for d in range(deg):
|
|
83
|
+
p[:, :, d + 2] = (r[d, 0] + xi * r[d, 1]) * p[:, :, d + 1] - r[d, 2] * p[:, :, d]
|
|
84
|
+
else:
|
|
85
|
+
for j, syschar in enumerate(syschars):
|
|
86
|
+
polysys = syschar_to_polysys(syschar)
|
|
87
|
+
r = polysys.recur_coeff(deg)
|
|
88
|
+
for d in range(deg):
|
|
89
|
+
p[j, :, d + 2] = (r[d, 0] + xi[j, :] * r[d, 1]) * p[j, :, d + 1] - r[d, 2] * p[j, :, d]
|
|
90
|
+
|
|
91
|
+
y_alpha_j = np.ones([M, k])
|
|
92
|
+
for j in range(m):
|
|
93
|
+
y_alpha_j = y_alpha_j * p[j, :, I[:, j] + 1]
|
|
94
|
+
|
|
95
|
+
if dual:
|
|
96
|
+
nrm2 = self.norm(do_sqrt=False)
|
|
97
|
+
y_alpha_j = (y_alpha_j / nrm2.reshape(-1, 1)).transpose()
|
|
98
|
+
return y_alpha_j
|
|
99
|
+
|
|
100
|
+
# ------------------------Compute the norm of the basis functions-----------------------
|
|
101
|
+
def norm(self, do_sqrt=True):
|
|
102
|
+
syschars = self.syschars
|
|
103
|
+
I = self.I
|
|
104
|
+
m = self.m
|
|
105
|
+
M = self.I.shape[0]
|
|
106
|
+
|
|
107
|
+
if syschars == syschars.lower():
|
|
108
|
+
norm_I = np.ones([M, 1])
|
|
109
|
+
return norm_I
|
|
110
|
+
|
|
111
|
+
if len(syschars) == 1:
|
|
112
|
+
# max degree of univariate polynomials
|
|
113
|
+
deg = max(self.I.flatten())
|
|
114
|
+
polysys = syschar_to_polysys(syschars)
|
|
115
|
+
nrm = polysys.sqnorm(range(deg + 1))
|
|
116
|
+
norm2_I = np.prod(nrm[I].reshape(I.shape), axis=1)
|
|
117
|
+
|
|
118
|
+
else:
|
|
119
|
+
norm2_I = np.ones([M])
|
|
120
|
+
for j in range(m):
|
|
121
|
+
deg = max(I[:, j])
|
|
122
|
+
polysys = syschar_to_polysys(syschars[j])
|
|
123
|
+
nrm2 = polysys.sqnorm(np.arange(deg + 1))
|
|
124
|
+
norm2_I = norm2_I * nrm2[I[:, j]]
|
|
125
|
+
if do_sqrt:
|
|
126
|
+
norm_I = np.sqrt(norm2_I)
|
|
127
|
+
else:
|
|
128
|
+
norm_I = norm2_I
|
|
129
|
+
|
|
130
|
+
return norm_I
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
# ##########################################################################################
|
|
134
|
+
# UTILS
|
|
135
|
+
# ##########################################################################################
|
|
136
|
+
|
|
137
|
+
#
|
|
138
|
+
# ##########################################################################################
|
|
139
|
+
# TEST
|
|
140
|
+
# ##########################################################################################
|
|
141
|
+
def main():
|
|
142
|
+
print(multiindex(3, 4))
|
|
143
|
+
gPCE = GpcSurrogateModel('PP', p=3)
|
|
144
|
+
gPCE.basis.norm()
|
|
145
|
+
print(gPCE.basis.evaluate(np.array([np.arange(-1, 1, 0.1)] * 2)))
|
|
146
|
+
print(gPCE)
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
if __name__ == "__main__":
|
|
150
|
+
main()
|