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)
dicebox.circumtri: employ _Exploration class. Keep naive CircumTri class in renamed module b8605fb24d55b3296ceac34afba541a5b7ee3070 I am 2022-12-15 09:33:59
convex_hull.QHull.get_exploration_vector: self -> hull fix dae47ef37b5871a98d2ea274cc35aeb2a4eebe1c I am 2022-12-15 09:30:31
qt_gui/qt_dicebox: add DumpExplorationWidget b687895f06c780418a12eea59bd052ad7cd348f3 I am 2022-12-15 01:31:14
dicebox: add helper _exploration module 836ae6cd12f1a04f1e2fc3423e46777d16ebad7d I am 2022-12-15 01:30:20
convex_hull: add get_exploration_vector() method 795259d91b64c732e60a83a1d9e3b89c2141b003 I am 2022-12-15 01:28:12
qt_gui.qt_gui: dot not create graph widgets if estimations are not present f070ed140a135a980e4436ed3779455c0e1bf399 I am 2022-12-14 02:25:45
qt_gui.gl_plot.CandidatesWidget: apply changes for GLplot too 03550040b60c67d247e26425e35fac565dd88886 Aleksei Gerasimov 2022-12-14 01:56:01
qt_gui.qt_plot.CandidatesWidget: add CandyNodes support 2357cdd92170b1f660b15c92aec695d3f7c108b3 I am 2022-12-14 01:08:30
qt_gui.qt_graph_widgets.EstimationGraph: reimplement piece of zerosafe logic 342a1b7bfddb7ba5695b3f0e017c7f75811db1f0 I am 2022-12-13 22:15:54
qt_gui.qt_graph_widgets: update x range when box runned c52052a9c3f6926d03e8c39f7642aa0a8864fdc3 I am 2022-12-13 10:23:45
qt_gui.qt_graph_widgets.EstimationGraph: add outside and mixed lines df6c06e4287492855d613b1ae46edfca6a4757d3 I am 2022-12-12 06:13:55
qt_gui: replace old copypaste by cleaned up EstimationGraph 515d0d8a892984f8a7667da874972daff3318d74 I am 2022-12-12 05:36:43
qt_gui: prepare new BoxEstimationData class; rework ErrorGraph 37387100715f980771a8a37f99eec3e723759cd3 I am 2022-12-11 23:17:06
dicebox.circumtri: replace ndim by nvar to make TriEstimation pandas-friendly 0824222ae4c9c1f3fede971481816ed9ded9707a I am 2022-12-11 23:14:05
step back: introduce box_estimations, keep "estimations" for user ones dde983d57423e28083980cbae05f0a81fc8311e6 I am 2022-12-10 03:54:09
simplex.BetterCubatureIntegration: hotfix f8a607e5d60c591eb81037010717519c1fe6e993 I am 2022-12-08 00:29:57
qt_gui.qt_gui: add EstimationTableWidget bb44fc8a056ed90906c217cfc95f7cabc6ef71eb I am 2022-12-07 23:17:42
remove deprecated never used Plotly code d42ebb3535e4736a1e9fdb84c8d6dae633c83a33 I am 2022-12-07 15:03:51
dicebox.circumtri.CircumTri: enable estimations 4fe25ad47d71b1fd19fe00ad03d9b320b8c8614c I am 2022-12-07 14:30:46
dicebox: introduce new clean experimental CircumTri box aca3e971212590a59e9d07a3ff1aa952d02a848b I am 2022-12-07 04:19:55
Commit b8605fb24d55b3296ceac34afba541a5b7ee3070 - dicebox.circumtri: employ _Exploration class. Keep naive CircumTri class in renamed module
Author: I am
Author date (UTC): 2022-12-15 09:33
Committer name: I am
Committer date (UTC): 2022-12-15 09:33
Parent(s): dae47ef37b5871a98d2ea274cc35aeb2a4eebe1c
Signer:
Signing key:
Signing status: N
Tree: bc9e7f96256ef991e141265ce610d529cfd1eb73
File Lines added Lines deleted
wellmet/dicebox/_circumtri.py 0 0
wellmet/dicebox/circumtri.py 85 130
File wellmet/dicebox/_circumtri.py copied from file wellmet/dicebox/circumtri.py (similarity 100%)
File wellmet/dicebox/circumtri.py changed (mode: 100644) (index e9ddfe8..bcf35f9)
5 5 import numpy as np import numpy as np
6 6 from scipy.spatial import distance from scipy.spatial import distance
7 7
8 import quadpy
9
8 10 from ..ghull import Ghull from ..ghull import Ghull
9 11 from .. import simplex as sx from .. import simplex as sx
10 12 from .. import convex_hull as khull from .. import convex_hull as khull
11 13 from ..reader import Store from ..reader import Store
12 14 from ..candynodes import CandyNodes from ..candynodes import CandyNodes
15 from .. import sball
16
17 from ._exploration import _Exploration
13 18
14 19 from collections import namedtuple from collections import namedtuple
15 20 from sortedcollections import ValueSortedDict from sortedcollections import ValueSortedDict
 
... ... from sortedcollections import ValueSortedDict
21 26 def get_entropy(pf): def get_entropy(pf):
22 27 return -pf * np.log(pf) - (1 - pf) * np.log(1 - pf) return -pf * np.log(pf) - (1 - pf) * np.log(1 - pf)
23 28
24 max_entropy = get_entropy(0.5)
25 29
26 30
27
28 TriEstimation = namedtuple('TriEstimation', (
31
32 CircumTriEstimation = namedtuple('CircumTriEstimation', (
29 33 "nsim", "nsim",
30 34 "nvar", "nvar",
31 35 "nfacets", "nfacets",
 
... ... TriEstimation = namedtuple('TriEstimation', (
36 40 "FORM_outside", "FORM_outside",
37 41 "TwoFORM_outside", "TwoFORM_outside",
38 42 "orth_outside", "orth_outside",
39 "shell_budget",
40 "shell_inside",
41 "shell_outside",
42 43 "inside", "inside",
43 44 "outside", "outside",
44 45 "success_points", "success_points",
 
... ... TriEstimation = namedtuple('TriEstimation', (
59 60 )) ))
60 61
61 62
62 #č Je třeba dávát bacha na odlišnosti v (staré) Triangulation třídě a nové Ghull třídě.
63 #č Zatímco Triangulation drží starý stáv, dokud .update() není spustěn,
64 #č Ghull, ale hlavně, odpovídající modely konvexních obálek jíž žádný .update() nemájí,
65 #č nové tečky uvidí sami dřív než se naše skříňka probere.
66 #č Takže teď odhady nově budeme ukladať hned pri incrementu.
67 #č Triangulation používá i jínej kód, samotné třídy beztak zbytečně komplikováné,
68 #č nechci teď to toho lezt.
69 class CircumTri:
63 class CircumTri(_Exploration):
70 64
71 65 #č míží nám sampling_space: Ghull umí vzorkovat outside pouze v G prostoru #č míží nám sampling_space: Ghull umí vzorkovat outside pouze v G prostoru
72 66 #č quadpy umístí integráční bodíky v prostoru triangulace. #č quadpy umístí integráční bodíky v prostoru triangulace.
73 def __init__(bx, sample_box, scheme, tri_space='G',
74 entropy_mode='weighted', shell_budget=1000, outer_budget=100):
67 def __init__(bx, sample_box, scheme, entropy_mode='weighted',
68 circumcenters_only=True, q=10):
75 69
70 bx.sample_box = sample_box
76 71 bx.scheme = scheme bx.scheme = scheme
77 bx.tri_space = tri_space
78
79
80 bx.shell_budget = shell_budget
81 bx.outer_budget = outer_budget
82 72 bx.entropy_mode = entropy_mode bx.entropy_mode = entropy_mode
73 bx.circumcenters_only = circumcenters_only
74 bx.q = q
83 75
84 76
85 bx.sample_box = sample_box
77 bx.direct_plan = quadpy.un.mysovskikh_1(bx.nvar).points
78 bx.sball = sball.Sball(bx.nvar)
79
80 bx.tri_space = 'G'
86 81
87 82 #č přece ponechame složku pro uživatelské odhady #č přece ponechame složku pro uživatelské odhady
88 83 #č stm kód může semka něco ukladat #č stm kód může semka něco ukladat
 
... ... class CircumTri:
91 86 #č vítejte nové uložiště odhadů. #č vítejte nové uložiště odhadů.
92 87 #č Odhady z stm kódu už ale nemají na tohle sahat #č Odhady z stm kódu už ale nemají na tohle sahat
93 88 if hasattr(bx, 'filename'): if hasattr(bx, 'filename'):
94 bx.box_estimations = Store.create(bx.filename + "_tri", TriEstimation)
89 bx.box_estimations = Store.create(bx.filename + "_ctri", CircumTriEstimation)
95 90 else: else:
96 91 bx.box_estimations = [] bx.box_estimations = []
97 92
 
... ... class CircumTri:
108 103 """ """
109 104 Returns dictionary of parameters the DiceBox was initialized with Returns dictionary of parameters the DiceBox was initialized with
110 105 """ """
111 return {'sample_box':bx.sample_box, 'scheme':bx.scheme.name,\
112 'tri_space':bx.tri_space, 'entropy_mode':bx.entropy_mode,\
113 'shell_budget':bx.shell_budget,'outer_budget':bx.outer_budget}
106 return {'sample_box':bx.sample_box, 'scheme':bx.scheme.name,
107 'entropy_mode':bx.entropy_mode,
108 'circumcenters_only':circumcenters_only, 'q':bx.q}
114 109
115 110
116 111 def __repr__(bx): def __repr__(bx):
 
... ... class CircumTri:
121 116
122 117
123 118
124 def __call__(bx):
125 if bx.nsim < 1: # je to legální
126 return bx.f_model.new_sample([], space='G', extend=True)
127 else:
119 def refine(bx):
120 if len(bx.candidates_index):
128 121 # return node with the greatest potential # return node with the greatest potential
129 122 key, value = bx.potential_index.peekitem() key, value = bx.potential_index.peekitem()
130 123 return bx.candidates_index[key] return bx.candidates_index[key]
124 else:
125 bx._logger(msg='refine called, but triangulation does not exist yet. Fallback to random sample')
126 return bx.f_model(1)
131 127
132 128
133 129 def regen(bx): def regen(bx):
 
... ... class CircumTri:
144 140
145 141 bx._regen_outside() bx._regen_outside()
146 142 bx._regen_inside() bx._regen_inside()
143
144 if bx.nsim > 0:
145 bx.get_pf_estimation() #č updates global stats
146 bx.update_exploration_ratio()
147 else:
148 bx.exploration_ratio = 1
149
147 150 bx._nsim = bx.nsim bx._nsim = bx.nsim
148 151
149 152
 
... ... class CircumTri:
193 196
194 197
195 198
199 def update_exploration_ratio(bx):
200 if "tri" in dir(bx):
201 outside = np.sqrt(bx.global_stats['outside'])
202 mixed = np.sqrt(bx.global_stats['mix'])
203 bx.exploration_ratio = outside / (outside + mixed)
204 else:
205 bx.exploration_ratio = 1
206
207
208
209
210
196 211 #č bejvalej .estimate_simplex() #č bejvalej .estimate_simplex()
197 212 #č teď je to kolbek, který volá Triangulation #č teď je to kolbek, který volá Triangulation
198 213 def _on_add_simplex(bx, nodes): def _on_add_simplex(bx, nodes):
 
... ... class CircumTri:
214 229 circum_pdf = float(circum_node.pdf(bx.tri_space)) circum_pdf = float(circum_node.pdf(bx.tri_space))
215 230 circum_potential = r * circum_pdf**(1/bx.nvar) circum_potential = r * circum_pdf**(1/bx.nvar)
216 231
217 #č nodes příjdou zabalené do CandyNodes. Ty mají .attrs a .kwargs
218 #circum_node = CandyNodes(circum_node, nodes.attrs)
219 #circum_node.potential = r * circum_pdf**(1/bx.nvar)
232 # circum rating
233 if bx.entropy_mode == 'none':
234 circum_rating = circum_potential
235 elif bx.entropy_mode == 'simple':
236 # fp like a failure points. Number of failure points
237 fp = len(failsi[failsi]) # the fastest solution
238 circum_rating = circum_potential * get_entropy(fp / len(failsi))
239 elif bx.entropy_mode == 'weighted':
240 # same as np.average(failsi, weights=pdf), but faster
241 wfr = np.sum(PDF[failsi]) / np.sum(PDF)
242 circum_rating = circum_potential * get_entropy(wfr)
220 243
221 244
245 if bx.circumcenters_only:
246 #č nodes příjdou zabalené do CandyNodes. Ty mají .attrs a .kwargs
247 circum_node = CandyNodes(circum_node, nodes.attrs)
248 circum_node.potential = circum_potential
249 circum_node.rating = circum_rating
250 bx.candidates_index[tuple(indices)] = circum_node
251 bx.potential_index[tuple(indices)] = circum_rating
252
253 return
254
255 #else:
256
222 257 nodes_model = getattr(nodes, bx.tri_space) nodes_model = getattr(nodes, bx.tri_space)
223 258 dr = distance.cdist(nodes_model, [circum_center]).flatten() dr = distance.cdist(nodes_model, [circum_center]).flatten()
224 259 nodes_pdf = nodes.pdf(bx.tri_space) nodes_pdf = nodes.pdf(bx.tri_space)
225 260 node_potentials = (r - dr) * nodes_pdf**(1/bx.nvar) node_potentials = (r - dr) * nodes_pdf**(1/bx.nvar)
226 261
227 262 if bx.entropy_mode == 'none': if bx.entropy_mode == 'none':
228 node_ratings = node_potentials * max_entropy
229 circum_rating = circum_potential * max_entropy
230
263 node_ratings = node_potentials
231 264 elif bx.entropy_mode == 'simple': elif bx.entropy_mode == 'simple':
232 265 node_ratings = node_potentials * get_entropy(nodes.pfv) node_ratings = node_potentials * get_entropy(nodes.pfv)
233
234 # fp like a failure points. Number of failure points
235 fp = len(failsi[failsi]) # the fastest solution
236 circum_rating = circum_potential * get_entropy(fp / len(failsi))
237
238 266 elif bx.entropy_mode == 'weighted': elif bx.entropy_mode == 'weighted':
239 267 node_ratings = node_potentials * get_entropy(nodes.pfw) node_ratings = node_potentials * get_entropy(nodes.pfw)
240 268
241 # same as np.average(failsi, weights=pdf), but faster
242 wfr = np.sum(PDF[failsi]) / np.sum(PDF)
243 circum_rating = circum_potential * get_entropy(wfr)
244 269
245 270
246 271 max_node = np.nanargmax(node_ratings) max_node = np.nanargmax(node_ratings)
 
... ... class CircumTri:
260 285 bx.potential_index[tuple(indices)] = max_node_rating bx.potential_index[tuple(indices)] = max_node_rating
261 286
262 287
288
289
263 290
264 291 # callback # callback
265 292 #č sx.on_delete_simplex(indices=indices) #č sx.on_delete_simplex(indices=indices)
 
... ... class CircumTri:
273 300
274 301
275 302 def _regen_outside(bx): def _regen_outside(bx):
276 bx.convex_hull = khull.QHull(bx.f_model, space=bx.tri_space,
303 bx.convex_hull = khull.QHull(bx.f_model, space='G',
277 304 incremental=True, auto_update=False) incremental=True, auto_update=False)
278 305 bx.ghull = Ghull(bx.convex_hull) bx.ghull = Ghull(bx.convex_hull)
279 bx._R = -1 # update outer under R>_R condition
280 bx._afacet = None
281 bx._bfacet = np.inf
282 #č konečně mám pořádnou stejtful třídu
283 306 #č pokud mám aspoň jednu tečku, tak už je mi šuma #č pokud mám aspoň jednu tečku, tak už je mi šuma
284 307 #č zda se konvexní obálka vytvořila, či nikoliv #č zda se konvexní obálka vytvořila, či nikoliv
285 308 if bx.nsim > 0: if bx.nsim > 0:
 
... ... class CircumTri:
299 322 def __regen_inside(bx): def __regen_inside(bx):
300 323 try: try:
301 324 bx.Tri = sx.BetterCubatureIntegration(bx.samplebox, bx.scheme,\ bx.Tri = sx.BetterCubatureIntegration(bx.samplebox, bx.scheme,\
302 tri_space=bx.tri_space, incremental=True,\
325 tri_space='G', incremental=True,\
303 326 on_add_simplex=bx._on_add_simplex,\ on_add_simplex=bx._on_add_simplex,\
304 327 on_delete_simplex=bx._invalidate_simplex) on_delete_simplex=bx._invalidate_simplex)
305 328
 
... ... class CircumTri:
334 357 bx.estimate_outside() bx.estimate_outside()
335 358
336 359 bx.box_estimations.append(bx.get_pf_estimation()) bx.box_estimations.append(bx.get_pf_estimation())
360 bx.update_exploration_ratio()
337 361
338 362
339
340
341 363
342
343 def _rate_outside_nodes(bx, outside_nodes):
344 #č sice získáme filtrovaný outside,
345 dh = bx.convex_hull.get_hyperplane_distances(outside_nodes)
346
347 node_potentials = outside_nodes.pdf(bx.tri_space)**(1/bx.nvar) * dh
348
349 max_node = np.nanargmax(node_potentials)
350 max_node_rating = node_potentials[max_node] * max_entropy
351
352 if max_node_rating > bx.potential_index[-1]:
353 #č nodes příjdou zabalené do CandyNodes. Ty mají .attrs a .kwargs
354 outside_node = CandyNodes(outside_nodes[max_node])
355
356 outside_node.potential = node_potentials[max_node]
357 outside_node.rating = max_node_rating
358
359 bx.candidates_index[-1] = outside_node
360 bx.potential_index.pop(-1)
361 bx.potential_index[-1] = max_node_rating
362 364
363 365
364 366
 
... ... class CircumTri:
367 369 #č pokud mám aspoň jednu tečku, tak už je mi šuma #č pokud mám aspoň jednu tečku, tak už je mi šuma
368 370 #č zda se konvexní obálka vytvořila, či nikoliv #č zda se konvexní obálka vytvořila, či nikoliv
369 371
370 #č Máme 2 úkoly:
371 #č 1. Získat odhady a uložit je, abychom nemuseli opakovaně integrovat,
372 #č dokud se neobjeví nějaký nový vzorek zvenku.
373 #č 2. Získat kandidaty.
374 #č a. z mezíkruží (-12)
375 #č b. fire, to co navrhne QHull (-1)
376 #č c. boom, doporuření QHull můžou i zklamat (-11)
377 #č cc. ze vdálenejších galaxí (-111)
378
379 #č prace s tečkami v mezikruži se změnila
380 #č teď tečky dostávám přes kolbek po částech
381 #č a není předem známo, kolik těch částí bude.
382 bx.candidates_index.pop(-1, None)
383 #č těch kastomných slovníků se bojím...
384 bx.potential_index.pop(-1, None)
385 bx.potential_index[-1] = 0
386
387 # get candidates!
388 #č explicitně (pokažde) počtem teček zadavám přesnost integrace
389 #č takže změny bx.shell_budget budou při dálším spuštění aplikovány
390 data = bx.ghull.integrate(bx.shell_budget, \
391 callback_outside=bx._rate_outside_nodes)
392 ghull_estimation, convex_hull_estimation, global_stats = data
393 #č uložíme. Не жалко.
394 #č první úkol máme splněný
395 bx.ghull_estimation = ghull_estimation
396 bx.convex_hull_estimation = convex_hull_estimation
372 shell_estimation, global_stats = bx.ghull.get_shell_estimation()
373
374 # shell_estimation -22: inner, -3: shell, -11: outer
375 bx.shell_estimation = shell_estimation
397 376
398 377 #č kvůli názvu neleze do namedtuple #č kvůli názvu neleze do namedtuple
399 378 global_stats['TwoFORM_outside'] = global_stats.pop('2FORM_outside') global_stats['TwoFORM_outside'] = global_stats.pop('2FORM_outside')
 
... ... class CircumTri:
401 380 global_stats['nvar'] = global_stats.pop('ndim') global_stats['nvar'] = global_stats.pop('ndim')
402 381
403 382 bx.global_stats = global_stats bx.global_stats = global_stats
404 bx._logger(msg="outside estimation:", ghull_stats=global_stats)
405
406
407 383
408 #č zde už nám jde pouze o kandidaty
409 384
410 # fire
411 bx._fire()
412 # boom
413 385
414 #č Projedeme Moravou
415 #č tyhle funkce už vracej pouhý f_model
416 bx._rate_outside_nodes(bx.ghull.boom(bx.outer_budget, use_MC=True))
417 386
418 #č Už máte Mléčnou dráhu projdutou?
419 #č tyhle funkce už vracej pouhý f_model
420 bx._rate_outside_nodes(bx.ghull.boom(bx.outer_budget, use_MC=False))
421 387
422
423 def _fire(bx):
424 qhull = bx.ghull.hull
425 nodes = qhull.fire(bx.outer_budget, use_MC=True)
426 if nodes is not None:
427 bx._rate_outside_nodes(nodes)
428
429
430 388 def get_pf_estimation(bx): def get_pf_estimation(bx):
431 #č dle toho, čo vidím v kódu (spouští nás .increment())
432 #č přinejmenším konvexní obálka musí
433 #č zajištěně existovat
434 # convex_hull_estimation -2: inside, -1: outside
435 pf_inside = bx.convex_hull_estimation[-2]
436 pf_outside = bx.convex_hull_estimation[-1]
389 global_stats = bx.global_stats
390 orth_outside = global_stats['outside'] = global_stats['orth_outside']
391 pf_inside = global_stats['inside'] = 1 - orth_outside
437 392
438 393 #č Ghull spouštíme sporadicky, #č Ghull spouštíme sporadicky,
439 394 #č takže musíme sami lepit nové etikety #č takže musíme sami lepit nové etikety
440 bx.global_stats['nsim'] = bx.nsim
395 global_stats['nsim'] = bx.nsim
441 396
442 397 failsi = bx.failsi failsi = bx.failsi
443 398
 
... ... class CircumTri:
450 405 bx.global_stats['success'] = pf_inside - failure - mixed bx.global_stats['success'] = pf_inside - failure - mixed
451 406 bx.global_stats['candidates_sets'] = len(bx.candidates_index) bx.global_stats['candidates_sets'] = len(bx.candidates_index)
452 407
453 return TriEstimation(**bx.global_stats)
408 return CircumTriEstimation(**bx.global_stats)
454 409
455 410
456 411 #оӵ триангуляци ӧвӧл, иськем... #оӵ триангуляци ӧвӧл, иськем...
 
... ... class CircumTri:
460 415 #č takže celou skříňku prostě bereme jako simplex #č takže celou skříňku prostě bereme jako simplex
461 416 event, event_id, fr, wfr = sx.get_simplex_event(bx, weighting_space=bx.tri_space) event, event_id, fr, wfr = sx.get_simplex_event(bx, weighting_space=bx.tri_space)
462 417 # -1=outside, 0=success, 1=failure, 2=mix # -1=outside, 0=success, 1=failure, 2=mix
463 tri_estimation = {-1:pf_outside, 0:0, 1:0, 2:0}
418 tri_estimation = {0:0, 1:0, 2:0}
464 419 tri_estimation[event_id] = pf_inside tri_estimation[event_id] = pf_inside
465 420
466 421 vertex_estimation = pf_inside * fr vertex_estimation = pf_inside * fr
 
... ... class CircumTri:
484 439 global_stats['candidates_sets'] = len(bx.candidates_index) global_stats['candidates_sets'] = len(bx.candidates_index)
485 440 global_stats['ncoplanar'] = 0 global_stats['ncoplanar'] = 0
486 441
487 return TriEstimation(**global_stats)
442 return CircumTriEstimation(**global_stats)
488 443
489 444
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