51
51
class CH (CBase ): # generic derivation hierarchy of variable nesting: extH | derH, their layers and sub-layers
52
52
53
53
name = "H"
54
- def __init__ (He , root , Et , tft , lft = None , node_ = None , fd = None , altH = None ):
54
+ def __init__ (He , root = None , Et = None , tft = None , lft = None , node_ = None , fd = None , altH = None ):
55
55
super ().__init__ ()
56
56
He .Et = np .zeros (4 ) if Et is None else Et # += links (n is added to et now)
57
- He .tft = tft # top fork tuple: arrays m_t, d_t
57
+ He .tft = [] if tft is None else tft # top fork tuple: arrays m_t, d_t
58
58
He .lft = [] if lft is None else lft # lower fork tuple: CHs, each mediates its own tft and lft
59
- He .root = root # N or higher-composition He
59
+ He .root = None if root is None else root # N or higher-composition He
60
60
He .node_ = [] if node_ is None else node_ # concat bottom nesting order if CG, may be redundant to G.node_
61
61
He .altH = CH (altH = object ) if altH is None else altH # summed altLays, prevent cyclic
62
62
He .depth = 0 # max depth of fork tree?
@@ -69,7 +69,7 @@ def __init__(He, root, Et, tft, lft=None, node_=None, fd=None, altH=None):
69
69
# He.deep = 0 if deep is None else deep # nesting in root H
70
70
# He.nest = 0 if nest is None else nest # nesting in H
71
71
72
- def __bool__ (H ):return bool (H . lft ) # empty only in empty CH
72
+ def __bool__ (H ):return bool (len ( H . tft ) > 0 ) # empty only in empty CH (should be tft now? lft is empty in bottom layer)
73
73
74
74
75
75
def copy_ (He , root , rev = 0 , fc = 0 ): # comp direction may be reversed to -1
@@ -88,8 +88,7 @@ def add_tree(HE, He_, rev=0, fc=0): # rev = dir==-1, unpack derH trees down to
88
88
89
89
for He in He_ :
90
90
# top fork tuple per node of fork tree:
91
- for fd , (TT ,tt ) in enumerate (zip_longest (HE .tft , He .tft , fillvalue = None )):
92
- np .add (TT , tt * - 1 if rev and (fd or fc ) else tt )
91
+ HE .sum_tft (He ,rev = rev ,fc = fc )
93
92
94
93
for Fork , fork in zip_longest (HE .lft , He .lft , fillvalue = None ):
95
94
if fork : # empty in bottom layer
@@ -103,11 +102,23 @@ def add_tree(HE, He_, rev=0, fc=0): # rev = dir==-1, unpack derH trees down to
103
102
104
103
return HE # root should be updated by returned HE
105
104
105
+
106
+ def sum_tft (HE , He , rev = 0 , fc = 0 ): # sum He.tft into HE.tft
107
+
108
+ if HE .tft :
109
+ for fd , (T_t , t_t ) in enumerate (zip (HE .tft , He .tft )): # loop eacmd_t and dd_t
110
+ for T_ , t_ in zip_longest (T_t , t_t , fillvalue = None ): # loop each m_ and d_
111
+ t_ = t_ * - 1 if rev and (fd or fc ) else t_
112
+ if T_ is None : HE .tft [fd ] = T_t = np .array ([* T_t , t_ ],dtype = object )
113
+ else : T_ += t_
114
+ else :
115
+ HE .tft = deepcopy (He .tft ) # empty HE.tft (it may empty in new init He)
116
+
106
117
def comp_tree (_He , He , rn , root , dir = 1 ): # unpack derH trees down to numericals and compare them
107
118
108
- (mver , dver ), et = comp_md_ (_He .tft [1 ], He .tft [1 ], rn , dir = dir )
119
+ (mver , dver ), et = comp_md_t (_He .tft [1 ], He .tft [1 ], rn , dir = dir )
109
120
# comp d_t only
110
- derH = CH (root = root , tft = [mver ,dver ], Et = np .array ([* et ,_He .Et [3 ]+ He .Et [3 ] / 2 ]))
121
+ derH = CH (root = root , tft = [mver ,dver ], Et = np .array ([* et ,( He . Et [ 2 ] + He . Et [ 2 ]) / 2 , ( _He .Et [3 ]+ He .Et [3 ]) / 2 ]))
111
122
112
123
for _fork , fork in zip (_He .lft , He .lft ): # comp shared layers
113
124
if _fork and fork : # same depth
@@ -270,6 +281,17 @@ def val_(Et, mEt=[], fo=0):
270
281
val = m - ave * n * (o if fo else 1 ) # * overlap in cluster eval, not comp eval
271
282
return val
272
283
284
+ # we need a separate version of comp_md_t for md_t and dd_t, i think it's clearer to have another version here?
285
+ def comp_md_t (_d_t ,d_t , rn = .1 , dir = 1 ): # dir may be -1
286
+
287
+ d_t = d_t * rn # normalize by compared accum span
288
+ dd_t = (_d_t - d_t * dir ) # np.arrays
289
+ md_t = np .array ([np .minimum (_d_ , d_ ) for _d_ , d_ in zip (_d_t , d_t )], dtype = object )
290
+ for i , (_d_ , d_ ) in enumerate (zip (_d_t , d_t )): md_t [i ][(_d_ < 0 ) != (d_ < 0 )] *= - 1 # Negate where only one of _d_ or d_ is negative
291
+
292
+ M = sum ([sum (md_ ) for md_ in md_t ]); D = sum ([sum (dd_ ) for dd_ in dd_t ])
293
+ return np .array ([md_t ,dd_t ]), np .array ([M ,D ]) # [m_,d_], Et
294
+
273
295
def comp_node_ (_N_ ): # rng+ forms layer of rim and extH per N, appends N_,L_,Et, ~ graph CNN without backprop
274
296
275
297
_Gp_ = [] # [G pair + co-positionals]
@@ -382,7 +404,7 @@ def comp_N(_N,N, rn, angle=None, dist=None, dir=1): # dir if fd, Link.derH=dH,
382
404
_L , L = len (_N .node_ ),len (N .node_ ); dL = _L - L * rn ; mL = min (_L , L * rn ) - ave_L
383
405
mA ,dA = comp_area (_N .box , N .box ) # compare area in CG vs angle in CL
384
406
# der ext
385
- m_t = np .array ([mL ,mA ]); d_t = np .array ([dL ,dA ])
407
+ m_t = np .array ([mL ,mA ], dtype = float ); d_t = np .array ([dL ,dA ], dtype = float )
386
408
_o ,o = _N .Et [3 ],N .Et [3 ]; olp = (_o + o ) / 2 # inherit from comparands?
387
409
Et = np .array ([mL + mA , abs (dL )+ abs (dA ), .3 , olp ]) # n = compared vars / 6
388
410
if fd : # CH
@@ -397,7 +419,7 @@ def comp_N(_N,N, rn, angle=None, dist=None, dir=1): # dir if fd, Link.derH=dH,
397
419
derH = CH (tft = [m_t ,d_t ], Et = Et )
398
420
if _N .derH and N .derH :
399
421
dderH = _N .derH .comp_tree (N .derH , rn , root = derH ) # comp shared layers
400
- derH .lft += dderH ; derH .Et += dderH .Et
422
+ derH .sum_tft ( dderH , rev = 0 , fc = 0 ); derH . lft += [ dderH ] ; derH .Et += dderH .Et
401
423
# not revised:
402
424
# spec: comp_node_(node_|link_), combinatorial, node_ nested / rng-)agg+?
403
425
Et = copy (derH .Et )
@@ -430,7 +452,7 @@ def sum2graph(root, grapht, fd, nest, fsub=0): # sum node and link params into
430
452
yx = np .array ([0 ,0 ])
431
453
fg = isinstance (node_ [0 ],CG )
432
454
if fg : M ,D = 0 ,0
433
- derH = CH (root = graph )
455
+ graph . derH = derH = CH (root = graph )
434
456
for N in node_ :
435
457
graph .box = extend_box (graph .box , N .box ) # pre-compute graph.area += N.area?
436
458
yx = np .add (yx , N .yx )
@@ -443,7 +465,7 @@ def sum2graph(root, grapht, fd, nest, fsub=0): # sum node and link params into
443
465
graph .Et [:2 ] += np .array ([M ,D ]) * icoef ** 2
444
466
# sum link.derHs:
445
467
derLay = CH ().add_tree ([link .derH for link in link_ ])
446
- graph . derH = derH .lft + [derLay ]
468
+ derH . sum_tft ( derLay ); derH .lft += [derLay ]; derH . Et += derLay . Et # append derlay (when N.derH is empty in base fork, we have derlay in their lft only)
447
469
# derLay Et = arg Et:
448
470
graph .Et += Et ; graph .derH .Et += Et
449
471
L = len (node_ )
0 commit comments