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 , tft = None , der_ = None , Et = None , node_ = None , root = None , fd = None , altH = None ):
54
+ def __init__ (He , root , Et , tft , 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 = [] if tft is None else tft # nested CH forks, each mediates its own layt, or md_tC in top layer
58
- He .der_ = [] if der_ is None else der_ # m_t | d_t, also summing feedback?
59
- He .root = None if root is None else root # N or higher-composition He
57
+ He .tft = tft # top fork tuple: arrays m_t, d_t
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
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?
63
63
He .fd = 0 if fd is None else fd # 0: sum CGs, 1: sum CLs
64
64
# if combined-fork H:
65
- # He.i = 0 if i is None else i # lay index in root.tft , to revise olp
65
+ # He.i = 0 if i is None else i # lay index in root.lft , to revise olp
66
66
# He.i_ = [] if i_ is None else i_ # priority indices to compare node H by m | link H by d
67
67
# He.fd = 0 if fd is None else fd # 0: sum CGs, 1: sum CLs
68
68
# He.ni = 0 # exemplar in node_, trace in both directions?
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 (len ( H . der_ ) > 0 ) # never empty? extH is empty before we sum them, so they may empty
72
+ def __bool__ (H ):return bool (H . lft ) # empty only in empty CH
73
73
74
74
75
- def copy_ (He , root , dir = 1 , fc = 0 , fd = 0 ): # comp direction may be reversed to -1
75
+ def copy_ (He , root , rev = 0 , fc = 0 ): # comp direction may be reversed to -1
76
76
77
- C = CH (root = root , node_ = copy (He .node_ ), Et = He .Et * dir if fc else copy (He .Et ))
78
- C .der_ = np .array ([np .array ([(v * dir if (fd or not fc ) else v ) for v in v_ ]) for v_ in He .der_ ], dtype = object )
79
- for fd , he in enumerate (He .tft ): # mfork, dfork
80
- C .tft += [he .copy_ (root = C , dir = dir , fc = fc , fd = fd )]
77
+ C = CH (root = root , node_ = copy (He .node_ ), Et = He .Et * - 1 if (fc and rev ) else copy (He .Et ))
81
78
79
+ for fd , tt in enumerate (He .tft ): # nested array tuples
80
+ C .tft += [tt * - 1 if rev and (fd or fc ) else deepcopy (tt )]
81
+ # empty in bottom layer:
82
+ for fork in He .lft :
83
+ C .lft += [fork .copy_ (root = C , rev = rev , fc = fc )]
82
84
return C
83
85
84
-
85
- def add_tree (HE , He_ , dir = 1 , fc = 0 ): # unpack derH trees down to numericals and sum them, may subtract from centroid
86
+ def add_tree (HE , He_ , rev = 0 , fc = 0 ): # rev = dir==-1, unpack derH trees down to numericals and sum/subtract them
86
87
if not isinstance (He_ ,list ): He_ = [He_ ]
87
88
88
89
for He in He_ :
89
- He .der_ += He .der_ # add der_ (in higher layers' der_ or bottom mfork|dfork's der)
90
- for fd , (Fork , fork ) in enumerate (zip_longest (HE .tft , He .tft , fillvalue = None )): # top fork tuple at each node of fork trees
91
- if fork :
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 )
93
+
94
+ for Fork , fork in zip_longest (HE .lft , He .lft , fillvalue = None ):
95
+ if fork : # empty in bottom layer
92
96
if Fork : # unpack|add, same nesting in both forks
93
- Fork .add_tree (fork ,dir , fc )
97
+ Fork .add_tree (fork , rev , fc )
94
98
else :
95
- HE .tft += [fork .copy_ (root = HE , dir = dir , fc = fc , fd = fd )]
99
+ HE .lft += [fork .copy_ (root = HE , rev = rev , fc = fc )]
96
100
97
101
HE .node_ += [node for node in He .node_ if node not in HE .node_ ] # empty in CL derH?
98
- HE .Et += He .Et * dir
102
+ HE .Et += He .Et * - 1 if rev and fc else He . Et
99
103
100
104
return HE # root should be updated by returned HE
101
105
102
- def comp_md_C (_md_C , md_C , rn , root , olp = 1. , dir = 1 ):
103
-
104
- m_t , d_t = [],[]
105
- Et = np .zeros (2 )
106
- # md_C is always dfork here
107
- for _d_ , d_ in zip (_md_C .der_ , md_C .der_ ): # [dext, ?dlat, dvert]
108
- (m_ , d_ ), et = comp_md_ (_d_ , d_ , rn , dir = dir )
109
- m_t += [m_ ]
110
- d_t += [d_ ]
111
- Et += et
112
- mfork = CH (der_ = np .array (m_t ,dtype = object )) # mainly empty
113
- dfork = CH (der_ = np .array (d_t ,dtype = object ))
114
- # der_ is summed from deeper forks?
115
- return CH (root = root , tft = [mfork ,dfork ], der_ = m_t + d_t , Et = np .append (Et ,[olp , .3 if len (m_t )== 1 else 2.3 ])) # .3 in default comp ext)
116
-
117
- def comp_tree (_He , He , rn , root ):
118
- derH = CH (root = root )
119
-
120
- for _fork , fork in zip (_He .tft [1 ::2 ], He .tft [1 ::2 ]): # comp dforks only? (if comp dforks only, it's always comparing single fork, so there's no need to loop too)
106
+ def comp_tree (_He , He , rn , root , dir = 1 ): # unpack derH trees down to numericals and compare them
107
+
108
+ (mver , dver ), et = comp_md_ (_He .tft [1 ], He .tft [1 ], rn , dir = dir )
109
+ # comp d_t only
110
+ derH = CH (root = root , tft = [mver ,dver ], Et = np .array ([* et ,_He .Et [3 ]+ He .Et [3 ] / 2 ]))
111
+
112
+ for _fork , fork in zip (_He .lft , He .lft ): # comp shared layers
121
113
if _fork and fork : # same depth
122
- if fork .tft : # empty in top lay
123
- dLay = _fork .comp_tree (fork , rn , root = derH ) # deeper unpack -> comp_md_t
124
- else :
125
- dLay = _fork .comp_md_C (fork , rn = rn , root = derH , olp = (_He .Et [3 ]+ He .Et [3 ]) / 2 )
126
- # comp shared layers, add n to olp?
127
- derH .tft += [dLay ]; derH .Et += dLay .Et
114
+ subH = _fork .comp_tree (fork , rn , root = derH ) # deeper unpack -> comp_md_t
115
+ derH .lft += [subH ]
116
+ derH .Et += subH .Et
128
117
return derH
129
118
130
- # not updated:
131
119
def norm_ (He , n ):
132
-
133
- for lay in He .tft : # not empty list
134
- if lay :
135
- if isinstance (lay .tft [0 ], CH ):
136
- lay .norm_C (n )
137
- else :
138
- for md_ in lay .tft : md_ *= n
139
- lay .Et *= n
120
+ for f in He .tft : # arrays
121
+ f *= n
122
+ for fork in He .lft : # CHs
123
+ fork .norm_C (n )
124
+ fork .Et *= n
140
125
He .Et *= n
141
126
142
- # not updated :
127
+ # not used :
143
128
def sort_tree (He , fd ): # re-assign olp and form priority indices for comp_tree, if selective and aligned
144
129
145
130
i_ = [] # priority indices
146
- for i , lay in enumerate (sorted (He .tft , key = lambda lay : lay .Et [fd ], reverse = True )):
131
+ for i , lay in enumerate (sorted (He .lft , key = lambda lay : lay .Et [fd ], reverse = True )):
147
132
di = lay .i - i # lay index in H
148
133
lay .olp += di # derR- valR
149
134
i_ += [lay .i ]
150
135
He .i_ = i_ # comp_tree priority indices: node/m | link/d
151
136
if not fd :
152
- He .root .node_ = He .tft [i_ [0 ]].node_ # no He.node_ in CL?
137
+ He .root .node_ = He .lft [i_ [0 ]].node_ # no He.node_ in CL?
153
138
154
139
155
140
class CG (CBase ): # PP | graph | blob: params of single-fork node_ cluster
@@ -193,9 +178,9 @@ def __init__(l, nodet=None, dist=None, derH=None, angle=None, box=None, H_=None,
193
178
l .dist = 0 if dist is None else dist # distance between nodet centers
194
179
l .box = [] if box is None else box # sum nodet, not needed?
195
180
l .yx = [0 ,0 ] if yx is None else yx
196
- l .tft_ = [] if H_ is None else H_ # if agg++| sub++?
181
+ l .lft_ = [] if H_ is None else H_ # if agg++| sub++?
197
182
# add med, rimt, elay | extH in der+
198
- def __bool__ (l ): return bool (l .derH .tft )
183
+ def __bool__ (l ): return bool (l .derH .lft )
199
184
200
185
# not updated:
201
186
def vectorize_root (frame ):
@@ -260,7 +245,7 @@ def cluster_PP_(edge, fd):
260
245
edge .link_ = L_
261
246
if val_ (Et , fo = 1 ) > 0 : # cancel by borrowing d?
262
247
mlay = CH ().add_tree ([L .derH for L in L_ ])
263
- edge .derH = CH (tft = [mlay ], root = edge , Et = copy (mlay .Et ))
248
+ edge .derH = CH (lft = [mlay ], root = edge , Et = copy (mlay .Et ))
264
249
mlay .root = edge .derH # init
265
250
if len (N_ ) > ave_L :
266
251
cluster_PP_ (edge , fd = 0 )
@@ -271,7 +256,7 @@ def cluster_PP_(edge, fd):
271
256
# comp dPP_:
272
257
lN_ ,lL_ ,_ = comp_link_ (L_ , Et )
273
258
dlay = CH ().add_tree ([L .derH for L in lL_ ])
274
- edge .derH .tft += [dlay ]; edge .derH .Et += dlay .Et
259
+ edge .derH .lft += [dlay ]; edge .derH .Et += dlay .Et
275
260
if len (lN_ ) > ave_L :
276
261
cluster_PP_ (edge , fd = 1 )
277
262
@@ -396,26 +381,25 @@ def comp_N(_N,N, rn, angle=None, dist=None, dir=1): # dir if fd, Link.derH=dH,
396
381
else :
397
382
_L , L = len (_N .node_ ),len (N .node_ ); dL = _L - L * rn ; mL = min (_L , L * rn ) - ave_L
398
383
mA ,dA = comp_area (_N .box , N .box ) # compare area in CG vs angle in CL
399
- # der ext: default new layer
400
- m_t = np .array ( [np .array ([mL ,mA ])] )
401
- d_t = np .array ( [np .array ([dL ,dA ])] )
402
- _o , o = _N .Et [3 ], N .Et [3 ]
403
- olp = (_o + o ) / 2 # inherit from comparands?
384
+ # der ext
385
+ m_t = np .array ([mL ,mA ]); d_t = np .array ([dL ,dA ])
386
+ _o ,o = _N .Et [3 ],N .Et [3 ]; olp = (_o + o ) / 2 # inherit from comparands?
404
387
Et = np .array ([mL + mA , abs (dL )+ abs (dA ), .3 , olp ]) # n = compared vars / 6
405
- if not fd : # CG
406
- mdLat , et1 = comp_latuple (_N .latuple , N .latuple , _o ,o )
407
- (mVert , dVert ), et2 = comp_md_ (_N .vert [1 ], N .vert [1 ], dir )
408
- m_t = np .array ([m_t [0 ],mdLat [0 ], mVert ], dtype = object ) # using numpy appenbd is merging them, so we need to use np.array hjere
409
- d_t = np .array ([d_t [0 ],mdLat [1 ], dVert ], dtype = object )
388
+ if fd : # CH
389
+ m_t = np .array ([m_t ]); d_t = np .array ([d_t ]) # add nesting
390
+ else : # CG
391
+ (mLat ,dLat ),et1 = comp_latuple (_N .latuple , N .latuple , _o ,o )
392
+ (mVer ,dVer ),et2 = comp_md_ (_N .vert [1 ], N .vert [1 ], dir )
393
+ m_t = np .array ([m_t , mLat , mVer ], dtype = object )
394
+ d_t = np .array ([d_t , dLat , dVer ], dtype = object )
410
395
Et += np .array ([et1 [0 ]+ et2 [0 ], et1 [1 ]+ et2 [1 ], 2 , 0 ])
411
396
# no added olp?
412
- mfork = CH (der_ = m_t ); dfork = CH (der_ = d_t ) # der_ is summed in deeper forks too?:
413
- derH = CH (tft = [mfork , dfork ], Et = Et , der_ = m_t + d_t ) # fork der_s and Ets are summed upward
397
+ derH = CH (tft = [m_t ,d_t ], Et = Et )
414
398
if _N .derH and N .derH :
415
- dderH = _N .derH .comp_tree (N .derH , rn , root = derH ) # comp shared tree layers
416
- derH .tft [fd ].add_tree (dderH )
417
- # spec: comp_node_(node_|link_), combinatorial, node_ nested / rng-)agg+?
399
+ dderH = _N .derH .comp_tree (N .derH , rn , root = derH ) # comp shared layers
400
+ derH .lft += dderH ; derH .Et += dderH .Et
418
401
# not revised:
402
+ # spec: comp_node_(node_|link_), combinatorial, node_ nested / rng-)agg+?
419
403
Et = copy (derH .Et )
420
404
if not fd and _N .altG and N .altG : # not for CL, eval M?
421
405
alt_Link = comp_N (_N .altG , N .altG , _N .altG .Et [2 ]/ N .altG .Et [2 ]) # no angle,dist, init alternating PPds | dPs?
@@ -457,14 +441,11 @@ def sum2graph(root, grapht, fd, nest, fsub=0): # sum node and link params into
457
441
N .root [- 1 ] = graph # replace Gt, if single root, else N.root[-1][-1] = graph
458
442
if fg :
459
443
graph .Et [:2 ] += np .array ([M ,D ]) * icoef ** 2
460
- if derH :
461
- graph .derH = derH # lower layers
462
- derLay = CH ().add_tree ([link .derH for link in link_ ])
463
- for i , (Fork , fork ) in enumerate (zip (graph .derH .tft , derLay .tft )):
464
- fork .root = graph ;
465
- Fork .add_tree (fork ) # something like this instead?
466
- # graph.derH.tft[i].add_tree += [fork] # deeper tfts are added by feedback
467
- graph .derH .Et += Et # arg Et
444
+ # sum link.derHs:
445
+ derLay = CH ().add_tree ([link .derH for link in link_ ])
446
+ graph .derH = derH .lft + [derLay ]
447
+ # derLay Et = arg Et:
448
+ graph .Et += Et ; graph .derH .Et += Et
468
449
L = len (node_ )
469
450
yx = np .divide (yx ,L ); graph .yx = yx
470
451
# ave distance from graph center to node centers:
0 commit comments