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)
convex_hull: 2FORM estimation WIP a0f04ef282d6dacbda52c9734f36f9e7ec9b46da I am 2021-07-19 06:14:54
convex_hull.fire: use sf instead of cdf function to fix precision issue in distant areas. e3b9f036f9d50994357e32827586fb98d85d43a7 I am 2021-07-15 09:13:58
qt_plot: add matplotlib menu 73835a59908b82f08d618a06c4c05a96703715b1 I am 2021-07-14 17:01:54
mart: add candidates plot functions 56b3f5320e83071886c0d8f65a3d9df7c5a231a8 I am 2021-07-13 10:55:13
dicebox.Goal.assess_candidates: put back dd attribute 5da7c67800b8cd6eb3f221273a8270393a571e2b I am 2021-07-12 08:47:00
sball: fix Radial pdf 830fbf3119e2e54e42ea48640dfe553ffa2b3c1f I am 2021-07-08 19:50:42
spring: try to fix infinite loop 0e9a6161996c1b078698b1631d10f1a171332818 I am 2021-07-08 17:54:04
dicebox.Goal: add q_psee potential 4c151252460f6e96f7c1ac5662f81474eae305a0 I am 2021-07-08 00:34:27
dicebox.Goal: Goal is back after the breakage! 19c3c63001ebc19ed5e17892e4b11edb4dbfe828 I am 2021-07-06 16:14:14
IS_stat.PushAndPull: small variance fix, spíše formální 7b5b87655b6978828ed06ba3743ada46a2bfde6b I am 2021-07-06 04:31:43
qt_plot.Ghull: update Ghull related code. A lot of fixes. Вроде фурычит. 29cd8fce14cecc872e1be856d73d9669a6395b08 I am 2021-07-05 18:47:53
IS_stat: new class added (for Ghull, actually) 27b2685694655cb75657c6629d10706669d1f2e2 I am 2021-07-04 22:05:48
convex_hull.Ghull: integrovaní memikruží je hodně překopano. Breakage. není zatím testováno 2d39dcd67948a99028013b0f7f420adf86eb19e9 I am 2021-07-04 22:02:48
dicebox: replace everywhere "potencial" typo by correct "potential" word. Save English eyes! c4aae036362d93c8a0a5bde9f30537d1b549adaa I am 2021-06-30 14:30:26
welford: add method for sparse data c9dd961c58243ac890b9a518cfff5901dd6a5789 I am 2021-06-28 13:47:09
welford: yet another Welford's algoritm implementation ec31907d6727c408306f4b25c09b7f87632b0ecf I am 2021-06-27 22:27:06
IS_stat.TrueIS: pridal jsem do komentářu vzpomínky 1c5b4596a4da1206b02ed91954cbe8147ec1e208 I am 2021-06-27 15:23:42
IS_stat: add get_IS_estimation() function d048b4cd4e90d8440e7ff2a3ad86bc0f3c160d4f I am 2021-06-26 19:55:14
spring: new brand hustý modul pro vyrovnání odhadů 3fc5eb00de1eb65cff2db71640c340602687f52f I am 2021-06-25 00:52:06
convex_hull.Ghull.rvs: hloupá chyba 7494eef4e2621ac9651037cd4a99e9f570704dee I am 2021-06-21 01:37:49
Commit a0f04ef282d6dacbda52c9734f36f9e7ec9b46da - convex_hull: 2FORM estimation WIP
Author: I am
Author date (UTC): 2021-07-19 06:14
Committer name: I am
Committer date (UTC): 2021-07-19 06:14
Parent(s): e3b9f036f9d50994357e32827586fb98d85d43a7
Signer:
Signing key:
Signing status: N
Tree: d591aec749419dbcf73a4346cc15f2dfb7203982
File Lines added Lines deleted
convex_hull.py 194 14
qt_plot.py 36 5
File convex_hull.py changed (mode: 100644) (index ec8d9e7..d757b85)
... ... from .IS_stat import PushAndPull # for Shell_IS
25 25 #č takže Gauss #č takže Gauss
26 26 #č (každá třida implementuje zvlášť) #č (každá třida implementuje zvlášť)
27 27
28 def fire(hull, ns):
28 def fire(hull, ns, use_MS=False):
29 29 if hull.space == 'G': if hull.space == 'G':
30 30 to_fire = np.nanargmax(hull.b) to_fire = np.nanargmax(hull.b)
31 r = -hull.b[to_fire]
31 32 a = hull.A[to_fire] a = hull.A[to_fire]
32 fire_from = stats.norm.sf(hull.get_r())
33 t = np.linspace(fire_from, 0, ns, endpoint=False)
34 t = stats.norm.isf(t)
35 fire_G = t.reshape(-1,1) @ a.reshape(1,-1)
36 33
34 if use_MC:
35 fire_from = stats.norm.sf(r)
36 t = np.linspace(fire_from, 0, ns, endpoint=False)
37 t = stats.norm.isf(t)
38 else:
39 # maximum radius, where norm.pdf() wasn't zero
40 # -38.575500173381374935388521407730877399444580
41 # don't ask me what the magic python use to distinguish
42 # digits after double precision
43 max_R_ever = -38.5755
44 t = np.linspace(r, max_R_ever, ns, endpoint=True)
45
46 fire_G = t.reshape(-1,1) @ a.reshape(1,-1)
37 47 return hull.sample.f_model.new_sample(fire_G, space='G') return hull.sample.f_model.new_sample(fire_G, space='G')
38 48
49
50 # common function for DirectHull, CompleteHull and QHull
51 # (even private function can be shared :D )
52 def _2FORM_helper(hull):
53 # supposed hull.space == 'G'
54 hull._update()
55 to_fire = np.nanargmax(hull.b)
56 a = hull.A[to_fire]
57
58 #č musí tam bejt G coordinates
59 # we'll get 1D npoints-sized negative b array
60 x = a @ hull.points.T
61 # here x == _b array has another meaning than hull.b
62 # where in hull.b we search for least distanced hyperplane
63 # here, in x, we search for a valid b_backward hyperplane offset
64 # It can be seen as transformation of the ED to 1D a-projection.
65 # There evidently exist min(x) and max(x)
66 # such that every single x value lies inside (between)
67 # max(x) (forward) value should be corresponding to r, to -hull.b
68 # So, we need to find min(x) (backward) value
69 # x_forward == max(x) == -b == r == max(a @ points.T) == -max(hull.b) == min(-hull.b)
70 # x_backward == min(x) == max(-a @ points.T)
71 x_forward = np.max(x)
72 x_backward = np.min(x)
73 print(-np.max(hull.b), x_forward)
74 return x_backward, x_forward, a
75
76 # common function for DirectHull, CompleteHull and QHull
77 def get_2FORM_outside(hull):
78 if hull.space == 'G':
79 # hull._update() will perform _FORM_helper()
80 x_backward, x_forward, __a = hull._2FORM_helper()
81 return stats.norm.cdf(x_backward) + stats.norm.sf(x_forward)
82 else:
83 #č když prostor není G, můžeme sice něco odvodit od s-ball
84 #č ale nechť se s tím pará GHull, vrátíme nulu.
85 return 0
86
87
88 # common function for DirectHull, CompleteHull and QHull
89 #č kdyby někdo chtěl všecko vidět vlastmina očima...
90 #č ale jinak předpokladám, že se funkce nebude spouštět přílíš často
91 def get_2FORM_points(hull):
92 if hull.space == 'G':
93 # hull._update() will perform _FORM_helper()
94 x_backward, x_forward, a = hull._2FORM_helper()
95 nodes_G = a * np.array([[x_backward], [x_forward]])
96 #č bacha, zadávám explicitně G prostor!
97 return hull.sample.f_model.new_sample(nodes_G, space='G')
98
99
39 100 #č jistě musíme mít nějaký zbytečný kus kódu #č jistě musíme mít nějaký zbytečný kus kódu
40 101 #č třida jen pro formu, jen tak na hračku #č třida jen pro formu, jen tak na hračku
41 102 #č když tečíčky jsou dále jak nejvzdálenější vzorek (bod), #č když tečíčky jsou dále jak nejvzdálenější vzorek (bod),
 
... ... class GBall:
84 145 return hull.get_R() return hull.get_R()
85 146
86 147
148 def get_2FORM_outside(hull):
149 return 2*stats.norm.sf(hull.get_r())
150
151
87 152 def fire(hull, ns): def fire(hull, ns):
88 153 pass pass
89 154
 
... ... class BrickHull: #č nebo BoundingBrick
110 175
111 176
112 177 hull._npoints = 0 hull._npoints = 0
178 #č miny a maxy obsahují minima a maxima
179 #č podel jednotlivých souřadnic (proměnných)
180 #č sincerely yours, Captain Obvious.
113 181 hull.mins = np.full(hull.sample.nvar, np.inf) hull.mins = np.full(hull.sample.nvar, np.inf)
114 182 hull.maxs = np.full(hull.sample.nvar, -np.inf) hull.maxs = np.full(hull.sample.nvar, -np.inf)
115 183
 
... ... class BrickHull: #č nebo BoundingBrick
180 248 b = np.concatenate((-hull.maxs, hull.mins)) b = np.concatenate((-hull.maxs, hull.mins))
181 249 return np.hstack((A,b[:,None])) return np.hstack((A,b[:,None]))
182 250
183 def fire(hull, ns): # boom
251
252 def _2FORM_helper(hull):
253 hull._update()
254 #č je to úplně zbýtečně trapit se nejakejma argama
255 #č poďme na to globálně!
256 #č (doufám, že nvar*2 výpočtů cdf() nikomu neublíží... )
257 #min_arg = np.nanargmin(hull.mins)
258 #max_arg = np.nanargmax(hull.maxs)
259 cdfs = stats.norm.cdf(hull.mins)
260 sfs = stats.norm.sf(hull.maxs)
261 #č _update() počítá nanmin a nanmax
262 #č takže nemusíme se bat nějakého hnusu v číslech
263 pfs = cdfs + sfs
264 i = np.argmax(pfs) # number of variable
265 # we'll return 2FORM estimation
266 # and corresponding number of variable
267 return pfs[i], i
268
269 def get_2FORM_outside(hull):
270 if hull.space == 'G':
271 # hull._update() will perform _FORM_helper()
272 p_out, __i = hull._2FORM_helper()
273 return p_out
274 else:
275 #č když prostor není G, můžeme sice něco odvodit od s-ball
276 #č ale nechť se s tím pará GHull, vrátíme nulu.
277 return 0
278
279 #č kdyby někdo chtěl všecko vidět vlastmina očima...
280 #č ale jinak předpokladám, že se funkce nebude spouštět přílíš často
281 def get_2FORM_points(hull):
282 if hull.space == 'G':
283 # hull._update() will perform _FORM_helper()
284 __p_out, i = hull._2FORM_helper()
285
286 # 0.0 - musí pak příjmout float
287 nodes_G = np.full((2, hull.sample.nvar), 0.0)
288 nodes_G[0, i] = hull.mins[i]
289 nodes_G[1, i] = hull.maxs[i]
290 #č bacha, zadávám explicitně G prostor!
291 return hull.sample.f_model.new_sample(nodes_G, space='G')
292
293 def get_2FORM_direction(hull):
294 __p_out, i = hull._2FORM_helper()
295 a = np.full(hull.sample.nvar, 0)
296 a[i] = 1
297 return hull.mins[i], hull.maxs[i], a
298
299 # add use_MC to the function signature
300 # but remain unimplemented for now
301 #č ten fire je hrozný. Výhodit U prostor
302 #č (jsou tam nepřesné cdf transformace)
303 #č po úpravě přídat hull._update() na začátku.
304 def fire(hull, ns, use_MC=False): # boom
184 305 sample_U = hull.sample.U sample_U = hull.sample.U
185 306
186 307 U_mins = np.nanmin(sample_U, axis=0) U_mins = np.nanmin(sample_U, axis=0)
 
... ... class BrickHull: #č nebo BoundingBrick
205 326
206 327
207 328 class DirectHull: class DirectHull:
208 # take global function for fire()
329 # take some global functions
209 330 fire = fire fire = fire
331 _2FORM_helper = _2FORM_helper
332 get_2FORM_outside = get_2FORM_outside
333 get_2FORM_points = get_2FORM_points
334 get_2FORM_direction = _2FORM_helper
335
210 336
211 337 def __init__(hull, sample, direct_plan, space='G'): def __init__(hull, sample, direct_plan, space='G'):
212 338 hull.sample = sample hull.sample = sample
 
... ... class DirectHull:
294 420
295 421
296 422 class CompleteHull: class CompleteHull:
297 # take global function for fire()
423 # take some global functions
298 424 fire = fire fire = fire
425 _2FORM_helper = _2FORM_helper
426 get_2FORM_outside = get_2FORM_outside
427 get_2FORM_points = get_2FORM_points
428 get_2FORM_direction = _2FORM_helper
299 429
300 430 def __init__(hull, sample, direct_plan, space='G'): def __init__(hull, sample, direct_plan, space='G'):
301 431 hull.sample = sample hull.sample = sample
 
... ... class CompleteHull:
410 540
411 541
412 542 class QHull: class QHull:
543 # take some global function
544 _2FORM_helper = _2FORM_helper
545 get_2FORM_points = get_2FORM_points
546 get_2FORM_direction = _2FORM_helper
547
413 548 def __init__(self, sample, space='G', incremental=True): def __init__(self, sample, space='G', incremental=True):
414 549 self.sample = sample self.sample = sample
415 550 self.incremental = incremental self.incremental = incremental
 
... ... class QHull:
520 655 else: else:
521 656 return 0 return 0
522 657
523 def fire(hull, ns):
658 def fire(hull, ns, use_MC=False):
524 659 try: try:
525 660 # take global function for fire() # take global function for fire()
526 return fire(hull, ns)
661 return fire(hull, ns, use_MC)
527 662 except: except:
528 663 pass pass
664
665
666
667 def get_2FORM_outside(hull):
668 if not hull.enough_points:
669 return 1 #č odvažný odhad
670 elif hull.space == 'G':
671 try:
672 # hull._update() will perform _FORM_helper()
673 x_backward, x_forward, __a = hull._2FORM_helper()
674 return stats.norm.cdf(x_backward) + stats.norm.sf(x_forward)
675 except: #č ve světě QHull se může nastat jakékoliv zázrak
676 #č Nějaká chyba! Něco se pokazilo!
677 #č nasrat. Posíláme odvažně jedničku-redkvičku
678 return 1
679 else:
680 #č když prostor není G, můžeme sice něco odvodit od s-ball
681 #č ale nechť se s tím pará GHull, vrátíme nulu.
682 return 0
683
529 684
530 685
531 686 #č mým úkolem při návrhu této třidy je pořádně všecko zkomplikovat. #č mým úkolem při návrhu této třidy je pořádně všecko zkomplikovat.
 
... ... class Ghull:
552 707 self.outside_dist = sball.Shell(hull.sample.nvar) self.outside_dist = sball.Shell(hull.sample.nvar)
553 708 self.sample = hull.sample self.sample = hull.sample
554 709
710 self.use_MC = use_MC
711
555 712 if use_MC: if use_MC:
556 713 self.gint = Shell_MC(hull, self.shell, non_Gaussian_reduction) self.gint = Shell_MC(hull, self.shell, non_Gaussian_reduction)
557 714 else: else:
558 715 self.gint = Shell_IS(hull, self.shell, non_Gaussian_reduction) self.gint = Shell_IS(hull, self.shell, non_Gaussian_reduction)
559 716
560 717
561 def fire(self, ns):
562 nodes = self.hull.fire(ns)
718 def fire(self, ns, use_MC=None):
719 nodes = self.hull.fire(ns, use_MC=self.use_MC)
563 720 if nodes is not None: if nodes is not None:
564 721 return nodes return nodes
565 722 else: else:
566 723 return self.boom(ns) return self.boom(ns)
567 724
568 725 def boom(self, ns): def boom(self, ns):
569 self.outside_dist.set_bounds(self.get_R())
570 nodes_G = self.outside_dist.rvs(ns)
726 if self.use_MC:
727 self.outside_dist.set_bounds(self.get_R())
728 nodes_G = self.outside_dist.rvs(ns)
729 else:
730 # rand_dir: prepare ns random directions on a unit d-sphere
731 rand_dir = sball.get_random_directions(ns, self.sample.nvar) #random directions
732
733 # maximum radius, where norm.pdf() wasn't zero
734 # -38.575500173381374935388521407730877399444580
735 # don't ask me what the magic python use to distinguish
736 # digits after double precision
737 max_R_ever = -38.5755
738
739 r = np.linspace(self.get_R(), max_R_ever, ns, endpoint=True)
740 nodes_G = rand_dir*r[:,None]
741
571 742 nodes = self.sample.f_model.new_sample(nodes_G, space='G') nodes = self.sample.f_model.new_sample(nodes_G, space='G')
572 743 return nodes return nodes
573 744
745 def get_2FORM_outside(self):
746 if self.hull.space == 'G':
747 return self.hull.get_2FORM_outside()
748 else:
749 #č nebudem do toho michat nic dalšího.
750 #č Když 2FORM, tak 2FORM!
751 return 2 * stats.norm.sf(self.get_R())
752
574 753 def get_R(self): def get_R(self):
575 754 sum_squared = np.sum(np.square(self.sample.G), axis=1) sum_squared = np.sum(np.square(self.sample.G), axis=1)
576 755 #index = np.argmax(sum_squared) #index = np.argmax(sum_squared)
 
... ... class Ghull:
617 796 shell_estimation = {-22:shell.ps, -3: shell.p_shell, -11: shell.pf} shell_estimation = {-22:shell.ps, -3: shell.p_shell, -11: shell.pf}
618 797 global_stats = {"nsim":self.sample.nsim, "ndim":self.sample.nvar, \ global_stats = {"nsim":self.sample.nsim, "ndim":self.sample.nvar, \
619 798 "nfacets": self.hull.nsimplex, "r":r, "R":R, \ "nfacets": self.hull.nsimplex, "r":r, "R":R, \
799 "2FORM_outside": self.get_2FORM_outside(),\
620 800 "inner":shell.ps, "shell":shell.p_shell, "outer":shell.pf} "inner":shell.ps, "shell":shell.p_shell, "outer":shell.pf}
621 801 return shell_estimation, global_stats return shell_estimation, global_stats
622 802
File qt_plot.py changed (mode: 100644) (index 04a3015..1fcf59b)
... ... class HullEstimationWidget(pg.LayoutWidget):
3050 3050 params.append({'name': 'inside', 'type': 'color', 'value': (133, 172, 102, 255) }) params.append({'name': 'inside', 'type': 'color', 'value': (133, 172, 102, 255) })
3051 3051 params.append({'name': 'convex_hull', 'type': 'color', 'value': (85, 170, 255, 255) }) # (186, 109, 0, 255) params.append({'name': 'convex_hull', 'type': 'color', 'value': (85, 170, 255, 255) }) # (186, 109, 0, 255)
3052 3052 params.append({'name': 'fire', 'type': 'color', 'value': (245, 117, 0, 255) }) params.append({'name': 'fire', 'type': 'color', 'value': (245, 117, 0, 255) })
3053 params.append({'name': 'FORM', 'type': 'color', 'value': (255, 0, 0, 255) })
3053 3054 params.append({'name': 'outside', 'type': 'color', 'value': 0.6}) params.append({'name': 'outside', 'type': 'color', 'value': 0.6})
3054 3055 params.append({'name': 'R', 'type': 'color', 'value': (85, 85, 255, 255) }) params.append({'name': 'R', 'type': 'color', 'value': (85, 85, 255, 255) })
3055 3056 params.append({'name': 'Update as the box runned', 'type': 'bool', 'value': False }) # 'tip': "This is a checkbox" params.append({'name': 'Update as the box runned', 'type': 'bool', 'value': False }) # 'tip': "This is a checkbox"
 
... ... class HullEstimationWidget(pg.LayoutWidget):
3115 3116
3116 3117 def draw_convex_hull(self, hull): def draw_convex_hull(self, hull):
3117 3118 try: try:
3118 #č zatím uděláme jen pro 2D infinite lajny
3119 design_points = hull.get_design_points()
3120
3121 3119 if self.param.getValues()['index'][0]: # replace previous if self.param.getValues()['index'][0]: # replace previous
3122 3120 self.equation_planes.clear() self.equation_planes.clear()
3123 3121
3122 #č zatím uděláme jen pro 2D infinite lajny
3123 design_points = hull.get_design_points()
3124
3124 3125 size = self.param.getValues()['node (pixel) size'][0] size = self.param.getValues()['node (pixel) size'][0]
3125 3126 color = self.param.getValues()['convex_hull'][0] #č tam bude barva color = self.param.getValues()['convex_hull'][0] #č tam bude barva
3126 3127
 
... ... class HullEstimationWidget(pg.LayoutWidget):
3135 3136 #č na central widgetu. #č na central widgetu.
3136 3137 #č To vše skončí ve pyqtgrafové InfiniteLine třidě. #č To vše skončí ve pyqtgrafové InfiniteLine třidě.
3137 3138 #č ta moje třida InfiniteLines sama se stará o shodování prostorů #č ta moje třida InfiniteLines sama se stará o shodování prostorů
3138 #č indexy posilat nebudeme (s nimi je to trošku komplikovanější),
3139 #č takže ty konvexní obálky budou hromadit
3139 #č indexy posilat nebudeme (s nimi je to trošku komplikovanější)
3140 3140
3141 3141 #pos = list() #č navrhové body nakreslíme všechny dohromady #pos = list() #č navrhové body nakreslíme všechny dohromady
3142 3142 for equation in hull.equations: for equation in hull.equations:
 
... ... class HullEstimationWidget(pg.LayoutWidget):
3155 3155 angle = np.rad2deg(np.arccos(-np.abs(y))) angle = np.rad2deg(np.arccos(-np.abs(y)))
3156 3156 self.equation_planes.add_line(space=hull.space,\ self.equation_planes.add_line(space=hull.space,\
3157 3157 z=29, pos=design_point, angle=angle, pen=color) z=29, pos=design_point, angle=angle, pen=color)
3158
3159
3160 # 2FORM
3161 FORM_points = hull.get_2FORM_points()
3162
3163 color = self.param.getValues()['FORM'][0] #č tam bude barva
3164
3165 self.giracle.add_serie(FORM_points, z=32, index=self.index('2FORM points'),\
3166 pen=None, symbol='o', symbolPen=pg.mkPen(None), \
3167 symbolBrush=color, symbolSize=size, name='2FORM points')
3168 if self.ndim == 2:
3169 #č musíme něco zavolat na self.equation_planes
3170 #č equation_planes má funkci add_line()
3171 #č add_line(self, space='G', index=None, **plot_kwargs)
3172 #č která pak plot_kwargs přeposilá funkci addLine()
3173 #č na central widgetu.
3174 #č To vše skončí ve pyqtgrafové InfiniteLine třidě.
3175 #č ta moje třida InfiniteLines sama se stará o shodování prostorů
3176 #č indexy posilat nebudeme (s nimi je to trošku komplikovanější)
3177
3178 __x_b, __x_f, a = hull.get_2FORM_direction()
3179 if np.prod(a) < 0: #č tak to aspoň kreslí
3180 angle = np.rad2deg(np.arccos(np.abs(y)))
3181 else:
3182 angle = np.rad2deg(np.arccos(-np.abs(y)))
3183 G_nodes = FORM_points.G
3184 self.equation_planes.add_line(space='G',\
3185 z=30, pos=G_nodes[0], angle=angle, pen=color)
3186 self.equation_planes.add_line(space='G',\
3187 z=30, pos=G_nodes[1], angle=angle, pen=color)
3188
3158 3189 except BaseException as e: except BaseException as e:
3159 3190 msg = "draw_convex_hull error " msg = "draw_convex_hull error "
3160 3191 error_msg = self.__class__.__name__ + ": " + msg + repr(e) error_msg = self.__class__.__name__ + ": " + msg + repr(e)
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