iam-git / WellMet (public) (License: MIT) (since 2021-08-31) (hash sha1)
WellMet is pure Python framework for spatial structural reliability analysis. Or, more specifically, for "failure probability estimation and detection of failure surfaces by adaptive sequential decomposition of the design domain".
List of commits:
Subject Hash Author Date (UTC)
directory structure changed d67e975a7f4c7b01388f469324f635c74cf17995 Олёш 2020-06-03 21:17:35
Commit d67e975a7f4c7b01388f469324f635c74cf17995 - directory structure changed
Author: Олёш
Author date (UTC): 2020-06-03 21:17
Committer name: Олёш
Committer date (UTC): 2020-06-03 21:23
Parent(s):
Signer:
Signing key:
Signing status: N
Tree: 756e62f26cbf730a8f82af99f655bbedcb75c1ff
File Lines added Lines deleted
IS_stat.py 337 0
__init__.py 1 0
blackbox.py 648 0
f_models.py 394 0
g_models.py 852 0
gp_plot.py 84 0
plot.py 26 0
plotly_plot.py 92 0
reader.py 191 0
samplebox.py 125 0
sball.py 137 0
whitebox.py 601 0
File IS_stat.py added (mode: 100644) (index 0000000..b53080c)
1 #!/usr/bin/env python
2 # coding: utf-8
3
4 """
5 """
6
7
8 import numpy as np
9 import collections # for defaultdict
10 #from scipy import optimize # it was needed for spring solution
11
12
13 # bisect function is taken from somewhere in internet.
14 # StackOverflow, maybe?
15 # Hope it is not big issue.
16 def bisect(f, target, low, high):
17 low, high = float(low), float(high)
18 while low != high:
19 mid = (low + high) / 2
20 f_mid = f(mid)
21 if f_mid == target:
22 return mid
23 elif f_mid > target:
24 high = mid if mid != high else low
25 else:
26 low = mid if mid != low else high
27 return low
28
29
30 class TrueIS:
31 def __init__(self, f, IS_mode='G'):
32 self.f_sample = f()
33 self.series_data = []
34 self.IS_mode = IS_mode
35 self.events = []
36
37 def add_IS_serie(self, sample, events, alpha=1):
38 """
39 alpha is for rejection sampling, not used
40 """
41 self.series_data.append((sample, events, alpha))
42 self.events += events
43 if self.IS_mode == 'R':
44 # jestli máme to právé vzorkovácí rozdělení - tak nemáme čo robiť
45 self.f_sample.add_sample(sample) # smerdží se to po R
46 # w like weights
47 #wt.w = to_sample.pdf_R / wt.h.pdf_R
48 else: #IS_mode == 'G':
49 # tady musíme provést jeden trik
50 self.f_sample.add_sample(sample.R, 'G') # R-ko smerdžíme ako G-čko
51 #wt.w = to_sample.pdf_G / wt.h.pdf_R # snad je to správně
52
53
54 def get_weights(self):
55 accu_denom_w = np.zeros(self.f_sample.nsim, dtype=float)
56 if self.IS_mode == 'R':
57 for serie in self.series_data:
58 h_sample, events, alpha = serie
59 h = h_sample.new_sample(self.f_sample)
60 accu_denom_w += h.pdf_R * h_sample.nsim
61 return self.f_sample.pdf_R / accu_denom_w, self.events
62
63 else: # IS_mode == 'G'
64 for serie in self.series_data:
65 h_sample, events, alpha = serie
66 h = h_sample.new_sample(self.f_sample.G, 'R')
67 accu_denom_w += h.pdf_R * h_sample.nsim
68 return self.f_sample.pdf_G / accu_denom_w, self.events
69
70
71 def get_means(self):
72 w, events = self.get_weights()
73 keys = np.unique(events)
74 Nsim = len(w)
75
76 means = np.empty(len(keys), dtype=float)
77 vars = np.empty(len(keys), dtype=float)
78
79
80 # tak bacha
81 ev = np.array(events)
82 for key, i in zip(keys, range(len(keys))):
83
84 mask = ev==key
85 ev_w = w[mask]
86 # podle IS vzorečků (skoro)
87 key_mean = np.sum(ev_w)
88 key_var = (np.sum(ev_w**2)*Nsim - key_mean**2) / Nsim
89
90 # uložime
91 means[i] = key_mean
92 vars[i] = key_var
93
94 # vyfiltrujeme zbytek
95 w = w[~mask]
96 ev = ev[~mask]
97
98 # kontrola
99 assert len(w)==0 and len(ev)==0, "Что за хренотень?!"
100
101 return means, vars
102
103
104 class ISSI:
105 """
106 IS statistics = weights series + events
107 ISSI calculates probabilities of repeated IS series
108 with implicit (non-zero) variances
109
110 zda se mi, že tím nelze nic zhoršit
111 """
112 def __init__(self, events=[]):
113 """
114 """
115 self.series_data = []
116 self.events = events
117
118 def add_IS_serie(self, weights, events, implicit_multiplicator=1):
119 keys = np.unique(events)
120 Nsim = len(weights)
121
122 # vytvoříme slovník pro sadu vzorků, který implicitně
123 # bude předpokládát průměr=0 a rozptyl 1/Nsim^2
124 # pro všecko, co se v sadě neobjevilo
125 if Nsim == 1:
126 # jedno meření je taky měření)
127 implicit_var = implicit_multiplicator
128 else:
129 implicit_var = implicit_multiplicator*(1-1/Nsim)/Nsim**2
130 serie = collections.defaultdict(lambda:(0, implicit_var))
131
132 # tak bacha
133 w = np.array(weights)
134 ev = np.array(events)
135 for key in keys:
136 if key not in self.events:
137 self.events.append(key)
138
139 mask = ev==key
140 ev_w = w[mask]
141 # podle IS vzorečků
142 key_mean = np.sum(ev_w)/Nsim
143 key_var = (np.sum(ev_w**2)/Nsim - key_mean**2) / Nsim
144 if key_var == 0: # to nechcem
145 key_var = implicit_var
146
147 # uložime
148 serie[key] = (key_mean, key_var)
149
150 # vyfiltrujeme zbytek
151 w = w[~mask]
152 ev = ev[~mask]
153
154 # kontrola
155 assert len(w)==0 and len(ev)==0, "Что за хренотень?!"
156
157 self.series_data.append(serie)
158
159 # ачиз значение утёз
160 self.get_estimations()
161 self.estimations = {self.events[i] : self.values[i] for i in range(len(self.events))}
162
163
164 def get_means(self):
165 # počet jevů
166 # number of events
167 n_ev = len(self.events)
168 self.weighted_means = np.empty(n_ev, dtype=float)
169 self.weighted_vars = np.empty(n_ev, dtype=float)
170
171 # spočteme važené průměry a rozptyly
172 for event, key in zip(self.events, range(n_ev)):
173 key_accusum = 0
174 key_accuweight = 0
175 for serie in self.series_data:
176 key_mean, key_var = serie[event]
177 key_accusum += key_mean / key_var
178 key_accuweight += 1/key_var
179
180 self.weighted_means[key] = key_accusum / key_accuweight
181 self.weighted_vars[key] = 1/key_accuweight
182
183
184 return self.weighted_means, self.weighted_vars, np.array(self.events)
185
186 def get_estimations(self):
187
188 # p-čka. We are still talking about probabilities, right?
189 p, vars, __ = self.get_means()
190
191 sum_p = np.sum(p)
192 if sum_p == 1: # а вдруг?
193 self.values = p
194 return p, np.array(self.events)
195
196 # spring (non-linear) analogue
197 # silu, kterou zatížíme system jen tak neseženeme
198 elif sum_p > 1: # stlačit
199 low_atF = -np.pi/2
200 high_atF = 0
201 else: # roztahnout
202 low_atF = 0
203 high_atF = np.pi/2
204
205 # nuly nám udělaj problém
206 mask = p==0
207 p = np.ma.array(p)
208 vars = np.ma.array(p)
209 p.mask = mask
210 vars.mask = mask
211
212 F = np.tan(bisect(lambda atF: np.sum(np.exp(np.tan(atF)*vars/p)*p), 1, low_atF, high_atF))
213 corrected_means = p * np.exp(F * vars/p)
214
215 corrected_means.mask = False
216 self.values = corrected_means
217 return corrected_means, np.array(self.events)
218
219
220
221
222
223
224
225
226
227
228 class ISS:
229 """
230 IS statistics = weights series + events
231 ISS calculates probabilities of repeated IS series
232 """
233 def __init__(self):
234 """
235 defaultdict zajistí, že na každý jev nás čeka seznam, do kterého
236 může přidávat průměr a rozptyl ze sady
237 """
238 self.data = collections.defaultdict(list)
239
240 def add_IS_serie(self, weights, events):
241 keys = np.unique(events)
242 Nsim = len(weights)
243
244 # tak bacha
245 w = np.array(weights)
246 ev = np.array(events)
247 for key in keys:
248 mask = ev==key
249 ev_w = w[mask]
250 # podle IS vzorečků
251 key_mean = np.sum(ev_w)/Nsim
252 key_var = (np.sum(ev_w**2)/Nsim - key_mean**2) / Nsim
253 # uložime
254 self.data[key].append((key_mean, key_var))
255
256 # vyfiltrujeme zbytek
257 w = w[~mask]
258 ev = ev[~mask]
259
260 # kontrola
261 assert len(w)==0 and len(ev)==0, "Что за хренотень?!"
262
263
264
265 def get_means(self):
266 # počet jevů
267 # number of events
268 weighted_means = []
269 weighted_vars = []
270
271 # spočteme važené průměry a rozptyly
272 for key_data in self.data.values():
273 key_accusum = 0
274 key_accuweight = 0
275 for key_mean, key_var in key_data:
276 key_accusum += key_mean / key_var
277 key_accuweight += 1/key_var
278
279 weighted_means.append(key_accusum / key_accuweight)
280 weighted_vars.append(1/key_accuweight)
281
282
283 return weighted_means, weighted_vars, np.array(list(self.data.keys()))
284
285 def get_estimations(self):
286 weighted_means, weighted_vars, __ = self.get_means()
287
288 # p-čka. We are still talking about probabilities, right?
289 p = np.array(weighted_means)
290 vars = np.array(weighted_vars)
291
292 sum_p = np.sum(p)
293 if sum_p == 1: # а вдруг?
294 return p, np.array(list(self.data.keys()))
295
296 # spring (non-linear) analogue
297 # silu, kterou zatížíme system jen tak neseženeme
298 elif sum_p > 1: # stlačit
299 low_atF = -np.pi/2
300 high_atF = 0
301 else: # roztahnout
302 low_atF = 0
303 high_atF = np.pi/2
304
305 F = np.tan(bisect(lambda atF: np.sum(np.exp(np.tan(atF)*vars/p)*p), 1, low_atF, high_atF))
306 corrected_means = p * np.exp(F * vars/p)
307
308 return corrected_means, np.array(list(self.data.keys()))
309
310
311
312
313 # scipy проверяет брэкеты, чем вызывает overflow warning, раздражает
314 # sol = optimize.root_scalar(lambda atF: np.sum(np.exp(np.tan(atF)*vars/p)*p)-1, bracket=(-np.pi/2, np.pi/2) )
315 # F = np.tan(sol.root)
316
317
318
319
320
321 # triangle analogue
322 # if len(weighted_means) == 2:
323 # # tak je to jednoduchý
324 # # it's piece of cake
325 # # triangle analogue
326 # a, b = *weighted_means
327 # # derivations of Heron's formula
328 # da = 8*a*b**2 + 6*a - 2*b - 2
329 # db = 8*b*a**2 + 6*b - 2*a - 2
330 # # matice koeficientů přetvořené podmínkové rovnice
331 # B = np.array([[1,1], [da, db]])
332
333 # u = 1 - np.sum(p)
334 # # vzoreček z teorii chyb měření a vyrovnávacího počtu nefunguje
335 # # dává aj záporné pravděpodobnosti
336 # #k = (1 - np.sum(weighted_means))/np.sum(weighted_vars)
337 # #corrected_means = weighted_means + weighted_vars*k
File __init__.py added (mode: 100644) (index 0000000..0916b75)
1 # vlmt
File blackbox.py added (mode: 100644) (index 0000000..09d2f73)
1 #!/usr/bin/env python
2 # coding: utf-8
3
4 """
5 Zde leží BlackBox (tuším, bude jeden)
6 BlackBox pěčlivě ukladá věškerá data,
7 věškeré sady vzorků, průběžné odhady a tak.
8 Nejsem už jistý, zda BlackBox je šťastný nazev, neboť
9 teďkom je to spíše jen krabička pro krámy
10 """
11
12
13 import numpy as np
14 from scipy import spatial
15 from . import plot
16 import pickle
17 from . import IS_stat
18 from . import sball # for adaptive censoring
19 from . import f_models # for adaptive censoring
20 from scipy import stats # for adaptive censoring
21
22 import inspect # for ._log() function
23
24 from .samplebox import SampleBox # for candidates packing
25
26 # considering to rewrite it with pandas
27 class GuessBox:
28 """
29 Je tu vynalezaní kola, ale aspoň tak
30 Odhady můžou tvořít strašnej bordel a proto jsou
31 ukladany do slovníku.
32 Tak ale jej nemůžu furt ukladat,
33 proto to robim s určitým krokem
34 Na konci je třeba zabalit tuhle krabičku ručně!
35 """
36 def __init__(gb, filename='', flush=100):
37 """
38 .counter - kdy bylo poslední ukladaní
39 """
40 gb.estimations = dict()
41 gb.filename = filename
42 gb.counter = 0
43 gb.flush = flush
44 gb.pick()
45
46 def __repr__(self):
47 return "%s(%r, %s)"%(self.__class__.__name__, self.filename, self.flush)
48
49 def __str__(gb):
50 return str(gb.estimations)
51
52 def __len__(gb):
53 return len(gb.estimations)
54
55 def __getitem__(gb, slice):
56 return gb.estimations[slice]
57
58 def guess(gb, index, nsim, estimation):
59 if index in gb.estimations:
60 gb.estimations[index][0].append(nsim)
61 gb.estimations[index][1].append(estimation)
62 else:
63 gb.estimations[index] = [[nsim], [estimation]]
64
65 gb.counter+= 1
66 if gb.filename and gb.counter > gb.flush:
67 gb.put()
68
69 def pick(gb):
70 if gb.filename:
71 try:
72 with open(gb.filename + '.pickle', 'rb') as f:
73 gb.estimations = pickle.load(f)
74 except:
75 # škoda, no
76 print("GuessBox: Já tu vaši odhady %s.pickle nevidím" % gb.filename)
77 else:
78 print('GuessBox is in air mode')
79
80 def put(gb):
81 if gb.filename:
82 try:
83 with open(gb.filename + '.pickle', 'wb') as f:
84 pickle.dump(gb.estimations, f)
85 gb.counter = 0
86 except:
87 # nefrčí...
88 print("GuessBox: Can not write %s.pickle" % gb.filename)
89 else:
90 print('GuessBox is in air mode')
91
92
93 class BlackBox:
94 """
95 BlackBox pěčlivě ukladá věškerá data,
96 věškeré sady vzorků (well, no yet), průběžné odhady a tak.
97 Nejsem už jistý, zda BlackBox je šťastný nazev, neboť
98 teďkom je to spíše jen krabička pro krámy
99
100 .sampled_plan object
101 .Z = g_values
102 .failsi
103
104 Souřadnice primárně z prostoru modelu, ty co jsme rovnou
105 posilali do g_modelu!
106
107 """
108 def __init__(bx, sample_box):
109 bx.sample_box = sample_box
110 # not really needed
111 bx.f = sample_box.sampled_plan()
112 # sample density (just helpful thing)
113 bx.h = bx.f
114 # don't ask me
115 bx.candidates = sample_box.sampled_plan()
116 # má bejt GuessBox součástí BlackBoxu?
117 try:
118 bx.guessbox = GuessBox(sample_box.filename, flush=20)
119 except:
120 bx.guessbox = GuessBox("", flush=20)
121 bx.regen()
122
123 def __repr__(bx):
124 return "%s(%s, %s)"%('BlackBox', repr(bx.f))
125
126 def __str__(bx):
127 return str('BlackBox ' + bx.sample_box)
128
129 def __len__(bx):
130 return bx.sample_box.nsim
131
132 def __call__(bx):
133 """
134 Offer next sample
135 """
136 # I do not see nothing illegal here
137 # LHS_like_correction do right conversion
138 return bx.LHS_like_correction(bx.h(1))
139
140 def __getitem__(bx, slice):
141 # stačí vratit sample_box
142 return bx.sample_box[slice]
143
144 def __getattr__(bx, attr):
145 # По всем вопросам обращайтесь
146 # на нашу горячую линию
147 return getattr(bx.sample_box, attr)
148
149 # just plot, green points, red points...
150 plot2D = plot.plot2D
151 plot3D = plot.plot3D
152
153 # přidávání vzorků musí bejt explicitní!
154 def add_sample(bx, input_sample):
155 bx._log("we have got new data:", str(input_sample))
156 bx.sample_box.add_sample(input_sample)
157 # tohle musí převest rozdělení vstupního vzorku na vlastní rozdělení skříňky
158 inner_sample = bx.sample_box.new_sample(input_sample)
159 bx.increment(inner_sample)
160
161
162 def increment(bx, input_sample):
163 for i in range(bx.nvar):
164 for j in range(len(input_sample)):
165 plan_index = np.searchsorted(bx.sorted_plan_U[i], input_sample.U[j,i])
166 bx.sorted_plan_U[i] = np.insert(bx.sorted_plan_U[i], plan_index, input_sample.U[j,i])
167
168 def regen(bx):
169 # pro LHS_like_correction
170 bx.sorted_plan_U = [i for i in range(bx.nvar)] # just create list
171 for i in range(bx.nvar):
172 bx.sorted_plan_U[i] = np.concatenate(([0], np.sort(bx.sampled_plan.U[:, i]), [1]))
173
174 # LHS_style correction
175 def LHS_like_correction(bx, input_sample):
176 """
177 returns sample object (f_model)
178 """
179 # what is input?
180 # as we need transformation anyway,
181 # I'll ask for conversion to f sample
182 # Здесь вижу железную конвертацию до f-ка,
183 # которая пройдёт по R координатам
184 # Kruci drát, tady by se nemohlo nic posrat
185 to_sample_node = bx.f.new_sample(input_sample)
186
187 LHS_node = np.empty(bx.nvar, dtype=float)
188 for i in range(bx.nvar):
189 if to_sample_node.U.flatten()[i] <= bx.sorted_plan_U[i][0]:
190 LHS_node[i] = (bx.sorted_plan_U[i][0] + bx.sorted_plan_U[i][1]) / 2
191 elif to_sample_node.U.flatten()[i] >= bx.sorted_plan_U[i][-1]:
192 LHS_node[i] = (bx.sorted_plan_U[i][-2] + bx.sorted_plan_U[i][-1]) / 2
193 else:
194 plan_index = np.searchsorted(bx.sorted_plan_U[i], to_sample_node.U.flatten()[i])
195 # vzdy
196 LHS_node[i] = (bx.sorted_plan_U[i][plan_index] + bx.sorted_plan_U[i][plan_index - 1]) / 2
197
198 return bx.f.new_sample(LHS_node, 'U')
199
200 def _log(bx, *msg, indent=0):
201 print(bx.__class__.__name__ + ":", *msg)
202
203 def _logi(bx, *msg, indent=1):
204 print("\t"*indent, inspect.currentframe().f_back.f_code.co_name + ":", *msg)
205
206
207 class Censoring(BlackBox):
208 def __init__(bx, sample_object, tri_space='Rn'):
209 bx.tri_space = tri_space
210 super().__init__(sample_object)
211
212 def __repr__(bx):
213 return "%s(%s, %s, %s)"%('Censoring', repr(bx.f), repr(bx.tri_space))
214
215 def __str__(bx):
216 return str('Censoring')
217
218 def increment(bx, input_sample):
219 super().increment(input_sample)
220
221 if "tri" in dir(bx):
222 # tri - Deloneho triangulace
223 # sample je jíž převeden na f (v .add_sample()), takže je to bezpěčný
224 bx.tri.add_points(getattr(input_sample, bx.tri_space))
225 # print('increment se podaril')
226 if len(bx.tri.coplanar): # pokud triangulace není v pořadku
227 #print('triangulace v pořádku není')
228 bx._log('triangulation is coplanar')
229 else:
230 bx._log('Triangulace (zatím?) neexistuje')
231 bx.regen()
232
233
234 def regen(bx):
235 super().regen()
236 # pokud tecek nestaci na vytvareni aspon jedneho simplexu - pokrcim rameny
237 try:
238 # tady je to OK
239 bx.tri = spatial.Delaunay(getattr(bx.sampled_plan, bx.tri_space), incremental=True)
240 if len(bx.tri.coplanar): # pokud triangulace je v pořadku
241 #print('triangulace v pořádku není')
242 bx._log('triangulation is coplanar')
243 else:
244 #print('triangulace je v pořádku')
245 bx._log('triangulation is OK')
246 except:
247 # kdyby neco - berem kramle
248 bx._log('triangulation failed')
249
250
251
252 def __call__(bx):
253 # je treba si uvedomit ze pravdepodobnost chytnuti muze byt min jak pf. V soucasne realizaci
254 try:
255 # očekávám, že projde kandidaty
256 # vodkaď jsou - netuším
257 to_sample, rate = bx.filter()
258 # když nepovedlo s kandidaty, zkusíme sami nagenerovat
259 while len(to_sample) == 0: # nekonečno
260 # tak, děcka, server má spoustu času a nikam nespejchá
261 # ale pokud tohle sežere věškerou paměť (ne když, ale kdy)
262 # dostaneš co proto!
263 # vomezíme pole na 10e6 (desitky mega teda vodhadově)
264 # by bylo možně použit chytrejší vzoreček s logaritmem
265 # ale snad tohle postačí
266 to_sample, rate = bx.filter(bx.h(int(0.9999*rate + 100)))
267 return bx.LHS_like_correction(to_sample)
268
269 # chcu zachytit spadnuti QHull na začatku, kdy ještě není
270 # dostatek teček. Je-li bx.tri fakticky existuje, tj.
271 # triangulace jíž existovala - je třeba nechat QHull spadnout
272 except AttributeError:
273 # kdyby neco - berem kramle
274 print("Triangulation doesn't exist. Censoring failed")
275 return bx.LHS_like_correction(bx.h(1)) # it should be OK
276
277 def filter(bx, candidates=[]):
278 """
279 supports both sample and sample.R input
280
281 logika metody, nebo, přesněji, implementaci
282 je taková, že bule-li někdo-něco mimo doménu,
283 tak funkce je vrátí a zbytek už neřeší
284 """
285 # co to bylo na vstupu?
286 # když nebyl žádný,
287 # projdeme vlastními kandidaty
288 if len(candidates)==0:
289 candidates = bx.candidates
290
291
292 # tady byl problém. Funkce byla původně navržena tak,
293 # aby ji nezajimalo co je na vstupu
294 # to ale nefunguje
295 # další funkce jako výstup očekavají něco s validním R-kem
296 candidates_to_sample_node = getattr(bx.f.new_sample(candidates), bx.tri_space)
297
298
299 found_simplices = bx.tri.find_simplex(candidates_to_sample_node)
300 # ouside of domain - it's easy
301 outside = candidates[found_simplices < 0]
302 if len(outside) > 0:
303 # my hodnotili svých kandidatov?
304 if bx.candidates == candidates:
305 bx.candidates = outside
306 return outside, len(candidates)/len(outside)
307
308 # tady já chcu vrátit první vhodný vzorek a tím končít
309 for candidate_id in range(len(candidates)):
310 # simplex_id >= 0: # inside of domain
311 simplex_id = found_simplices[candidate_id]
312 simplex = bx.tri.simplices[simplex_id]
313
314 # fp like a failure points. Number of failure points
315 fp = len(np.setdiff1d(simplex, bx.failure_points))
316
317 # pokud je simplex není jednobarevny..
318 if (fp != 0) and (fp != bx.nvar+1):
319 # my hodnotili svých kandidatov?
320 if bx.candidates == candidates:
321 bx.candidates = candidates[candidate_id:]
322 return candidates[candidate_id], candidate_id
323
324 # nepovedlo. nic
325 # mě nenapadá žádný lepší způsob vrátit prázdnou matici
326 return candidates[0:0], len(candidates)
327
328
329 class AdaptiveCensoring(Censoring):
330 def __init__(bx, sample_object, tri_space='Rn', pf_lim=(1,0)):
331 bx._log("instance creating")
332 bx.sball = sball.Sball(sample_object.nvar)
333 bx.pf_lim = pf_lim
334
335 bx.base_r = bx.sball.get_r(0.5)
336
337 # pro jistotu pridame
338 bx.simplex_index = {'failure':[], 'success':[], 'mix':[]}
339
340
341 # overall estimations
342 #bx.oiss = IS_stat.ISSI(['failure', 'success', 'out', 'mix'])
343 # -1 = 'out', 0=success, 1=failure, 2=mix
344 bx.oiss = IS_stat.ISSI([-1,0,1,2])
345 # current estimations
346 bx.ciss = IS_stat.ISSI([-1,0,1,2])
347
348 super().__init__(sample_object, tri_space)
349
350
351 def __repr__(bx):
352 return "%s(%s, %s, %s, %s)"%('AdaptiveCensoring', repr(bx.f), repr(bx.tri_space), repr(bx.pf_lim))
353
354 def __str__(bx):
355 return str('AdaptiveCensoring')
356
357 def regen(bx):
358 bx._logi(inspect.currentframe().f_back.f_code.co_name, "launched regeneration")
359
360 super().regen()
361 if bx.pf_lim[1] == 0:
362 bx.drop_r = float("inf")
363 else:
364 bx.drop_r = bx.sball.get_r(bx.pf_lim[1])
365
366 # dropneme (pro jistotu) odhady
367 bx.oiss = bx.ciss
368 # -1 = 'out', 0=success, 1=failure, 2=mix
369 bx.ciss = IS_stat.ISSI([-1,0,1,2])
370
371 # drop indexes
372 bx.simplex_index = {'failure':[], 'success':[], 'mix':[]}
373
374 def increment(bx, input_sample):
375 super().increment(input_sample)
376
377 # drop indexes
378 bx.simplex_index = {'failure':[], 'success':[], 'mix':[]}
379
380 # current estimations
381 try: # to čo já vidím v kódu - ISSI slovníky se pokažde generujóu znovu,
382 # není nutně je explicitně kopirovať
383 bx.guessbox.guess('TRI_overall_estimations', bx.nsim-1, bx.oiss.estimations)
384 bx.guessbox.guess('TRI_current_estimations', bx.nsim-1, bx.ciss.estimations)
385 except AttributeError:
386 bx.guessbox.guess('TRI_upper_pf', bx.nsim-1, 1)
387
388 # a znovu začneme počítat
389 # -1 = 'out', 0=success, 1=failure, 2=mix
390 bx.ciss = IS_stat.ISSI([-1,0,1,2])
391
392
393 def __call__(bx):
394 bx._log("we were asked for an recommendation")
395 # je treba si uvedomit ze pravdepodobnost chytnuti muze byt min jak pf. V soucasne realizaci
396 try:
397 # očekávám, že projde kandidaty
398 # odkaď jsou - netuším
399 to_sample, rate, simplex_id = bx.filter()
400 # když nepovedlo s kandidaty, zkusíme sami nagenerovat
401 while len(to_sample) == 0: # nekonečno
402 # pokusme se nastavit rate tak, abychom získali právě jedneho kandidata
403 try: # try uvnitř traja
404 p_rate = bx.oiss.estimations[-1] + bx.oiss.estimations[2]
405 except:
406 p_rate = bx.pf_lim[0] - bx.pf_lim[1]
407 if p_rate < 1e-5:
408 rate = 100000
409 else:
410 rate = int(1/p_rate) + 1
411 to_sample, rate, simplex_id = bx.filter(bx.get_candidates(rate))
412 choose = bx.LHS_like_correction(to_sample)
413 bx._log("finally we choose", str(choose), "of", simplex_id, "simplex")
414 return choose
415
416 # chcu zachytit spadnuti QHull na začatku, kdy ještě není
417 # dostatek teček. Je-li bx.tri fakticky existuje, tj.
418 # triangulace jíž existovala - je třeba nechat QHull spadnout
419 except AttributeError:
420 choose = bx.LHS_like_correction(bx.get_candidates(1))
421 if bx.nsim < bx.nvar + 1: # je to legální
422 bx._log("we have no enough points to build triangulation, so", str(choose), "is our recommendation")
423 return choose
424
425 elif bx.nsim < 2*bx.nvar + 3: # to je ještě budiž
426 bx._log("we have troubles with triangulation, so we offer random sample for now:", str(choose))
427 return choose
428 else: # no to teda ne!
429 raise ValueError("AdaptiveCensoring: s tou triangulací je fakt něco není v pořadku")
430
431
432 def filter(bx, candidates=[]):
433 """
434 za pvré, jako vstup očekávám kandidaty od .get_candidates() funkce,
435 zabalené do полукустарного sample_boxu s zadaným .implicit_multiplicator
436 (je to drobnost pro přesnějši zpracování sad IS IS_statem).
437
438 Metoda musí souřádnicím přiřazovat jev
439 "success", "failure", "mix", "outside"
440
441 TATO metoda jakmile narazí na "mix" nebo "outside"
442 ukladá zjištěné informace do ISSI a nalezeného kandidata vrací
443 """
444 # co to bylo na vstupu?
445 # když nebyl žádný,
446 # projdeme vlastními kandidaty
447 if len(candidates)==0:
448 candidates = bx.candidates
449
450 bx._logi("kandidaty:", candidates)
451
452 # je třeba lokálně zachovat implicit_multiplicator
453 # jinak se ztrací při slajsingu
454 # nechceš přepsat SampleBox, Alexi?
455 try:
456 implicit_multiplicator = candidates.implicit_multiplicator
457 except AttributeError: # kandidaty můžou bejt odkudkoliv
458 # s nekonečným rozptylem nebudou mít váhu "absenční" jevy
459 # moc to odhadům nepomůže, protože je-li kandidaty
460 # nemajú .implicit_multiplicator
461 # asi nebudou mať ani váhy IS v .g_values
462 implicit_multiplicator = float("inf")
463 bx._logi("Dobrý den, kandidaty nemajú .implicit_multiplicator")#. S pozdravem, AdaptiveCensoring")
464
465 # tady byl problém. Funkce byla původně navržena tak,
466 # aby ji nezajimalo co je na vstupu
467 # to ale nefunguje
468 # další funkce jako výstup očekavají něco s validním R-kem
469 # no tj. já zde provádím posouzení transformací z R-ka vstupních souřadnic
470 candidates_to_sample_node = getattr(bx.f.new_sample(candidates), bx.tri_space)
471
472
473 current_simplices = bx.tri.find_simplex(candidates_to_sample_node)
474
475
476 # tak bacha
477 # budeme přepísovat jevy in-place
478 found_simplices = np.ma.array(current_simplices.copy()) #.copy()
479 # nemaskované - obsahuji číslo simplexu
480 # maskované - číslo jevu
481 # -1 = 'out', 0=success, 1=failure, 2=mix
482 # tj. procházíme simplexy z náhodné sady vzorků,
483 # nahrazujeme čislo simplexu odpovidajicím mu jevem
484 # a skryváme ho
485 # pote ty "skryté", "projduté" vzorky využiváme k žískání odhadů
486
487 while len(current_simplices):# > 0:
488 bx._logi("current simplices", current_simplices)
489 # berem hned prvního kandidata
490 # a posuzujeme co je zač
491 simplex_id = current_simplices[0]
492 mask = found_simplices==simplex_id
493
494 if simplex_id < 0: # -1 means ouside
495 # berem kramle
496 break
497 elif simplex_id in bx.simplex_index['success']:
498 found_simplices[mask] = 0
499 elif simplex_id in bx.simplex_index['failure']:
500 found_simplices[mask] = 1
501 elif simplex_id in bx.simplex_index['mix']:
502 found_simplices[mask] = 2
503 # kramle
504 break
505 else: # no index information
506 # tady já chcu vrátit první vhodný vzorek a tím končít
507 # simplex_id >= 0: # inside of domain
508 # asi tady získavam množinu s čísly vrcholů
509 # kteří zakladají simplex
510 simplex = bx.tri.simplices[simplex_id]
511
512 # for debug
513 bx._logi("провал индексу", simplex_id, indent=2)
514
515 # fp like a failure points. Number of failure points
516 # setdiff "Return the unique values in ar1 that are not in ar2."
517 fp = len(np.setdiff1d(simplex, bx.failure_points))
518
519 if fp == bx.nvar+1: #
520 bx.simplex_index['success'].append(simplex_id)
521 found_simplices[mask] = 0
522 elif fp == 0:
523 bx.simplex_index['failure'].append(simplex_id)
524 found_simplices[mask] = 1
525 #print("failure simplex", simplex_id)
526 else:
527 bx.simplex_index['mix'].append(simplex_id)
528 found_simplices[mask] = 2
529 bx._logi("mixed simplex", simplex_id)
530 # bacha! kramle
531 break
532
533 # pridame do seznamu známého
534 found_simplices[mask] = np.ma.masked
535 # eště raz
536 cmask = current_simplices==simplex_id
537 # vyfiltrujeme
538 current_simplices = current_simplices[~cmask]
539
540
541
542 # zde je třeba перехватить ситуацию, куке одӥг но кандидат ӧвӧл
543 # нужно ли?
544 # if len(current_simplices) == 0:
545 # # nepovedlo. nic
546 # bx.candidates = candidates[0:0]
547 # # mě nenapadá žádný lepší způsob vrátit prázdnou matici
548 # return candidates[0:0], len(candidates), -2 # simple_id
549
550 # nemaskované, včetně současného kandidata (nevím proč) - ke kandidatům
551 # землю - крестьянам, фабрики - рабочим
552 # předpokladam, že kandidaty jsou se všim všudy
553 # s vahami (.g_value) a se svým .implicit_multiplicator'em
554 ## zde True hodnoty roušky - to co jíž bylo skryto
555 bx.candidates = candidates[~np.ma.getmaskarray(found_simplices)][1:] # toho prvního prečo nechcem
556 try: # na zacatku je tam prazdný f_model, kterému atribut pripsat nemůžeme
557 bx.candidates.implicit_multiplicator = implicit_multiplicator
558 except:
559 pass
560
561 # vrátíme kandidaty, všechny-ne všechny?
562 # малы одӥг гинэ? уг тодӥськы чик...
563 selected_candidate = candidates[~np.ma.getmaskarray(found_simplices)][:1] # chcem toho prvního
564
565
566 # odešleme ISSI
567 try:
568 # pridame do seznamu známého
569 # rouška musí zůstat z cyklu
570 # proboha, Alexi, co to je za roušku, co se tu děje?
571 # jakmile v tom hlavním cyklu nalezli jsme mix nebo outside
572 # my hned z cyklu vylezli a je neskryli - abychom je vzali jako kandidaty
573 # teď je však skryváme s tou "rouškou", co musela být před opuštěním cyklu nastavena
574 # tak ISSI bude mít možnost odhadovat i pravděpodobnosti mix a outside
575 found_simplices[mask] = np.ma.masked
576 # zde získáme True hodnoty roušek
577 # ukazatel
578 imask = found_simplices.mask
579 found_simplices.mask = ~imask # invertujem, dotkne to i samotnou imask
580 events = found_simplices.compressed()
581 print(candidates)
582 print(candidates.g_values)
583 print("imask", imask)
584 print(candidates.g_values[~imask])
585 print(events)
586 bx.oiss.add_IS_serie(candidates.g_values[~imask], events, implicit_multiplicator)
587 print("global estimation", bx.oiss.estimations)
588 bx.ciss.add_IS_serie(candidates.g_values[~imask], events, implicit_multiplicator)
589 print("current estimation", bx.ciss.estimations)
590 except AttributeError:
591 bx._logi("Это вы мне прислали неваженых кандидатов?")
592 except UnboundLocalError: # čo tu chybu způsobuje?
593 # asi nebyly žádné kandidaty (třeba hned na začátku)
594 assert len(candidates)==0 and len(bx.candidates)==0, "AdaptiveCensoring: Что за бурда с этими кандидатама?"
595 return candidates, 0, -2
596
597
598 # rate = kolík bylo - kolik zůstalo
599 return selected_candidate, len(candidates) - len(bx.candidates), simplex_id
600
601
602
603
604 def get_candidates(bx, Nsim=int(1e4)):
605 # -1 = 'out', 0=success, 1=failure, 2=mix
606
607 # не мудрствуя лукаво
608 user_pf = np.mean(bx.pf_lim)
609 try:
610 low_pf = bx.oiss.estimations[1] # failure
611 upper_pf = 1 - bx.ciss.estimations[0] # sucess
612 self_pf = (low_pf + upper_pf)/2
613 except AttributeError:
614 self_pf = 0.5
615
616 # bereme *mean* od svého a uživatelského odhadu
617 # minimum nejede
618 sampling_r, __ = bx.sball.get_r_iteration(np.mean((self_pf, user_pf)))
619 # asi tam bylo sampling_r/bx.base_r, že?
620 # u stats.norm zadáváme směrodatnou odchylku, je to asi správné
621 h = f_models.UnCorD([stats.norm(0, sampling_r/bx.base_r) for i in range(bx.nvar)])
622
623 # for IS_stats
624 svar = (sampling_r/bx.base_r)**2 # svar like sampling_variance
625 # něco takovýho bych nahrubo placnul
626 implicit_multiplicator = svar**bx.nvar * np.exp(bx.nvar/svar - bx.nvar)
627
628 #
629 # jdeme na to, koťě!
630 #
631
632 # zgenerujeme vzorky
633 # nic zajimavýho
634 h = h(Nsim)
635 # dropneme priliš vzdálené kandidaty
636 distance_from_zero = np.sum(h.R**2, axis=1)
637 mask = distance_from_zero < bx.drop_r
638
639 # a teď bacha!
640 # tady musíme provést jeden trik
641 to_sample = bx.f.new_sample(h.R[mask], 'G') # R-ko smerdžíme ako G-čko
642 w = to_sample.pdf_G / h.pdf_R # snad je to správně
643 # zabalme do boxu
644 candidates = SampleBox(to_sample, w, 'BlackBox internal samples and weights')
645 candidates.implicit_multiplicator = implicit_multiplicator
646 # vahy máme, zbytek už nejsou naši starosti
647 return candidates
648
File f_models.py added (mode: 100644) (index 0000000..374874f)
1 #!/usr/bin/env python
2 # coding: utf-8
3
4
5 """
6 cs:
7
8
9 en:
10
11 """
12
13 import numpy as np
14 from scipy import stats
15 import copy
16
17
18 class Ingot:
19 """
20 Prazdná třida pro "nevypalené" vzorky, tj. bez přiřazeného rozdělení
21 """
22 def __init__(self, data, attr='R'):
23 # data? takový neslaný nazev...
24 # data suppose to be pandas compatible, i.e.
25 # nsim, nvar = data.shape
26 self.attr = attr
27 try:
28 self.data = np.atleast_2d(getattr(data, attr))
29 except AttributeError:
30 self.data = np.atleast_2d(data)
31
32
33 def __repr__(self):
34 return "%s(np.%s, '%s')"%('Ingot', repr(self.data), self.attr)
35
36 def __str__(self):
37 return str(self.data)
38
39 def __len__(self):
40 return len(self.data)
41
42 def __getitem__(self, slice):
43 self_copy = copy.copy(self)
44 # robim kopiu z _data, nebo ne?
45 self_copy.data = np.atleast_2d(self.data[slice,:]) #.copy()
46 return self_copy
47
48
49 def __getattr__(self, attr):
50 # Рекурсилы пезьдэт!
51 if attr in ('attr', 'data'):
52 raise AttributeError(attr)
53 #if attr in ('R', 'Rn', 'GK', 'G', 'P', 'U') and attr==self.space:
54 # return f._data
55 elif attr == 'nvar':
56 nsim, nvar = self.data.shape
57 return nvar
58 elif attr == 'nsim':
59 return len(self.data)
60
61 # гулять так гулять
62 elif attr == self.attr:
63 return self.data
64
65 raise AttributeError(attr)
66
67
68 # vstupné vzorky jsou implicitně R,
69 # nikoliv z prostoru tohoto krámu
70 def add_sample(self, sample, space='R'):
71 # first of all, are you one of us?
72 if space == self.attr:
73 # does sample is another sample object?
74 # zde nechcu, aby spadlo
75 try:
76 self.data = np.vstack((self.data, getattr(sample, self.attr)))
77 except AttributeError:
78 self.data = np.vstack((self.data, sample))
79
80 # no, actually
81 else:
82 # does sample is another sample object?
83 # self.data = np.vstack((self.data, getattr(sample, self.attr)))
84 # ale zde chcu
85 # (aby spadlo)
86 raise ValueError
87
88
89 # drobná pomucka
90 def new_sample(f, sample=None, space='R'):
91 return Ingot(sample, space) # too easy
92
93
94 class SNorm:
95 """
96 Standard Gauss distribution
97 """
98 def __init__(self, nvar):
99 self.__nvar = nvar
100 # nvar_R + nvar_U + pdf_R
101 rowsize = nvar*2 + 1
102 # data? takový neslaný nazev...
103 # data suppose to be cKDTree compatible, i.e.
104 # nsim, nvar = data.shape
105 self._data = np.empty((0, rowsize), dtype=float)
106
107 def __repr__(self):
108 return "%s(%s)"%('SNorm', self.__nvar)
109
110 def __str__(f):
111 return str(f.R)
112
113 def __call__(f, ns=0):
114 f_copy = eval(f.__repr__())
115 if ns:
116 sample_P = np.random.random((ns, f_copy.nvar))
117 sample_R = stats.norm.ppf(sample_P)
118
119 pdfs_R = stats.norm.pdf(sample_R)
120 pdf_R = np.prod(pdfs_R, axis=1).reshape(-1, 1)
121 f_copy._data = np.hstack((sample_R, sample_P, pdf_R))
122 return f_copy
123
124 def __len__(f):
125 return len(f._data)
126
127 def __getitem__(f, slice):
128 f_copy = eval(f.__repr__())
129 # robim kopiu z _data, nebo ne?
130 f_copy._data = np.atleast_2d(f._data[slice,:]) #.copy()
131 return f_copy
132
133
134 # slajsy. Nejsem jist, zda mám robit kopiu, nebo ne. Takže bacha!
135 def __getattr__(f, attr):
136 if attr in ('pdf_R', 'pdf_Rn', 'pdf_GK', 'pdf_G'):
137 return f._data[:,-1]
138 elif attr in ('R', 'Rn', 'GK', 'G'):
139 return f._data[:,:f.__nvar]
140 elif attr in ('P', 'U'):
141 return f._data[:,f.__nvar:2*f.__nvar]
142 elif attr == 'nvar':
143 return f.__nvar
144 elif attr == 'nsim':
145 return len(f._data)
146 elif attr == 'marginals':
147 return [stats.norm for __ in range(f.__nvar)]
148 elif attr == 'cor':
149 return np.diag([1 for __ in range(f.__nvar)])
150
151 raise AttributeError(attr)
152
153
154 # pro určitou konzistenci. Ne že bych chtěl zamykat dveře v Pythonu
155 def __setattr__(f, attr, value):
156 if attr in ('_SNorm__nvar','_data'):
157 f.__dict__[attr] = value
158 else:
159 #raise AttributeError('Čo tu robíš?')
160 #raise AttributeError('Враг не пройдёт!')
161 #raise AttributeError('Иди отсюда!')
162 #raise AttributeError('Аслыкъёсы воштыны уг луи!')
163 raise AttributeError('Atribute %s of %s object is not writable' % (attr, f.__class__.__name__))
164
165
166 def add_sample(f, sample, space='R'):
167 # does sample is exactly me?
168 if f.__repr__() == sample.__repr__():
169 newdata = sample._data
170 elif space in ('R', 'Rn', 'GK', 'G'):
171 # does sample is another f_model object?
172 try:
173 sample_R = getattr(sample, space)
174 except:
175 # no
176 sample_R = sample
177 sample_P = stats.norm.cdf(sample_R)
178
179 pdfs_R = stats.norm.pdf(sample_R)
180 pdf_R = np.prod(pdfs_R, axis=pdfs_R.ndim-1)
181 if pdfs_R.ndim == 2:
182 newdata = np.hstack((sample_R, sample_P, pdf_R.reshape(len(pdf_R), 1)))
183 else:
184 newdata = np.hstack((sample_R, sample_P, pdf_R))
185
186 elif space in ('P', 'U'):
187 try:
188 sample_P = getattr(sample, space)
189 except:
190 sample_P = sample
191 sample_R = stats.norm.ppf(sample_P)
192
193 pdfs_R = stats.norm.pdf(sample_R)
194 pdf_R = np.prod(pdfs_R, axis=pdfs_R.ndim-1)
195 if pdfs_R.ndim == 2:
196 newdata = np.hstack((sample_R, sample_P, pdf_R.reshape(len(pdf_R), 1)))
197 else:
198 newdata = np.hstack((sample_R, sample_P, pdf_R))
199
200 f._data = np.vstack((f._data, newdata))
201
202
203 # drobná pomucka
204 def new_sample(f, sample=None, space='R'):
205 f_copy = eval(f.__repr__())
206 if sample is not None:
207 f_copy.add_sample(sample, space)
208 return f_copy
209
210 # # drobná pomucka
211 # def new_random_sample(f, ns=1):
212 # f_copy = eval(f.__repr__())
213 # f_copy.add_sample(np.random.random((ns, f.nvar)), 'U')
214 # return f_copy
215
216
217
218
219
220
221 class UnCorD: # nic moc nazev, ale je přece lepší nez CommonJointDistribution
222 """
223 Takes tuple of scipy stats distribution objects
224 """
225 def __init__(self, marginals):
226 self.__marginals = marginals
227 # nvar_Rn + nvar_R + nvar_P + nvar_G + pdf_R + pdf_G
228 rowsize = len(marginals)*4 + 2
229 # data? takový neslaný nazev...
230 # data suppose to be cKDTree compatible, i.e.
231 # nsim, nvar** = data.shape
232 self._data = np.empty((0, rowsize), dtype=float)
233
234 def __repr__(self):
235 return "%s(%s)"%('UnCorD', repr(self.__marginals))
236
237 def __str__(f):
238 return str(f.R)
239
240 def __call__(f, ns=0):
241 f_copy = copy.copy(f) # nebo deep?
242 f_copy._data = np.empty((0, f_copy._data.shape[1]), dtype=float)
243
244 if ns:
245 sample_dict = {'P':np.random.random((ns, f_copy.nvar))}
246 f._chain(sample_dict)
247 pdf_G = np.prod(stats.norm.pdf(sample_dict['G']), axis=1).reshape(-1, 1)
248 pdfs_R = [f.marginals[i].pdf(sample_dict['R'][:, i]) for i in range(f.nvar)]
249 # je tu fakt axis=0. Dochazí totíž v iterátoru k převracení
250 pdf_R = np.prod(pdfs_R, axis=0).reshape(-1, 1)
251 # nvar_Rn + nvar_R + nvar_P + nvar_G + pdf_R + pdf_G
252 f_copy._data = np.hstack((sample_dict['Rn'], sample_dict['R'], sample_dict['P'], sample_dict['G'], pdf_R, pdf_G))
253 return f_copy
254
255 def __len__(f):
256 return len(f._data)
257
258 def __getitem__(f, slice):
259 f_copy = copy.copy(f) # nebo deep?
260 f_copy._data = np.atleast_2d(f._data[slice,:]) #.copy()
261 return f_copy
262
263 # dúfám, že tyhle slajsy sa vyplatí
264 def __getattr__(f, attr):
265 if attr == 'pdf_R':
266 return f._data[:,-2]
267 elif attr in ('pdf_GK', 'pdf_G'):
268 return f._data[:,-1]
269 elif attr == 'Rn':
270 return f.__frame(0)
271 elif attr == 'R':
272 return f.__frame(1)
273 elif attr in ('P', 'U'):
274 return f.__frame(2)
275 elif attr in ('GK', 'G'):
276 return f.__frame(3)
277
278 elif attr == 'nvar':
279 return len(f.__marginals)
280 elif attr == 'nsim':
281 return len(f._data)
282 elif attr == 'marginals':
283 return f.__marginals
284 elif attr == 'cor':
285 return np.diag([1 for __ in range(f.nvar)])
286 raise AttributeError(attr)
287
288 # pro určitou konzistenci. Ne že bych chtěl zamykat dveře v Pythonu
289 def __setattr__(f, attr, value):
290 if attr in ('_UnCorD__marginals','_data'):
291 f.__dict__[attr] = value
292 else:
293 #raise AttributeError('Аслыкъёсы воштыны уг луи!')
294 raise AttributeError('Atribute %s of %s object is not writable' % (attr, f.__class__.__name__))
295
296 def __frame(f, i):
297 nvar = f.nvar
298 sl = slice(i*nvar, (i+1)*nvar)
299 return f._data[:,sl]
300
301 def add_sample(f, sample, space='R'):
302 # isinstance, ne?
303 if f.__class__.__name__ == sample.__class__.__name__:
304 if f.marginals == sample.marginals:
305 f._data = np.vstack((f._data, sample._data))
306 return f
307 elif space not in ('R', 'Rn', 'P', 'GK', 'G', 'U'):
308 # co jako, mám gettext sem tahnout?!
309 raise ValueError('Zadaný prostor %s mi není znám' % space)
310 raise ValueError('Unknown space %s' % space)
311
312 # does sample is another f_model object?
313 try:
314 sample_ = getattr(sample, space)
315 except:
316 # no
317 sample_ = sample
318
319 if space=='GK':
320 space='G'
321 elif space=='U':
322 space='P'
323
324 sample_dict = {space:np.array(sample_, dtype=float).reshape(-1, f.nvar)}
325 f._chain(sample_dict)
326 pdf_G = np.prod(stats.norm.pdf(sample_dict['G']), axis=1).reshape(-1, 1)
327 pdfs_R = [f.marginals[i].pdf(sample_dict['R'][:, i]) for i in range(f.nvar)]
328 # je tu fakt axis=0. Dochazí totíž v iterátoru k převracení
329 pdf_R = np.prod(pdfs_R, axis=0).reshape(-1, 1)
330 # nvar_Rn + nvar_R + nvar_P + nvar_G + pdf_R + pdf_G
331 newdata = np.hstack((sample_dict['Rn'], sample_dict['R'], sample_dict['P'], sample_dict['G'], pdf_R, pdf_G))
332
333 f._data = np.vstack((f._data, newdata))
334
335
336 # drobná pomucka
337 def new_sample(f, sample=None, space='R'):
338 f_copy = f()
339 if sample is not None:
340 f_copy.add_sample(sample, space)
341 return f_copy
342
343 # # drobná pomucka
344 # def new_random_sample(f, ns=1):
345 # f_copy = f()
346 # f_copy.add_sample(np.random.random((ns, f.nvar)), 'U')
347 # return f_copy
348
349 def _chain(f, sample_dict):
350 # chain tam
351 # чаль татысь
352 if 'R' not in sample_dict and 'Rn' in sample_dict:
353 sample_dict['R'] = np.empty_like(sample_dict['Rn'])
354 for i in range(f.nvar):
355 sample_dict['R'][:, i] = sample_dict['Rn'][:, i]*f.marginals[i].std() + f.marginals[i].mean()
356
357 if 'P' not in sample_dict and 'R' in sample_dict:
358 sample_dict['P'] = np.empty_like(sample_dict['R'])
359 for i in range(f.nvar):
360 sample_dict['P'][:, i] = f.marginals[i].cdf(sample_dict['R'][:, i])
361
362 if 'G' not in sample_dict and 'P' in sample_dict:
363 sample_dict['G'] = stats.norm.ppf(sample_dict['P'])
364
365 # chain sem
366 # чаль татчи
367 elif 'P' not in sample_dict and 'G' in sample_dict:
368 sample_dict['P'] = stats.norm.cdf(sample_dict['G'])
369
370 if 'R' not in sample_dict and 'P' in sample_dict:
371 sample_dict['R'] = np.empty_like(sample_dict['P'])
372 for i in range(f.nvar):
373 sample_dict['R'][:, i] = f.marginals[i].ppf(sample_dict['P'][:, i])
374
375 if 'Rn' not in sample_dict and 'R' in sample_dict:
376 sample_dict['Rn'] = np.empty_like(sample_dict['R'])
377 for i in range(f.nvar):
378 sample_dict['Rn'][:, i] = (sample_dict['R'][:, i] - f.marginals[i].mean())/f.marginals[i].std()
379
380
381
382 # def Rn2R(f, sample):
383 # sample_Rn = np.array(sample).reshape(-1, f.nvar)
384 # sample_R = np.empty_like(sample_Rn)
385 # for i in range(f.nvar):
386 # sample_R[:, i] = sample_Rn[:, i]*f.marginals[i].std() + f.marginals[i].mean()
387 # return sample_R
388 #
389 # def R2P(f, sample):
390 # sample_R = np.array(sample).reshape(-1, f.nvar)
391 # sample_P = np.empty_like(sample_R)
392 # for i in range(f.nvar):
393 # sample_P[:, i] = sample_Rn[:, i]*f.marginals[i].std() + f.marginals[i].mean()
394 # return sample_P
File g_models.py added (mode: 100644) (index 0000000..eb3a878)
1 #!/usr/bin/env python
2 # coding: utf-8
3
4
5 """
6 cs:
7
8
9 en:
10 data should be pandas compatible, i.e.
11 nsim, nvar = data.shape
12
13 g_model returns SampleBox object, which actually contains:
14 1. what-was-on-input
15 2. values of perfomance function
16 AND 3. so called gm_signature - some string to identify data
17 and do not let them be mixed up.
18 Currently WhiteBox treat as gm_signature __name__ attribute (free functions has it),
19 otherwise repr(). Classes supposed to define __repr__ function for correct work.
20
21 Fence off!
22 Some of performance functions (g_models) are able to draw
23 failure region boundary, in this case
24 .get_2D_R_boundary(nrod, xlim, ylim) is defined.
25 nrod - number of "rods" in "fencing"
26 xlim, ylim describes your viewport, plotting terminal, whatever
27 g_model uses these parameters only for inspiration,
28 g_model is allowed to ignore them
29 xlim = (xmin, xmax)
30 ylim = (ymin, ymax)
31
32 returns tuple (or list) of R samples
33
34
35
36 """
37
38 import numpy as np
39 from .f_models import Ingot
40 from .samplebox import SampleBox
41
42
43 class GetQuadrantBoundary2D:
44 """
45 sebemenší pomocná třida pro vykreslení hranici L tvaru
46 """
47 def __init__(self, center_point=(0,0), quadrant='I'):
48 """
49 quadrants also сэрегъёс-compatible
50 #### CORNERS 2D #####
51 # print(сэрегъёс)
52 # numbering:
53 # 2 | 3
54 # -----|-----
55 # 0 | 1
56 """
57 self.center_point = center_point
58 self.quadrant = quadrant
59
60 def __call__(self, nrod=100, xlim=(-5,5), ylim=(-5,5)):
61 xc, yc = self.center_point
62 xmin = min(*xlim, xc-1)
63 xmax = max(*xlim, xc+1)
64 ymin = min(*ylim, yc-1)
65 ymax = max(*ylim, yc+1)
66
67 nrod = int(nrod/2)
68 # mně nic hezčího prostě nenapadá(
69 if self.quadrant in ('I', 3):
70 xbound = np.append(np.full(nrod, xc), np.linspace(xc, xmax, nrod, endpoint=True))
71 ybound = np.append(np.linspace(ymax, yc, nrod, endpoint=True), np.full(nrod, yc))
72 elif self.quadrant in ('II', 2):
73 xbound = np.append(np.linspace(xmin, xc, nrod, endpoint=True), np.full(nrod, xc))
74 ybound = np.append(np.full(nrod, yc), np.linspace(yc, ymax, nrod, endpoint=True))
75 elif self.quadrant in ('III', 0):
76 xbound = np.append(np.linspace(xmin, xc, nrod, endpoint=True), np.full(nrod, xc))
77 ybound = np.append(np.full(nrod, yc), np.linspace(yc, ymin, nrod, endpoint=True))
78 else: # self.quadrant in ('IV', 1):
79 xbound = np.append(np.full(nrod, xc), np.linspace(xc, xmax, nrod, endpoint=True))
80 ybound = np.append(np.linspace(ymin, yc, nrod, endpoint=True), np.full(nrod, yc))
81
82
83 # sample compatible
84 # малы транспонировать кароно? Озьы кулэ!
85 bound_R = np.vstack((xbound, ybound)).T
86 # tuple of tuple
87 return (Ingot(bound_R),)
88
89
90
91 def get_R_coordinates(input_sample, envar=0):
92 """
93 Tohle je pomocná funkce, vrácí g_modelům numpy 2d pole s daty
94
95 envar - zadavejte, pokud chcete zkontrolovat
96 počet náhodných proměnných
97 envar like estimated number of variables
98 """
99 # is it sample object?
100 try:
101 if envar > 0 and input_sample.nvar != envar:
102 raise ValueError('%sD data expected, but %sD sample given'% (envar, input_sample.nvar))
103 else:
104 return input_sample.R
105
106 # it is not an sample object,
107 # but maybe numpy can handle this?
108 except AttributeError:
109 sample = np.atleast_2d(np.array(input_sample))
110 # invar like input number of variables
111 nsim, invar = sample.shape
112 if envar > 0 and invar != envar:
113 raise ValueError('%sD data expected, but %sD sample given'% (envar, invar))
114 else:
115 return sample
116
117 class Linear_nD:
118 """
119 Class takes for inicialization tuple of betas
120 Betas are coeffitients in sense of Regression Analysis
121
122 g= a*X1 + b*X2 + c
123 becames
124 gm = Linear_nD(betas=(a,b,c))
125 gm(samples)
126 gm.get_2D_R_boundary(nrod, xlim) returns
127 xbounds a ybounds zabalené do tuplu, ty zabalené do listu
128 """
129
130 def __init__(self, betas):
131 self._betas = betas
132
133 # sign
134 def __repr__(self):
135 return 'Linear_nD(%s)' % repr(self._betas)
136
137 def __call__(self, input_sample):
138 selfnvar = len(self._betas)-1
139 # očekávam, že get_R_coordinates mně vrátí 2D pole
140 sample = get_R_coordinates(input_sample, selfnvar)
141 # teďkom zasahujeme přímo do tohoto pole
142 sim = sample.copy()
143 for i in range(selfnvar):
144 sim[:,i] = sim[:,i]*self._betas[i]
145 g = np.sum(sim, axis=1) + self._betas[-1]
146 return SampleBox(input_sample, g, repr(self))
147
148
149
150 # Fence off!
151 def get_2D_R_boundary(self, nrod=100, xlim=(-5,5), *args):
152 """
153 Fence off!
154 nrod - number of rods in fencing
155 """
156
157 xbound = np.linspace(xlim[0], xlim[1], nrod, endpoint=True)
158
159 selfnvar = len(self._betas)-1
160 # g= a*X1 + b*X2 + 0*X3 + 0*X4 + ... + c
161 a = self._betas[0]
162 b = self._betas[1]
163 c = self._betas[-1]
164
165 # 1D je spíše vtip
166 if selfnvar == 1:
167 return (-c/a)
168 else:
169 # sample compatible
170 # малы транспонировать кароно? Озьы кулэ!
171 bound_R = np.array((xbound, -c/b + (-a/b)*xbound)).T
172 # tuple of tuple
173 return (Ingot(bound_R),)
174
175
176 class Z_sum:
177 """
178 suma velicin plus beta*sqrt(Nvar. )
179 Pro IID Gaussian ma tohle ind. spol. beta = beta
180 The same as Linear_nD, but defined via
181 beta in sense of reliability index
182 """
183 def __init__(self, nvar, beta_exact):
184 self._nvar = nvar
185 self._beta_exact = beta_exact
186
187 # sign
188 def __repr__(self):
189 return 'Z_sum(%s, %s)' % (repr(self._nvar), repr(self._beta_exact))
190
191 def __call__(self, input_sample):
192 # očekávam, že get_R_coordinates mně vrátí 2D pole
193 sample = get_R_coordinates(input_sample, self._nvar)
194 g = np.sum(sample, axis=1) + self._beta_exact * np.sqrt(self._nvar)
195 return SampleBox(input_sample, g, repr(self))
196
197 # Fence off!
198 def get_2D_R_boundary(self, nrod=100, xlim=(-5,5), *args):
199 """
200 Fence off!
201 nrod - number of rods in fencing
202 """
203
204 xbound = np.linspace(xlim[0], xlim[1], nrod, endpoint=True)
205
206 # g= a*X1 + b*X2 + 0*X3 + 0*X4 + ... + c
207 a = 1
208 b = 1
209 c = self._beta_exact * np.sqrt(self._nvar)
210
211 # sample compatible
212 # малы транспонировать кароно? Озьы кулэ!
213 bound_R = np.array((xbound, -c/b + (-a/b)*xbound)).T
214 # tuple of tuple
215 return (Ingot(bound_R),)
216
217
218
219 class Z_prod:
220 """
221 soucin velicin plus nějaká konstanta
222 # g= X1 * X2 * X3 * X4 + c
223 """
224 # tenhle model ani nvar si neukladá, tohle vůbec neřeší
225 def __init__(self, const):
226 self._const = const
227
228 # sign
229 def __repr__(self):
230 return 'Z_prod(%s)' % repr(self._const)
231
232 def __call__(self, input_sample):
233 # očekávam, že get_R_coordinates mně vrátí 2D pole
234 sample = get_R_coordinates(input_sample)
235 g = np.prod(sample, axis=1) + self._const
236 return SampleBox(input_sample, g, repr(self))
237
238 # Fence off!
239 def get_2D_R_boundary(self, nrod=100, *args):
240 """
241 Fence off!
242 nrod - number of rods in fencing
243 """
244 # g= X1 * X2 + c
245 # a^2 = 2*X^2
246 # a=b= X * sqrt(2)
247 # a^2 = 2*c
248 # r = a*b / np.sqrt(b**2 * np.cos(phi)**2 - a**2 * np.sin(phi)**2)
249
250 c = self._const
251 _c = np.sign(c)
252 # náš oblibený trik - hranici nakreslime pomoci polárních souřádnic
253 phi = np.linspace(0.25*np.pi, (0.25+_c/2)*np.pi, nrod , endpoint=False)[1:]
254 r = np.sqrt(2*c / (np.sin(phi)**2 - np.cos(phi)**2))
255 bound_x_left = r * np.cos(phi+np.pi/4)
256 bound_y_left = r * np.sin(phi+np.pi/4)
257
258 phi = np.linspace(-0.75*np.pi, (_c/2-0.75)*np.pi, nrod , endpoint=False)[1:]
259 r = np.sqrt(2*c / (np.sin(phi)**2 - np.cos(phi)**2))
260 bound_x_right = r * np.cos(phi+np.pi/4)
261 bound_y_right = r * np.sin(phi+np.pi/4)
262
263 # sample compatible
264 # малы транспонировать кароно? Озьы кулэ!
265 bound_R_left = np.array((bound_x_left, bound_y_left)).T
266 bound_R_right = np.array((bound_x_right, bound_y_right)).T
267 # tuple of samples
268 return (Ingot(bound_R_left), Ingot(bound_R_right))
269
270
271
272 class Z_min:
273 """
274 min velicin plus nějaká konstanta
275 # g= min(X1, X2, X3, X4) + c
276 """
277 def __init__(self, const):
278 self._const = const
279 self.get_2D_R_boundary = GetQuadrantBoundary2D(center_point=(-const,-const), quadrant='I')
280
281 # sign
282 def __repr__(self):
283 return 'Z_min(%s)' % repr(self._const)
284
285 def __call__(self, input_sample):
286 # očekávam, že get_R_coordinates mně vrátí 2D pole
287 sample = get_R_coordinates(input_sample)
288 g = np.min(sample, axis=1) + self._const
289 return SampleBox(input_sample, g, repr(self))
290
291 # samotná "volaná" se určí v __init__
292 # trik aby se nezabindila
293 @staticmethod
294 def get_2D_R_boundary(): return None
295
296
297
298 class Z_sumexp:
299 """
300 """
301 def __init__(self, const):
302 self._const = const
303
304 # sign
305 def __repr__(self):
306 return 'Z_sumexp(%s)' % repr(self._const)
307
308 def __call__(self, input_sample):
309 # očekávam, že get_R_coordinates mně vrátí 2D pole
310 sample = get_R_coordinates(input_sample)
311 g = np.sum(np.exp(-(sample**2)), axis=1) + self._const
312 return SampleBox(input_sample, g, repr(self))
313
314 # Fence off!
315 def get_2D_R_boundary(self, nrod=100, xlim=(-5,5), ylim=(-5,5)):
316 """
317 Fence off!
318 nrod - number of rods in fencing
319 """
320
321
322 def e_bound(xbound): return np.sqrt(-np.log(-self._const - np.exp(-xbound**2)))
323
324 # let's mirror about (s,s) point
325 # 0 = 2*e^(-s^2)+c
326 # log(-c/2) = -s^2
327 # s = sqrt(-log(-c/2))
328 s = np.sqrt(-np.log(-self._const/2))
329 xmin = min(*xlim, -s-1)
330 xmax = max(*xlim, s+1)
331 ymin = min(*ylim, -s-1)
332 ymax = max(*ylim, s+1)
333
334 xb_1eft = np.linspace(xmin, -s, nrod, endpoint=False)
335 xb_right = np.linspace(xmax, s, nrod, endpoint=False)
336 yb_up = np.linspace(s, ymax, nrod)
337 yb_down = np.linspace(-s, ymin, nrod)
338
339
340 # numerace je náhodná
341 bound_R_1 = np.array((np.append(xb_1eft, -e_bound(yb_up)), np.append(e_bound(xb_1eft), yb_up))).T
342 bound_R_2 = np.array((np.append(xb_1eft, -e_bound(yb_down)), np.append(-e_bound(xb_1eft), yb_down))).T
343 bound_R_3 = np.array((np.append(xb_right, e_bound(yb_up)), np.append(e_bound(xb_right), yb_up))).T
344 bound_R_4 = np.array((np.append(xb_right, e_bound(yb_down)), np.append(-e_bound(xb_right), yb_down))).T
345
346 # sample compatible
347 # tuple of samples
348 return (Ingot(bound_R_1), Ingot(bound_R_2), Ingot(bound_R_3), Ingot(bound_R_4))
349
350
351
352
353 class S_ballSin2D:
354 """
355 c = 0.5 # wave amplitude in Gaussian space
356 d = 3.0 # average of sine fiunction in Gaussian space
357 k = 6 # number of sine waves (design points)
358 """
359 def __init__(self, c, d, k):
360 self._c = c
361 self._d = d
362 self._k = k
363
364 # sign
365 def __repr__(self):
366 return 'S_ballSin2D(%s,%s,%s)' % (self._c, self._d, self._k)
367
368 def __call__(self, input_sample):
369 # očekávam, že get_R_coordinates mně vrátí 2D pole
370 sample = get_R_coordinates(input_sample, 2)
371
372 R2 = np.sum(np.square(sample), axis=1)
373 R = np.sqrt(R2)
374 phi = np.arctan2(sample[:,1] , sample[:,0]) #arctan2(y,x)
375 rmax = self._c * np.sin(self._k * phi) + self._d
376 g = rmax - R
377 return SampleBox(input_sample, g, repr(self))
378
379 # Fence off!
380 def get_2D_R_boundary(self, nrod=100, *args):
381 """
382 Fence off!
383 nrod - number of rods in fencing
384 """
385
386 phi = np.linspace(0, 6.283185307, nrod , endpoint=True)
387 r = self._c * np.sin(self._k * phi) + self._d
388 bound_x = r * np.cos(phi)
389 bound_y = r * np.sin(phi)
390
391 # sample compatible
392 # малы транспонировать кароно? Озьы кулэ!
393 bound_R = np.array((bound_x, bound_y)).T
394 # tuple of samples
395 return (Ingot(bound_R),)
396
397
398 class Z_sumsq:
399 """
400 """
401 def __init__(self, const):
402 self._const = const
403
404 # sign
405 def __repr__(self):
406 return 'Z_sumsq(%s)' % repr(self._const)
407
408 def __call__(self, input_sample):
409 # očekávam, že get_R_coordinates mně vrátí 2D pole
410 sample = get_R_coordinates(input_sample)
411 g = np.sum(sample**2, axis=1) - self._const
412 return SampleBox(input_sample, g, repr(self))
413
414 # Fence off!
415 def get_2D_R_boundary(self, nrod=100, *args):
416 """
417 Fence off!
418 nrod - number of rods in fencing
419 """
420
421 phi = np.linspace(0, 2*np.pi, nrod , endpoint=True)
422 r = np.sqrt(self._const)
423 bound_x = r * np.cos(phi)
424 bound_y = r * np.sin(phi)
425
426 # sample compatible
427 # малы транспонировать кароно? Озьы кулэ!
428 bound_R = np.array((bound_x, bound_y)).T
429 # tuple of samples
430 return (Ingot(bound_R),)
431
432
433
434 class S_ball:
435 """
436 Find 10 differences with Z_sumsq
437 """
438 def __init__(self, r):
439 self._r = r
440
441 # sign
442 def __repr__(self):
443 return 'S_ball(%s)' % repr(self._r)
444
445 def __call__(self, input_sample):
446 # očekávam, že get_R_coordinates mně vrátí 2D pole
447 sample = get_R_coordinates(input_sample)
448 R2 = np.sum(np.square(sample), axis=1)
449 g = self._r**2 - R2
450 return SampleBox(input_sample, g, repr(self))
451
452 # Fence off!
453 def get_2D_R_boundary(self, nrod=100, *args):
454 """
455 Fence off!
456 nrod - number of rods in fencing
457 """
458 phi = np.linspace(0, 6.283185307, nrod, endpoint=True)
459 r = self._r
460 bound_x = r * np.cos(phi)
461 bound_y = r * np.sin(phi)
462
463 # sample compatible
464 # малы транспонировать кароно? Озьы кулэ!
465 bound_R = np.array((bound_x, bound_y)).T
466 # tuple of samples
467 return (Ingot(bound_R),)
468
469
470 class Exp_P:
471 """
472 g = y - 1./np.exp(x)**5
473 """
474 def __init__(self, k=1., pow=5):
475 self._k = k
476 self._pow = pow
477
478 # sign
479 def __repr__(self):
480 return 'Exp_P(%s, %s)' % (self._k, self._pow)
481
482 def __call__(self, input_sample):
483 # očekávam, že get_R_coordinates mně vrátí 2D pole
484 sample = get_R_coordinates(input_sample, 2)
485
486 x = sample[:,0]
487 y = sample[:,1]
488 g = y - self._k/np.exp(x)**self._pow
489 return SampleBox(input_sample, g, repr(self))
490
491 # Fence off!
492 def get_2D_R_boundary(self, nrod=100, xlim=(-5,5), *args):
493 """
494 Fence off!
495 nrod - number of rods in fencing
496 """
497
498 xbound = np.linspace(xlim[0], xlim[1], nrod, endpoint=True)
499
500 bound_y = self._k/np.exp(xbound)**self._pow
501
502 # sample compatible
503 # малы транспонировать кароно? Озьы кулэ!
504 bound_R = np.array((xbound, bound_y)).T
505 # tuple of samples
506 return (Ingot(bound_R),)
507
508
509 class Sin2D:
510 """
511 """
512 def __init__(self, kx=-1/4., ky=-1, kxsin=5, const=5):
513 self._kx = kx
514 self._ky = ky
515 self._kxsin = kxsin
516 self._const = const
517
518 # sign
519 def __repr__(self):
520 return 'Sin2D(%s, %s, %s, %s)' % (self._kx, self._ky, self._kxsin, self._const)
521
522 def __call__(self, input_sample):
523 # očekávam, že get_R_coordinates mně vrátí 2D pole
524 sample = get_R_coordinates(input_sample, 2)
525
526 x = sample[:,0]
527 y = sample[:,1]
528 g = self._kx * x + self._ky * y + np.sin(self._kxsin*x) + self._const
529 return SampleBox(input_sample, g, repr(self))
530
531 # Fence off!
532 def get_2D_R_boundary(self, nrod=100, xlim=(-5,5), *args):
533 """
534 Fence off!
535 nrod - number of rods in fencing
536 """
537 xbound = np.linspace(xlim[0], xlim[1], nrod, endpoint=True)
538
539 bound_y = -(self._kx * xbound + np.sin(self._kxsin * xbound) + self._const) / self._ky
540
541 # sample compatible
542 # малы транспонировать кароно? Озьы кулэ!
543 bound_R = np.array((xbound, bound_y)).T
544 # tuple of samples
545 return (Ingot(bound_R),)
546
547
548
549 class Prod_FourBetas:
550 """
551 g = beta^2/2 - |x1 * x2|
552 """
553 def __init__(self, beta=2.0):
554 self._beta = beta
555
556 # sign
557 def __repr__(self):
558 return 'Prod_FourBetas(beta=%s)' % repr(self._beta)
559
560 def __call__(self, input_sample):
561 # očekávam, že get_R_coordinates mně vrátí 2D pole
562 sample = get_R_coordinates(input_sample)
563
564 g = self._beta**2/2.0 - np.prod(np.abs(sample), axis=1)
565 return SampleBox(input_sample, g, repr(self))
566
567 # Fence off!
568 def get_2D_R_boundary(self, nrod=100, xlim=(-5,5), ylim=(-5,5)):
569 """
570 Fence off!
571 nrod - number of rods in fencing
572 """
573 # zde vynechal abs(), ale úpravil znaménka dolů
574 # don't ask me why. Ачим но уг тодӥськы.
575 def e_bound(xbound): return self._beta**2/2 / xbound
576
577 # let's mirror about (s,s) point
578 # 0 = beta^2/2 - s^2
579 # beta^2/2 = s^2
580 # s = beta/sqrt(2)
581 s = self._beta / np.sqrt(2)
582 xmin = min(*xlim, -s-1)
583 xmax = max(*xlim, s+1)
584 ymin = min(*ylim, -s-1)
585 ymax = max(*ylim, s+1)
586
587 xb_1eft = np.linspace(xmin, -s, nrod, endpoint=False)
588 xb_right = np.linspace(xmax, s, nrod, endpoint=False)
589 yb_up = np.linspace(s, ymax, nrod)
590 yb_down = np.linspace(-s, ymin, nrod)
591
592
593 # numerace je náhodná. Je tu hračka se znaménky.
594 bound_R_1 = np.array((np.append(xb_1eft, -e_bound(yb_up)), np.append(-e_bound(xb_1eft), yb_up))).T
595 bound_R_2 = np.array((np.append(xb_1eft, e_bound(yb_down)), np.append(e_bound(xb_1eft), yb_down))).T
596 bound_R_3 = np.array((np.append(xb_right, e_bound(yb_up)), np.append(e_bound(xb_right), yb_up))).T
597 bound_R_4 = np.array((np.append(xb_right, -e_bound(yb_down)), np.append(-e_bound(xb_right), yb_down))).T
598
599 # sample compatible
600 # tuple of samples
601 return (Ingot(bound_R_1), Ingot(bound_R_2), Ingot(bound_R_3), Ingot(bound_R_4))
602
603
604
605 class BlackSwan2D:
606 """
607 a = 2.0 # boundary for x1
608 b = 5.0 # boundary for x2
609 y = np.where(sim[:,0] <= a, sim[:,0], sim[:,1])
610 # pro x1 <= a y = x1
611 # pro x1 > a y = x2
612 g = b - y # failure for b<y
613 """
614 def __init__(self, a=2.0, b=5.0):
615 self._a = a
616 self._b = b
617 if a<b:
618 self.get_2D_R_boundary = GetQuadrantBoundary2D(center_point=(a, b), quadrant='I')
619
620 # sign
621 def __repr__(self):
622 return 'BlackSwan2D(%s, %s)' % (self._a, self._b)
623
624 def __call__(self, input_sample):
625 # očekávam, že get_R_coordinates mně vrátí 2D pole
626 sample = get_R_coordinates(input_sample, 2)
627
628 y = np.where(sample[:,0] <= self._a, sample[:,0], sample[:,1])
629 g = self._b - y # failure for b<y
630 return SampleBox(input_sample, g, repr(self))
631
632
633 # samotná "volaná" se určí v __init__
634 # trik aby se nezabindila
635 @staticmethod
636 def get_2D_R_boundary(*args, **kwargs):
637 # jako kdyby .get_2D_R_boundary nebyla vůbec definována.
638 raise AttributeError
639
640
641
642 class Metaballs2D:
643 """
644 """
645 def __init__(self, const=5):
646 # sebemenší parametrizace
647 self._const = const
648
649 # sign
650 def __repr__(self):
651 return 'Metaballs2D(%s)' % repr(self._const)
652
653 def __call__(self, input_sample):
654 # očekávam, že get_R_coordinates mně vrátí 2D pole
655 sample = get_R_coordinates(input_sample, 2)
656
657 x1 = sample[:,0]
658 x2 = sample[:,1]
659
660 # auxiliary variables
661 y1 = 4/9*(x1 + 2 )**2 + 1/25 * (x2 )**2
662 y2 = 1/4*(x1 - 2.5)**2 + 1/25 * (x2-0.5)**2
663 g = 30.0/( y1**2 + 1.0 ) + 20.0/( y2**2 + 1.0 ) - self._const
664 return SampleBox(input_sample, g, repr(self))
665
666 #hranice poruchy ӧвӧл :(
667
668
669
670 class Logistic2D:
671 """
672 """
673 def __init__(self, c1=5, c2=4, easy_version=True):
674 # sebemenší parametrizace
675 self._c1 = c1
676 self._c2 = c2
677 self.easy_version = easy_version
678
679 # For both versions
680
681 self.get_2D_R_boundary = GetQuadrantBoundary2D(center_point=(c1,-c2), quadrant='II')
682
683 def __call__(self, input_sample):
684 # očekávam, že get_R_coordinates mně vrátí 2D pole
685 sample = get_R_coordinates(input_sample, 2)
686
687 x1 = sample[:,0]
688 x2 = sample[:,1]
689
690 # auxiliary variables
691 y1 = self._c1 - x1
692 y2 = self._c2 + x2
693 y3 = 1.0/(1+np.exp(-2.0*y2)) - 0.5
694
695 if self.easy_version:
696 g = np.minimum(y1,y2) # easy version for SuS
697 else:
698 g = np.minimum(y1,y3) # difficult version for SuS
699 return SampleBox(input_sample, g, repr(self))
700
701 def __repr__(self):
702 return 'Logistic2D(%s, %s, easy_version=%s)'%(self._c1, self._c2, self.easy_version)
703
704 def pf_expression(self, f_model):
705 """
706 We trying to say how to calculate pf
707 to someone, who will know actual distribution
708 """
709 a = f_model.marginals[0].sf(self._c1)
710 b = f_model.marginals[1].cdf(-self._c2)
711 # subtract the twice calculated intersection
712 return a + b - a*b, 'exact solution'
713
714 @staticmethod
715 def get_2D_R_boundary(): return None
716
717
718
719 class CosExp2D:
720 """
721 """
722 def __init__(self, s=5):
723 # sebemenší parametrizace
724 self._s = s
725
726 # sign
727 def __repr__(self):
728 return 'CosExp2D(s=%s)' % repr(self._s)
729
730 def __call__(self, input_sample):
731 # očekávam, že get_R_coordinates mně vrátí 2D pole
732 sample = get_R_coordinates(input_sample)
733
734 # auxiliary variables
735 s = self._s
736 # g = cos((np.exp(-xm-s ))*xm) * np.exp(-(x +s )/3)
737 g = np.cos( ( np.exp(-sample[:,0] - s ) )*sample[:,0]) * np.exp( -(sample[:,0] + s )/3 )
738 return SampleBox(input_sample, g, repr(self))
739
740 # Fence off!
741 def get_2D_R_boundary(self, nrod=100, xlim=(-5,5), ylim=(-5,5)):
742 """
743 Fence off!
744 nrod - number of rods in fencing
745 """
746
747 if self._s == 5:
748 # it is not mine
749 xa = -4.05229846333861
750 xb = -4.95067172463682
751 xc = -5.37859367619679
752 xd = -5.66345816541508
753 xe = -5.87765022259327
754 xf = -6.04950202015156
755 xg = -6.19309680892552
756
757 # ikska
758 xes = (xa, xb, xc, xd, xe, xf, xg)
759
760 boundaries = []
761 ymin, ymax = ylim
762
763 for x in xes:
764 xbound = np.full(nrod, x)
765 ybound = np.linspace(ymin, ymax, nrod, endpoint=True)
766 # sample compatible
767 # малы транспонировать кароно? Озьы кулэ!
768 bound_R = np.vstack((xbound, ybound)).T
769 boundaries.append(Ingot(bound_R))
770
771
772 return boundaries
773
774
775
776 else:
777 # jako kdyby .get_2D_R_boundary nebyla vůbec definována.
778 raise AttributeError("Hranice poruchy pro s!=5 není spočitana")
779
780
781
782
783
784
785 #
786 # Free functions
787 #
788
789 # signature
790 #inspect.currentframe().f_code.co_name
791
792
793 def piecewise_2D_linear(input_sample):
794 selfnvar = 2
795 # očekávam, že get_R_coordinates mně vrátí 2D pole
796 sample = get_R_coordinates(input_sample, selfnvar)
797 x1, x2 = sample[:,0], sample[:,1]
798 g1 = np.where(x1 > 3.5, 4-x1, 0.85-0.1*x1)
799 g2 = np.where(x2 > 2, 0.5-0.1*x2, 2.3-x2)
800 g = np.min((g1,g2), axis=0)
801 return SampleBox(input_sample, g, 'piecewise_2D_linear')
802
803 # boundary
804 piecewise_2D_linear.get_2D_R_boundary = GetQuadrantBoundary2D(center_point=(4,5), quadrant='III')
805 piecewise_2D_linear.pf_expression = lambda fm, a=4, b=5: (fm.marginals[0].sf(a) + fm.marginals[1].sf(b) - fm.marginals[0].sf(a)*fm.marginals[1].sf(b), 'exact solution')
806
807
808
809
810 def non_chi_squares(input_sample):
811 selfnvar = 2
812 # očekávam, že get_R_coordinates mně vrátí 2D pole
813 sample = get_R_coordinates(input_sample, selfnvar)
814 x1, x2 = sample[:,0], sample[:,1]
815 g = 0.1 * (52 - 1.5 * x1**2 - x2**2)
816 return SampleBox(input_sample, g, 'non_chi_squares')
817
818
819
820
821 def branin_2D(input_sample):
822 """
823 Rescaled Branin function
824 """
825 selfnvar = 2
826 # očekávam, že get_R_coordinates mně vrátí 2D pole
827 sample = get_R_coordinates(input_sample, selfnvar)
828 x1, x2 = sample[:,0], sample[:,1]
829 g = 80 - ((15*x2 - 5/(4*np.pi**2)*(15*x1-5)**2 + 5/np.pi*(15*x1-5)-6)**2 + 10*(1-1/8/np.pi)*np.cos(15*x1-5) + 10)
830 return SampleBox(input_sample, g, 'branin_2D')
831
832
833
834
835
836 def four_branch_2D(input_sample):
837 """
838 Four branch system
839 """
840 selfnvar = 2
841 # očekávam, že get_R_coordinates mně vrátí 2D pole
842 sample = get_R_coordinates(input_sample, selfnvar)
843 x1, x2 = sample[:,0], sample[:,1]
844 g1 = 3 + 0.1*(x1 - x2)**2 - (x1 + x2)/np.sqrt(2)
845 g2 = 3 + 0.1*(x1 - x2)**2 + (x1 + x2)/np.sqrt(2)
846 g3 = (x1 - x2) + 7/np.sqrt(2)
847 g4 = (x2 - x1) + 7/np.sqrt(2) # byl tu překlep v članku
848 g = np.min((g1, g2, g3, g4), axis=0)
849 return SampleBox(input_sample, g, 'four_branch_2D')
850
851
852
File gp_plot.py added (mode: 100644) (index 0000000..5d721d1)
1 #!/usr/bin/env python
2 # coding: utf-8
3
4 import PyGnuplot as gp
5 import os
6
7 # nikdo mi neuvěří, že by tohle postačílo a nebylo by nutné tohlensto furt úpravovat
8 def gp_plot(sample_box, space='R', terminal='png', filename=''):
9 if not filename:
10 filename = 'store/%s_%s_%s'%(sample_box.gm_signature, space, sample_box.nsim)
11 if space in ['Rn', 'GK', 'G']:
12 gp.c('set autoscale xy')
13 gp.c('set size square')
14 gp.c('set zeroaxis')
15 elif space in ['P', 'U']:
16 gp.c('set xrange [0:1]')
17 gp.c('set yrange [0:1]')
18 gp.c('set size square')
19 #gp.c('set autoscale')
20 gp.c('unset zeroaxis')
21 else: # R teda?
22 gp.c('set size noratio')
23 gp.c('set autoscale')
24 gp.c('unset zeroaxis')
25
26 gp.c('set terminal ' + terminal)
27 gp.c('set output "%s.%s"'%(filename, terminal))
28 if os.name == 'posix':
29 gp.c('set decimalsign locale "POSIX"')
30
31 # legenda
32 gp.c('unset key')
33
34 # se mi zda, že gp bere data v řadcích
35 f_name = "%s_failure.dat" % (filename)
36 s_name = "%s_success.dat" % (filename)
37 gp.s(getattr(sample_box.failure_samples, space).T, f_name)
38 gp.s(getattr(sample_box.success_samples, space).T, s_name)
39
40
41 # rozkaz, který předaváme gnuplotovi
42 gp_plot = 'plot "%s" title "Success points" w p lc rgb "green", "%s" title "Failure points" w p lc rgb "red"' % (s_name, f_name)
43
44 # Kružničky chcete?
45 # Кружочки ннада?
46 if space in ['Rn', 'G']:
47 gp.c('set parametric')
48 for i in range(5):
49 lw = 2 - i*0.3
50 gp_plot += ', cos(t)*%s,sin(t)*%s notitle w l lc rgb "black" lw %s'%(i+1, i+1, lw)
51
52 # ne všichni majó definované hranice
53 try:
54 bounds = sample_box.get_2D_boundary()
55
56 for i in range(len(bounds)):
57 bound = getattr(bounds[i], space).T
58 gp.s(bound, "%s_boundary_%s.dat"%(filename, i+1))
59 gp_plot += ', "%s_boundary_%s.dat" notitle w l lc rgb "blue"'%(filename, i+1)
60 except AttributeError:
61 pass
62
63 # Plot!
64 gp.c(gp_plot)
65
66
67
68 # nikdo mi neuvěří, že by tohle postačílo a nebylo by nutné tohlensto furt úpravovat
69 def plot(data2D, terminal='png', filename=''):
70 if not filename:
71 filename = 'store/plot_%s'%(len(data2D[0]))
72
73 gp.c('set terminal ' + terminal)
74 gp.c('set output "%s.%s"'%(filename, terminal))
75 if os.name == 'posix':
76 gp.c('set decimalsign locale "POSIX"')
77
78
79 # se mi zda, že gp bere data v řadcích
80 gp.s(data2D, filename+'.dat')
81
82 # Plot!
83 # rozkaz, který předaváme gnuplotovi
84 gp.c('plot "%s.dat" ' % (filename))
File plot.py added (mode: 100644) (index 0000000..d73fccb)
1 #!/usr/bin/env python
2 # coding: utf-8
3
4 # tohle je modul-wrapper k různým vizualizačním prostředkům
5
6 def empty_plot(sample_box, *args, **kwargs):
7 print("Plot: žel bohu, nič vám nakrelsiť nemůžu")
8
9 # optional dependences
10 try:# gnuplot
11 from . import gp_plot
12 plot2D = gp_plot.gp_plot
13 except:
14 plot2D = empty_plot
15
16
17 plot3D = empty_plot
18
19
20 try:# plot.ly
21 from . import plotly_plot
22 tri_estimation_graph = plotly_plot.tri_estimation_graph
23 except:
24 tri_estimation_graph = empty_plot
25
26
File plotly_plot.py added (mode: 100644) (index 0000000..8c8b0a9)
1 #!/usr/bin/env python
2 # coding: utf-8
3
4 import plotly.graph_objects as go
5
6
7 def tri_estimation_graph(bx, filename=''):
8 if not filename:
9 filename = 'store/%s_%s_%s_tri_estimation_graph'%(bx.gm_signature, bx.nsim, repr(bx))
10
11
12 # -1 = 'out', 0=success, 1=failure, 2=mix
13
14 # uplně hahoru - success
15 # outside
16 # mix
17 # uplně dolu - failure
18 x=[1,2,3,4]
19 fig = go.Figure()
20
21 fig.add_trace(go.Scatter(
22 x=x, y=[40, 20, 30, 40],
23 mode='lines',
24 line=dict(width=0.5, color='red'), #rgb(184, 247, 212)
25 name="Failure",
26 stackgroup='one',
27 groupnorm='fraction' # sets the normalization for the sum of the stackgroup
28 ))
29 fig.add_trace(go.Scatter(
30 x=x, y=[50, 70, 40, 60],
31 mode='lines',
32 line=dict(width=0.5, color='orange'),
33 name="Mixed",
34 stackgroup='one'
35 ))
36 fig.add_trace(go.Scatter(
37 x=x, y=[70, 80, 60, 70],
38 mode='lines',
39 line=dict(width=0.5, color='white'),
40 name="Outside",
41 stackgroup='one'
42 ))
43 fig.add_trace(go.Scatter(
44 x=x, y=[100, 100, 100, 100],
45 mode='lines',
46 line=dict(width=0.5, color='green'),
47 name="Success",
48 stackgroup='one'
49 ))
50
51 fig.update_layout(
52 showlegend=True,
53 #xaxis_type='category',
54 yaxis=dict(
55 type='linear',
56 range=[0, 1],
57 #ticksuffix='%'
58 ))
59
60 # zatím nechcu nikomu nic zobrazovat
61 #fig.show()
62 fig.write_html(filename + ".html")
63
64 # kdyby někdo chtěl statické obrázky
65 # musí mať psutil nainštalovany
66 try:
67 fig.write_image(filename + ".png")
68 except:
69 pass
70
71 # vratíme figuru,
72 # uživatel by mohl s ní eště něčo udělat
73 return fig
74
75
76
77
78
79 # 3D plot requires WebGL support
80 # which is not currently availiable under Haiku.
81 #
82 #import plotly.graph_objects as go
83 #import numpy as np
84 #
85 ## Helix equation
86 #t = np.linspace(0, 10, 50)
87 #x, y, z = np.cos(t), np.sin(t), t
88 #
89 #fig = go.Figure(data=[go.Scatter3d(x=x, y=y, z=z,
90 # mode='markers')])
91 #fig.show()
92 #
File reader.py added (mode: 100644) (index 0000000..fc18a41)
1
2 import csv
3 import numpy as np
4 from .samplebox import SampleBox
5 from .f_models import Ingot
6
7
8
9 class Reader:
10 """
11 stateful object to keep consistency of using append()
12 First rule of writing API - write example of use
13 # musel tedy tady bejt...
14
15 zkusím takovehle delegování
16
17 # reader bude pokažde otevirat/zavirat soubor, což není úplně ideální,
18 # ale zás,
19 # předpokladá se, že každej vzorek musí být schvalen vědeckou radou
20 # csv umožňuje dozápis
21 """
22
23 # piece of black magic
24 def __new__(cls, filename, f_model=None):
25 """
26 Здесь отталкиваемся от файла
27 """
28 sb = super().__new__(cls)
29 sb.filename = filename
30 try: # sample box nemá vůbec smysl schovavat
31 sb.sample_box = reader(filename, f_model)
32 sb.append_allowed = True
33 except FileNotFoundError:
34 # Штош...
35 sb.append_allowed = False
36 if f_model is not None:
37 sb.sample_box = SampleBox(f_model)
38 print("Reader:", filename + '.csv', "ӧвӧл")
39 return sb
40
41 @classmethod
42 def FromSampleBox(cls, filename, sample_box):
43 """
44 Здесь отталкиваемся от сэмплбоксу
45 """
46 sb = super().__new__(cls)
47 # nepotrebujeme žádné rozdělení, nic
48 sb.sample_box = sample_box
49 sb.filename = filename
50 sb.append_allowed = False
51 return sb
52
53 def __len__(self):
54 return self.sample_box.nsim
55
56 def __getitem__(sb, slice):
57 # stačí vratit sample_box
58 return sb.sample_box[slice]
59
60 def __getattr__(sb, attr):
61 # По всем (почти) вопросам обращайтесь
62 # на нашу горячую линию
63 if attr == 'sample_box':
64 return None
65 else:
66 return getattr(sb.sample_box, attr)
67
68 # def read(self):
69 # return self.__sbox
70
71 def force_read(self):
72 try:
73 self.sample_box = reader(self.filename, self.sample_box.sampled_plan)
74 self.append_allowed = True
75 return self.sample_box
76 except AttributeError:
77 self.sample_box = reader(self.filename)
78 self.append_allowed = True
79 return self.sample_box
80 except FileNotFoundError:
81 # Штош...
82 print("Reader:", self.filename + '.csv', "opravdu ӧвӧл")
83
84 def write(self):
85 export(self.filename, self.sample_box)
86 self.append_allowed = True
87
88 # что бы эта бурда могла делать?
89 # def force_write(self):
90 # self.__sbox = sample_box
91 # export(self.__filename, sample_box)
92
93 def add_sample(self, sample_box):
94 if self.append_allowed and (self.sample_box.gm_signature == sample_box.gm_signature):
95 self.sample_box.add_sample(sample_box)
96 append(self.filename, sample_box)
97 elif 'sample_box' in dir(self):
98 self.sample_box.add_sample(sample_box)
99 if self.sample_box.nsim > 0:
100 export(self.filename, self.sample_box)
101 self.append_allowed = True
102 else:
103 self.sample_box = sample_box
104 if self.sample_box.nsim > 0:
105 export(self.filename, self.sample_box)
106 self.append_allowed = True
107
108
109 # průbežný export
110 # if bx.filename:
111 # if gm_signature == input_sample.gm_signature:
112 # reader.append(bx.filename + '.csv', input_sample)
113 # else:
114 # bx.export(bx.filename)
115
116
117
118
119 #
120 # import simulations
121 #
122 def reader(filename, f_model=None):
123 rows = []
124 with open(filename + '.csv', 'r', newline='') as f:
125 reader = csv.reader(f, quoting=csv.QUOTE_NONNUMERIC)
126 for row in reader:
127 rows.append(row)
128
129 # předpokladam, že na prvních dvou řadcích jsou gm_signature a popísek
130 data = np.atleast_2d(rows[2:])
131
132 if f_model is None:
133 # veškeré datové řadky, sloupy - od (včetně) do (nezahrnuje)
134 return SampleBox(Ingot(data[:,:-2]), data[:,-2:-1].flatten(), rows[0][0])
135 else:
136 sample = f_model()
137 sample.add_sample(data[:,:-2])
138 return SampleBox(sample, data[:,-2:-1].flatten(), rows[0][0])
139
140
141
142 def append(filename, sample_box):
143 """
144 Святые угодники, объясните мне кто-нибудь, почему я здесь не использ..овал
145 context manager?
146 """
147 if sample_box.nsim == 0:
148 return False
149
150 with open(filename + '.csv', 'a', newline='') as csvfile:
151 csv_writer = csv.writer(csvfile, quoting=csv.QUOTE_NONNUMERIC)
152
153 # bacha! není tu žádná kontrola, co se kam zapisuje!
154 for i in range(sample_box.nsim):
155 row = [sample_box.R[i, j] for j in range(sample_box.nvar)]
156 row.append(sample_box.g_values[i])
157 row.append(int(sample_box.failsi[i]))
158 csv_writer.writerow(row)
159 #csvfile.close()
160
161 def Export(filename, sample_box):
162 """
163 vratíme nový Reader objekt
164 """
165 export(filename, sample_box)
166 return Reader.FromSampleBox(filename, sample_box)
167
168 def export(filename, sample_box):
169 if sample_box.nsim == 0:
170 return False
171
172 with open(filename + '.csv', 'w', newline='') as csvfile:
173 csv_writer = csv.writer(csvfile, quoting=csv.QUOTE_NONNUMERIC)
174
175 # gm_signature
176 csv_writer.writerow([sample_box.gm_signature])
177
178 # popísky
179 row = ['var ' + str(j+1) for j in range(sample_box.nvar)]
180 row.append('value')
181 row.append('failure')
182 csv_writer.writerow(row)
183
184 for i in range(sample_box.nsim):
185 row = [sample_box.R[i, j] for j in range(sample_box.nvar)]
186 row.append(sample_box.g_values[i])
187 row.append(int(sample_box.failsi[i]))
188 csv_writer.writerow(row)
189 # csvfile.close()
190
191
File samplebox.py added (mode: 100644) (index 0000000..278bfa0)
1 #!/usr/bin/env python
2 # coding: utf-8
3
4 """
5 SampleBox = sample_R(f_model) + g_values
6 """
7
8
9 import numpy as np
10
11
12 class SampleBox:
13 """
14 SampleBox = sample_R(f_model) + g_values
15
16 .sampled_plan object
17 .g_values
18 .failsi
19
20 Souřadnice primárně z prostoru modelu, ty co jsme rovnou
21 posilali do g_modelu!
22 """
23
24 # nechtěl bys nazvy proměnných?
25 def __new__(cls, sample_object, g_values=(), gm_signature=''):
26 """
27 Jedname tvrdě - není-li vstup konzistentní,
28 tak sbox vůbec nevytvaříme
29 """
30 g_values = np.atleast_1d(g_values)
31 if len(sample_object) == len(g_values):
32 sb = super(SampleBox, cls).__new__(cls)
33 # nepotrebujeme žádné rozdělení, nic
34 sb.sampled_plan = sample_object
35 sb.g_values = g_values
36 sb.gm_signature = gm_signature
37 return sb
38 else:
39 raise ValueError("Sample and g_value hasn't the same length. Zkrátka, do sebe nepatří")
40
41
42 def __str__(sb):
43 return '%s: %s at %s' %(sb.gm_signature, sb.g_values, sb.sampled_plan)
44
45 def __repr__(sb):
46 return 'SampleBox(%s, %s, %s)' %(repr(sb.sampled_plan), repr(sb.g_values), repr(sb.gm_signature))
47
48 def __len__(sb):
49 return len(sb.g_values)
50
51
52 def __call__(sb):
53 # я ваще хз
54 # offer next sample?
55 # do calculation?
56 # add to this sample?
57 # return new instance?
58 # мар, сакра, кароно?
59
60 # finally, we will offer sample to sample
61 # like BlackBox does
62 return sb.sampled_plan(1)
63
64
65 def __getitem__(sb, slice):
66 return SampleBox(sb.sampled_plan[slice], sb.g_values[slice], sb.gm_signature)
67
68
69 def __getattr__(sb, attr):
70 if attr == 'failsi':
71 # ~(g_values>0) to handle nan
72 return ~(sb.g_values>0)
73 elif attr == 'success_points':
74 return np.argwhere(sb.g_values>0).flatten()
75 elif attr == 'failure_points':
76 return np.argwhere(~(sb.g_values>0)).flatten()
77 elif attr == 'failure_samples':
78 return sb[~(sb.g_values>0)]
79 elif attr == 'success_samples':
80 return sb[sb.g_values>0]
81
82 # to je jistě k samplovi
83 else:
84 return getattr(sb.sampled_plan, attr)
85
86
87 def add_sample(sb, input_sb):
88 input_sb.consistency_check()
89
90 # ты чьих будешь?
91 # where are you from?
92 # are you one of us?
93 if sb.gm_signature == input_sb.gm_signature:
94 # dá se tuhle kontrolu jednoduše napálit, ale to neřeším
95 sb.sampled_plan.add_sample(input_sb.sampled_plan)
96 sb.g_values = np.append(sb.g_values, input_sb.g_values)
97
98 return sb.consistency_check()
99
100 # je to pro případ prázdného sample_boxu
101 elif sb.gm_signature == '':
102 # dá se tuhle kontrolu jednoduše napálit, ale to neřeším
103 sb.sampled_plan.add_sample(input_sb.sampled_plan)
104 sb.g_values = np.append(sb.g_values, input_sb.g_values)
105 sb.gm_signature = input_sb.gm_signature
106 return sb.consistency_check()
107 else:
108 #raise ValueError("Merge sa nám nějak nepovedol")
109 raise ValueError("gm_signatures are unequal. You are probably trying to merge data from different sources")
110
111 def new_sample(sb, input_sb):
112 """
113 We want to create new SampleBox object with our distribution (f_model)
114 but with data of input_sb (just like f_model.new_sample() does)
115 """
116 return SampleBox(sb.sampled_plan.new_sample(input_sb), input_sb.g_values, input_sb.gm_signature)
117
118 def consistency_check(sb):
119 if len(sb.sampled_plan)==len(sb.g_values):
120 return True
121 else:
122 # уг тодӥськы чик мар кароно
123 # ConsistencyError
124 raise ValueError('SampleBox is in an inconsistent state and nobody knows what to do with it')
125
File sball.py added (mode: 100644) (index 0000000..bac994a)
1 #!/usr/bin/env python
2 # coding: utf-8
3
4 import numpy as np
5 #from scipy import stats
6 from scipy import special # for S_ball
7 from scipy import integrate # for S_ball
8
9 # нельзя просто так взять и написать Ньютонову методу
10 # fails on nvar = 501, fails on Sball(500).get_r(0), fails on Sball(800).get_r(0.999)
11
12 class Sball:
13 def __init__(self, nvar):
14 self.nvar = nvar
15 if nvar != 2:
16 self.C = 2**(1-nvar/2) / special.gamma(nvar/2)
17 self.logC = (1-nvar/2)*np.log(2) - special.gammaln(nvar/2)
18 self.flex = self.current_r = np.sqrt(self.nvar-1)
19 self.flex_pf = self.current_pf = self.get_pf(self.flex)
20
21 def get_pf(self, r):
22 """
23 returns pf, i.e. complementary part of multidimensional Gaussian distribution
24 """
25 if self.nvar == 1:
26 #return 1 - 2**(1-nvar/2) / special.gamma(nvar/2) * (np.sqrt(np.pi)*special.erf(r/np.sqrt(2)))/np.sqrt(2)
27 return 1 - special.erf(r/1.4142135623730951)
28 elif self.nvar == 2:
29 return np.exp(-r**2/2)
30 elif self.nvar == 3:
31 #return 1 - 2**(1-nvar/2) / special.gamma(nvar/2) * (np.exp(-r**2/2)*(np.sqrt(np.pi)*np.exp(r**2/2)*special.erf(r/np.sqrt(2))-np.sqrt(2)*r))/np.sqrt(2)
32 return 1 - 0.5641895835477564 * (np.exp(-r**2/2)*(np.sqrt(np.pi)*np.exp(r**2/2)*special.erf(r/np.sqrt(2))-np.sqrt(2)*r))
33 elif self.nvar == 4:
34 return (r**2/2+1)*np.exp(-r**2/2)
35 elif self.nvar == 6:
36 return (r**4+4*r**2+8)*np.exp(-r**2/2)/8
37
38 # nvar=8: (48-(r^6+6*r^4+24*r^2+48)*e^(-r^2/2) / 2**(nvar/2))/48
39
40 # hračička ve hračce
41 # nemám žádnou jistotu, že tohle počítá přesněji
42 # ale ve výsokých dimenzích aspoň počítá
43 elif self.nvar % 2 == 0: # sudé
44 poly = [1]
45 for i in range(self.nvar-2, 0, -2):
46 poly.append(0)
47 poly.append(i*poly[-2])
48 return np.polyval(np.array(poly) / poly[-1], r) * np.exp(-r**2/2)
49
50 else:
51 try:
52 pf = self.C * integrate.quad(lambda x: np.exp(-(x**2)/2)*x**(self.nvar-1), r, np.inf)[0]
53 except OverflowError:
54 pf = 1 - self.C * integrate.quad(lambda x: np.exp(-(x**2)/2)*x**(self.nvar-1), 0, r)[0]
55
56 return pf
57
58 def get_r(self, desired_pf):
59 """
60 sball_inversion
61 returns r
62 """
63 if self.nvar == 2:
64 return np.sqrt(-2*np.log(desired_pf))
65 elif self.flex_pf == desired_pf:
66 return self.flex
67 else:
68 # je to jistější
69 self.current_r = self.flex
70 self.current_pf = previous_pf = self.flex_pf
71
72 self.__do_iter(desired_pf)
73 self.current_pf = self.get_pf(self.current_r)
74 # hrůza
75 # pokračujeme, dokud to nezkonverguje, přenejmenším pokud to konvergue a neosciluje.
76 while self.current_pf != previous_pf and self.current_pf != desired_pf\
77 and (self.current_pf > desired_pf or previous_pf < desired_pf):
78
79 previous_pf = self.current_pf
80 self.__do_iter(desired_pf)
81 self.current_pf = self.get_pf(self.current_r)
82
83 return self.current_r
84
85 def __do_iter(self, desired_pf):
86 r = self.current_r
87 denominator = (self.C * np.exp(-(r**2)/2)*r**(self.nvar-1))
88 if denominator != 0 and not np.isnan(denominator):
89 self.current_r += (self.current_pf - desired_pf) / denominator
90 else:
91 # zkombinujeme C a r^nvar, ale stejně nikoho to nezahraní
92 log_delta = np.log(abs(self.current_pf - desired_pf)) + (r**2)/2 - (np.log(r)*(self.nvar-1) + self.logC)
93 self.current_r += np.exp(log_delta)*np.sign(self.current_pf - desired_pf)
94
95 if self.current_r < 0:
96 self.current_r = r/2
97
98
99 def get_r_iteration(self, desired_pf):
100 """
101 Same as get_r, but do just one iteration
102 """
103
104
105 if self.nvar == 2:
106 return np.sqrt(-2*np.log(desired_pf)), desired_pf
107
108 # logaritmus je na nulu citelný
109 elif self.current_pf - desired_pf != 0:
110
111 # hrůza, nečitelný
112 # pokud je současné r-ko v jiné straně od chtěného r-ka, tak se vrátíme do inflexního bodu
113 if (self.flex_pf > self.current_pf) is (self.flex_pf < desired_pf):
114 # vstupní kontrola
115 self.current_r = self.flex
116 self.current_pf = self.flex_pf
117
118
119 r = self.current_r # pro výstupní kontrolu
120
121 self.__do_iter(desired_pf)
122
123
124 # vystupní kontrola
125 if (self.flex > self.current_r) is (self.flex < r):
126 # preskočili jsme inflexní bod
127 self.current_r = self.flex
128 self.current_pf = self.flex_pf
129 # ještě jednou
130 self.__do_iter(desired_pf)
131
132 self.current_pf = self.get_pf(self.current_r) # ne že bychom pf potrebovali v tomto kroce, ale...
133 return self.current_r, self.current_pf
134
135
136
137
File whitebox.py added (mode: 100644) (index 0000000..5134b7a)
1 #!/usr/bin/env python
2 # coding: utf-8
3
4 """
5 Zde leží whiteboxy
6 Zatimco BlackBox pěčlivě ukladá věškerá data,
7 věškeré sady vzorků, průběžné odhady a tak,
8 WhiteBox musí obsahovat jen pf_exact, které buď už předem zná,
9 nebo jej spočítá a není vůbec/nachren nutný cokoliv ukladat.
10
11 en:
12 f_model + g_model = pf
13 WhiteBox = [f_model, g_model, pf_exact]
14 pf_exact is most important part of WhiteBox
15 Knowledge of pf is the only reason to create WhiteBox
16
17 whitebox actually IS g_model PLUS:
18 .f f_model
19 .pf_exact
20 .pf_exact_method
21 """
22 import numpy as np
23 from scipy import stats
24 from scipy import special # for S_ball
25 from scipy import integrate # for S_ball
26
27 from .samplebox import SampleBox
28
29 from . import f_models
30 import copy
31 from . import g_models
32
33 from . import plot
34
35
36 class WhiteBox:
37 """
38 Bazová třida pro dědictví
39
40 úkolem whiteboxu je spočítat pf-ko
41 .pf_exact
42 .pf_exact_method
43 """
44 pf_exact_method = 'None'
45
46 def __init__(wt, f_model, g_model):
47 wt.gm = g_model
48 wt.f = f_model
49 # na začatku nemáme vzorky - pouze rozdělení a podpís
50 wt.sample_box = SampleBox(wt.f(), gm_signature=wt.gm_signature)
51
52 try: # no to jsme líný. Možná samotný g_model tuší jak se spočte pf-ko?
53 wt.pf_exact, wt.pf_exact_method = g_model.pf_expression(f_model)
54 except AttributeError:
55 pass
56
57 def __str__(wt):
58 return wt.__class__.__name__ + ' of' + str(wt.g_model)
59
60 def __repr__(wt):
61 return 'WhiteBox(%s, %s)' %(repr(wt.f), repr(wt.gm))
62
63 def __len__(wt):
64 return len(wt.sample_box)
65
66
67 def __call__(wt, sample=None):
68 if sample is None:
69 sample = wt.sample_box()
70
71 # zamykame se do sebe
72 result = wt.gm(sample)
73 wt.sample_box.add_sample(result)
74 return result
75
76
77 def __getitem__(self, slice):
78 self_copy = copy.copy(self)
79 self_copy.sample_box = self.sample_box[slice]
80 return self_copy
81
82 def __getattr__(wt, attr):
83 # co patři g_modelovi?
84 if attr == 'get_2D_R_boundary':
85 return wt.gm.get_2D_R_boundary
86 elif attr == 'gm_signature':
87 try: # byla volná funkce?
88 return wt.gm.__name__
89 # asi to byla trida?
90 except AttributeError:
91 return repr(wt.gm)
92
93
94 # co mělo být definováno ve WhiteBoxu? Ale teda není?
95 elif attr == 'pf_exact_method':
96 raise AttributeError
97
98 # пытка-непытка
99 elif attr == 'pf_exact':
100 if 'beta_exact' in wt.__dict__:
101 return stats.norm.cdf(-wt.beta_exact)
102 else:
103 # мы нищего не знаем
104 raise AttributeError("Nothing known about failure probability")
105
106 elif attr == 'beta_exact':
107 if 'pf_exact' in wt.__dict__:
108 return -stats.norm.ppf(wt.pf_exact)
109 else:
110 raise AttributeError("Nothing known about failure probability")
111
112
113 # branime sa rekurzii
114 # defend against recursion
115 elif attr == 'sample_box':
116 raise AttributeError
117
118 # zbytek teda nievím
119 else:
120 return getattr(wt.sample_box, attr)
121
122 # just plot, green points, red points...
123 plot2D = plot.plot2D
124 plot3D = plot.plot3D
125
126
127 def get_2D_boundary(wt, nrod=100, viewport_sample=None, viewport_space='R'):
128 """
129 Fence off!
130 nrod - number of rods in fencing
131 viewport_sample - limit points of viewport
132 (function will get xlim and ylim from there,
133 assuming there will be at least two points)
134 """
135
136 if (viewport_sample is not None): # and viewport_sample.nsim: #>0
137 breakpoint
138 if viewport_space=='R':
139 viewport_sample_R = viewport_sample
140 else:
141 viewport_sample_R = wt.f.new_sample(viewport_sample, viewport_space).R
142 else:
143 viewport_sample_R = wt.f.new_sample([[-7,-7],[7,7]], 'G').R
144
145 # should I tolerate nD?
146 viewport_sample_R = np.vstack((viewport_sample_R, wt.sample_box.R[:,0:2]))
147 xmin = np.min(viewport_sample_R[:,0])
148 xmax = np.max(viewport_sample_R[:,0])
149 ymin = np.min(viewport_sample_R[:,1])
150 ymax = np.max(viewport_sample_R[:,1])
151
152 # získám seznam polí
153 bounds_R = wt.get_2D_R_boundary(nrod, (xmin, xmax), (ymin, ymax))
154 # transformuji na seznam vzorků
155 return [wt.f.new_sample(bounds_R[i]) for i in range(len(bounds_R))]
156
157
158
159
160 # Monte Carlo, n-krátá realizace
161 def MC(wt, Nsim=int(1e6)):
162
163
164 # tohlensto může bejt dost těžkým
165 result = wt.gm(wt.f(Nsim))
166 # should I stay or should I go?
167 wt.sample_box.add_sample(result)
168
169 # je tu jakoby že g_model vždy vrací nějakej sample_box
170 pf_exact = np.count_nonzero(result.failsi)/Nsim
171
172 # šlo by to?
173 if wt.pf_exact_method == 'None' or wt.pf_exact_method == 'MC' and wt.Nsim <= Nsim:
174 wt.pf_exact = pf_exact
175 wt.Nsim = Nsim
176 wt.pf_exact_method = 'MC'
177
178 print('Monte Carlo estimation of pf is %s (%s simulations)'%(pf_exact, Nsim))
179 return result
180
181
182
183 # IS, (n-2)-krátá realizace, n>2
184 def IS(wt, Nsim=int(1e4), h_model=None, IS_mode='G'):
185 """
186 IS_mode - v jakých souřadnicích robím merge a jaká PDF použiváme?
187 může být 'R' nebo 'G'
188 jinde # čo jinde?
189 """
190
191 if h_model is not None:
192 wt.h = h_model
193 wt.IS_mode = IS_mode
194 elif 'h' not in wt.__dict__:
195 wt.h = f_models.UnCorD([stats.norm(0,2.5) for i in range(wt.f.nvar)])
196 wt.IS_mode = 'G'
197
198
199 #
200 # jdeme na to, koťě!
201 #
202
203 # zgenerujeme vzorky
204 # nic zajimavýho
205 wt.h = wt.h(Nsim)
206
207 # a teď bacha!
208 if wt.IS_mode == 'R':
209 # jestli máme to právé vzorkovácí rozdělení - tak nemáme čo robiť
210 to_sample = wt.f.new_sample(wt.h) # smerdží se to po R
211 # w like weights
212 wt.w = to_sample.pdf_R / wt.h.pdf_R
213 elif wt.IS_mode == 'G':
214 # tady musíme provést jeden trik
215 to_sample = wt.f.new_sample(wt.h.R, 'G') # R-ko smerdžíme ako G-čko
216 wt.w = to_sample.pdf_G / wt.h.pdf_R # snad je to správně
217 else:
218 # шо-то тут не то...
219 # čo blbnéš, kámo?
220 # What's going on with my IS_mode?
221 raise ValueError("IS_mode should be either 'R' or 'G'")
222
223 # vahy máme, jedeme dál
224 # sample_box jíž není prázdnej
225 result = wt.gm(to_sample)
226 wt.sample_box.add_sample(result)
227
228 # hodilo by sa to?
229 pf_exact = np.sum(wt.w[result.failsi])/Nsim
230
231 if wt.pf_exact_method in ('None', 'IS_norm', 'IS'):
232 wt.Nsim = Nsim
233 if pf_exact < 1:
234 wt.pf_exact = pf_exact
235 wt.pf_exact_method = 'IS'
236 else:
237 # ať mně nerobí ostudu
238 wt.pf_exact = np.sum(wt.w[result.failsi]) / np.sum(wt.w)
239 wt.pf_exact_method = 'IS_norm'
240
241 print('Importance Sampling pure estimation of pf is %s (%s simulations)'%(pf_exact, Nsim))
242 return result
243
244
245
246 class HyperPlane(WhiteBox): # куда ж без него...
247 def __init__(self, betas=(1,2,3)):
248 """
249 Class takes for inicialization tuple of betas
250 Betas are coeffitients in sense of Regression Analysis (well, not really)
251 g= a*X1 + b*X2 + c
252 betas=(a,b,c)
253 """
254 self._betas = betas
255 self.gm = g_models.Linear_nD(betas)
256 self.f = f_models.SNorm(len(betas)-1)
257 # na začatku nemáme vzorky - pouze rozdělení a podpís
258 self.sample_box = SampleBox(self.f, gm_signature=self.gm_signature)
259
260 # tady už je to ta, "náše" beta )
261 # beta = c/np.sqrt(a**2 + b**2)
262 self.beta_exact = betas[-1]/np.sqrt(np.sum(np.array(betas[:-1])**2))
263 self.pf_exact = stats.norm.cdf(-self.beta_exact)
264 self.pf_exact_method = 'FORM (exact solution)' # Ang, Tang and Pythagoras
265
266
267 def __str__(wt):
268 return 'HyperPlaneBox%sD'%(len(wt._betas)-1)
269
270 def __repr__(wt):
271 return 'HyperPlane(%s)' % repr(wt._betas)
272
273
274
275 class Weibull_Z_min(WhiteBox):
276 def __init__(self, wb_scales=(1,1), shape=5, **kwargs):
277 """
278 parametry pravdepodobnostniho rozdeleni pro Z_min, pripadne dalsi fce s Weib. velicinami
279 wb_scales=(1,1) - tuple of Weibull scale parameters, len(wb_scales)==nvar
280 shape = 5
281 je třeba zadat buď pf_exact, nebo konštantu u funkce minima Z_min
282 """
283 self.wb_scales = wb_scales
284 self.shape = 5
285 self.f = f_models.UnCorD([stats.weibull_min(shape, scale=sc_i) for sc_i in wb_scales])
286
287 # scale parametr minima z nvar Weibullovskych
288 # tohle by platilo pro stejná rozdělení
289 #sn = scale * nvar ** (-1.0 / shape)
290 # pro nás musí to být něco takovýho
291 sn = np.sum(np.power(wb_scales, -shape)) ** (-1.0 / shape)
292 self.rvweibmin = stats.weibull_min(shape, scale=sn)
293
294 # je třeba zadat buď pf_exact, nebo konštantu u funkce minima Z_min
295 self.pf_exact_method = 'exact solution'
296 if 'pf_exact' in kwargs:
297 self.pf_exact = kwargs['pf_exact']
298 self.const = -self.rvweibmin.ppf(self.pf_exact)
299 elif 'beta_exact' in kwargs:
300 self.beta_exact = kwargs['beta_exact']
301 self.const = -self.rvweibmin.ppf(self.pf_exact)
302 elif 'const' in kwargs:
303 self.const = kwargs['const']
304 self.pf_exact = self.rvweibmin.cdf(-self.const) # asi
305 else:
306 # no to teda uživatele пошли
307 self.pf_exact = 1e-4
308 self.const = -self.rvweibmin.ppf(self.pf_exact)
309
310 self.gm = g_models.Z_min(self.const)
311 # na začatku nemáme vzorky - pouze rozdělení a podpís
312 self.sample_box = SampleBox(self.f, gm_signature=self.gm_signature)
313
314 def __str__(self):
315 return 'Weibull_Z_min%sD'%(len(self.wb_scales))
316
317 def __repr__(self):
318 return 'Weibull_Z_min(%s, %s, pf_exact=%s)' % (repr(self.wb_scales), repr(self.shape), repr(self.pf_exact))
319
320
321
322
323 # já teda tridu zababachnu, ale že to teoreticky platí jsem neodvozoval
324 # UPD: testy neprochází, logicky hodnoty nesedí
325 # vůbec netuším jak by se to mohlo odvozovat
326 class Gaussian_Z_sumexp(WhiteBox):
327 def __init__(self, nvar=2, **kwargs):
328 """
329 je třeba zadat buď pf_exact, nebo konštantu u funkce Z_sumexp
330 """
331
332 # je tam předpoklad SNormu?
333 self.f = f_models.SNorm(nvar)
334
335 self.C1 = np.sqrt(np.sqrt(5) / 3. - 1. / 3.)
336 self.C2 = np.sqrt(3.) / 3.
337 # je třeba zadat buď pf_exact, nebo konštantu u funkce Z_sumexp
338 self.pf_exact_method = 'tešt solution'
339 if 'pf_exact' in kwargs:
340 self.pf_exact = kwargs['pf_exact']
341 self.C = self.beta_exact * self.C1 * np.sqrt(nvar) - self.C2 * nvar
342 elif 'beta_exact' in kwargs:
343 self.beta_exact = kwargs['beta_exact']
344 self.C = self.beta_exact * self.C1 * np.sqrt(nvar) - self.C2 * nvar
345 elif 'const' in kwargs:
346 self.const = kwargs['const']
347 self.C = self.const
348 self.beta_exact = (self.C + self.C2 * nvar) / self.C1 / np.sqrt(nvar)
349 elif 'C' in kwargs:
350 self.C = kwargs['C']
351 self.beta_exact = (self.C + self.C2 * nvar) / self.C1 / np.sqrt(nvar)
352 else:
353 # no to teda uživatele пошли
354 self.pf_exact = 1e-4
355 self.C = self.beta_exact * self.C1 * np.sqrt(nvar) - self.C2 * nvar
356
357
358 self.const = self.C
359 self.gm = g_models.Z_sumexp(self.const)
360 # na začatku nemáme vzorky - pouze rozdělení a podpís
361 self.sample_box = SampleBox(self.f, gm_signature=self.gm_signature)
362
363 def __str__(self):
364 return 'Gaussian_Z_sumexp%sD'%(self.nvar)
365
366 def __repr__(self):
367 return 'Gaussian_Z_sumexp(%s, pf_exact=%s)' % (repr(self.nvar), repr(self.pf_exact))
368
369
370
371 class SNorm_Z_sumsq(WhiteBox):
372 def __init__(self, nvar=2, **kwargs):
373 """
374 je třeba zadat buď pf_exact, nebo konštantu u funkce Z_sumsq
375 """
376
377 # je tu předpoklad SNormu, to vím
378 self.f = f_models.SNorm(nvar)
379
380 self.rvchisq = stats.chi2(nvar)
381
382 # je třeba zadat buď pf_exact, nebo konštantu u funkce Z_sumsq
383 self.pf_exact_method = 'exact solution'
384 if 'pf_exact' in kwargs:
385 self.pf_exact = kwargs['pf_exact']
386 self.C = self.rvchisq.ppf(self.pf_exact)
387 elif 'beta_exact' in kwargs:
388 self.beta_exact = kwargs['beta_exact']
389 self.C = self.rvchisq.ppf(self.pf_exact)
390 elif 'const' in kwargs:
391 self.const = kwargs['const']
392 self.C = self.const
393 self.pf_exact = self.rvchisq.cdf(self.C)
394 elif 'C' in kwargs:
395 self.C = kwargs['C']
396 self.pf_exact = self.rvchisq.cdf(self.C)
397 else:
398 # no to teda uživatele пошли
399 self.pf_exact = 1e-4
400 self.C = self.rvchisq.ppf(self.pf_exact)
401
402
403 self.const = self.C
404 self.gm = g_models.Z_sumsq(self.C)
405 # na začatku nemáme vzorky - pouze rozdělení a podpís
406 self.sample_box = SampleBox(self.f, gm_signature=self.gm_signature)
407
408 def __str__(self):
409 return 'SNorm_Z_sumsq%sD'%(self.nvar)
410
411 def __repr__(self):
412 return 'SNorm_Z_sumsq(%s, pf_exact=%s)' % (repr(self.nvar), repr(self.pf_exact))
413
414
415
416
417
418
419 class SNorm_S_ball(WhiteBox):
420 #r = 5.256521 # pf 1.00000404635e-06
421 def __init__(self, nvar=2, r=5.256521):
422
423
424 # SNorm
425 self.f = f_models.SNorm(nvar)
426
427
428 #
429 # pf, jen tak, hračka
430 #
431 self.pf_exact_method = 'precise solution'
432 if nvar == 1:
433 #self.pf_exact = 1 - 2**(1-nvar/2) / special.gamma(nvar/2) * (np.sqrt(np.pi)*special.erf(r/np.sqrt(2)))/np.sqrt(2)
434 self.pf_exact = 1 - special.erf(r/1.4142135623730951)
435 elif nvar == 2:
436 self.pf_exact = np.exp(-r**2/2)
437 elif nvar == 3:
438 #self.pf_exact = 1 - 2**(1-nvar/2) / special.gamma(nvar/2) * (np.exp(-r**2/2)*(np.sqrt(np.pi)*np.exp(r**2/2)*special.erf(r/np.sqrt(2))-np.sqrt(2)*r))/np.sqrt(2)
439 self.pf_exact = 1 - 0.5641895835477564 * (np.exp(-r**2/2)*(np.sqrt(np.pi)*np.exp(r**2/2)*special.erf(r/np.sqrt(2))-np.sqrt(2)*r))
440 elif nvar == 4:
441 self.pf_exact = (r**2/2+1)*np.exp(-r**2/2)
442 elif nvar == 6:
443 self.pf_exact = (r**4+4*r**2+8)*np.exp(-r**2/2)/8
444
445 # nvar=8: (48-(r^6+6*r^4+24*r^2+48)*e^(-r^2/2) / 2**(nvar/2))/48
446
447 # hračička ve hračce
448 # nemám žádnou jistotu, že tohle počítá přesněji
449 elif nvar % 2 == 0: # sudé
450 poly = [1]
451 for i in range(nvar-2, 0, -2):
452 poly.append(0)
453 poly.append(i*poly[-2])
454 self.pf_exact = np.polyval(np.array(poly) / poly[-1], r) * np.exp(-r**2/2)
455
456 else:
457 self.pf_exact = 1 - 2**(1-nvar/2) / special.gamma(nvar/2) * integrate.quad(lambda x: np.exp(-(x**2)/2)*x**(nvar-1), 0, r)[0]
458
459
460 self.r = r
461 self.gm = g_models.S_ball(r)
462 # na začatku nemáme vzorky - pouze rozdělení a podpís
463 self.sample_box = SampleBox(self.f, gm_signature=self.gm_signature)
464
465 def __str__(self):
466 return 'SNorm_S_ball%sD'%(self.nvar)
467
468 def __repr__(self):
469 return 'SNorm_S_ball(nvar=%s, r=%s)' % (repr(self.nvar), repr(self.r))
470
471
472 #
473 #corner_values = np.full(2**nvar, 1, np.int8) # -1 means inertní, 0 failure, 1 success.
474 #alpha = [1, 1]
475 #
476 #if fce_por == 'Sin2D':
477 # corner_values[0] = 1
478 # corner_values[3] = 0
479 # pf_exact = 4.1508e-4
480 #elif fce_por == 'S_ball':
481 # corner_values = np.full(2**nvar, 0, np.int8)
482 # pf_exact = 1 - 2**(1-nvar/2) / gamma(nvar/2) * integrate.quad(lambda x: np.exp(-(x**2)/2)*x**(nvar-1), 0, r)[0]
483 #elif fce_por == 'S_ballSin2D':
484 # corner_values = np.full(2**nvar, 0, np.int8)
485 # pf_exact = 0 # I don't know, really
486 #elif fce_por == 'Prod_FourBetas':
487 # corner_values = np.full(2**nvar, 0, np.int8) # dont know in any corner
488 # beta = 2.0
489 # pf_exact = 2*np.sqrt(2)*stats.norm.cdf(-beta) # true only for beta -> infinity!!
490 #elif fce_por == 'BlackSwan2D':
491 # corner_values[0] = 1
492 # corner_values[3] = 0
493 # #corner_values = np.full(2**nvar, 1, np.int8) # Success in all corners
494 # #corner_values[0] = 0 #failure somwehere in top right corner
495 # a = 2.0
496 # b = 5.0
497 # p = stats.norm.cdf(-a)*stats.norm.cdf(-b)
498 # # a<b
499 # pf_exact = p
500 # # a>b
501 # # pf_exact = stats.norm.cdf(a) - stats.norm.cdf(b) + p
502 #elif fce_por == 'Metaballs2D':
503 # corner_values = np.full(2**nvar, 0, np.int8) # dont know in any corner
504
505
506
507
508 #def get_quadrant_probability(center_point=(0,0), quadrant='I'):
509 """
510 sebemenší pomocná funkce pri hranici L tvaru
511 quadrants also сэрегъёс-compatible
512 #### CORNERS 2D #####
513 # print(сэрегъёс)
514 # numbering:
515 # 2 | 3
516 # -----|-----
517 # 0 | 1
518 """
519
520 #class Quadrant2D(WhiteBox):
521 # def __new__(cls, g_model, f_model=f_models.SNorm(2)):
522 # """
523 # Trik je v tom, že já odhaduji pf na základě hranici poruchy,
524 # prohlašenou g_modelem.
525 # g_model MUST have .mins or .maxs setted up!
526 # """
527 # if f_model.nvar != 2:
528 # raise ValueError("Reliability problem is supposed to be 2D")
529 #
530 # else:
531 # wt = super(Quadrant2D, cls).__new__(cls)
532 # wt.gm = g_model
533 # wt.f = f_model
534 # # na začatku nemáme vzorky - pouze rozdělení a podpís
535 # wt.sample_box = SampleBox(wt.f(), gm_signature=wt.gm_signature)
536 #
537 # f1, f2 = f_model.marginals
538 # try:
539 # (c1, k1), (c2, k2) = g_model.mins
540 # if k1 > 0:
541 # a = f1.cdf(-c1/k1)
542 # else:
543 # a = f1.sf(-c1/k1)
544 # if k2 > 0:
545 # b = f2.cdf(-c2/k2)
546 # else:
547 # b = f2.sf(-c2/k2)
548 #
549 # quadrant = g_model.get_2D_R_boundary.quadrant
550 # xc, yc = g_model.get_2D_R_boundary.center_point
551 #
552 # #quadrants also сэрегъёс-compatible
553 # #### CORNERS 2D #####
554 # # print(сэрегъёс)
555 # # numbering:
556 # # 2 | 3
557 # # -----|-----
558 # # 0 | 1
559 #
560 # wt.pf_exact_method = 'exact solution' # under condition of right g_model
561 # # mně nic hezčího prostě nenapadá(
562 # if self.quadrant in ('I', 3):
563 # xbound = np.append(np.full(nrod, xc), np.linspace(xc, xmax, nrod, endpoint=True))
564 # ybound = np.append(np.linspace(ymax, yc, nrod, endpoint=True), np.full(nrod, yc))
565 # elif self.quadrant in ('II', 2):
566 # xbound = np.append(np.linspace(xmin, xc, nrod, endpoint=True), np.full(nrod, xc))
567 # ybound = np.append(np.full(nrod, yc), np.linspace(yc, ymax, nrod, endpoint=True))
568 # elif self.quadrant in ('III', 0):
569 # xbound = np.append(np.linspace(xmin, xc, nrod, endpoint=True), np.full(nrod, xc))
570 # ybound = np.append(np.full(nrod, yc), np.linspace(yc, ymin, nrod, endpoint=True))
571 # else: # self.quadrant in ('IV', 1):
572 # xbound = np.append(np.full(nrod, xc), np.linspace(xc, xmax, nrod, endpoint=True))
573 # ybound = np.append(np.linspace(ymin, yc, nrod, endpoint=True), np.full(nrod, yc))
574 #
575 #elif fce_por == 'Logistic2D':
576 # a = 4.
577 # b = 5. #one line, second line and subtract the twice calculated intersection
578 # pf_exact = lambda a=4, b=5: stats.norm.cdf(-a) + stats.norm.cdf(-b) - stats.norm.cdf(-a)*stats.norm.cdf(-b)
579
580
581
582
583 # no pf information - no reason to create such wbox
584
585 #class UniformBranin2D(WhiteBox):
586 # def __init__(self):
587 #
588 # # Uniform-uniform
589 # self.f = f_models.UnCorD((stats.uniform, stats.uniform))
590 #
591 # self.gm = g_models.branin_2D
592 # # na začatku nemáme vzorky - pouze rozdělení a podpís
593 # self.sample_box = SampleBox(self.f, gm_signature=self.gm_signature)
594 #
595 # def __str__(self):
596 # return 'UniformBranin2D'
597 #
598 # def __repr__(self):
599 # return 'UniformBranin2D()'
600
601
Hints:
Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://rocketgit.com/user/iam-git/WellMet

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@ssh.rocketgit.com/user/iam-git/WellMet

Clone this repository using git:
git clone git://git.rocketgit.com/user/iam-git/WellMet

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a merge request:
... clone the repository ...
... make some changes and some commits ...
git push origin main