Skip to content

Commit a9b95af

Browse files
committed
Changes:
1. Edits in agg_recursion.
1 parent 00e92c4 commit a9b95af

File tree

2 files changed

+55
-49
lines changed

2 files changed

+55
-49
lines changed

frame_2D_alg/vectorize_edge_blob/agg_recursion.py

+21-17
Original file line numberDiff line numberDiff line change
@@ -16,29 +16,31 @@
1616
postfix _ denotes array of same-name elements, multiple _s is nested array
1717
capitalized vars are summed small-case vars '''
1818

19-
def cross_comp(frame): # breadth-first (node_,L_) cross-comp, clustering, recursion
19+
def cross_comp(frame, layt): # breadth-first (node_,L_) cross-comp, clustering, recursion
2020

2121
N_,L_,Et = comp_node_(frame.subG_) # cross-comp exemplars, extrapolate to their node_s?
2222
# mfork
2323
if val_(Et, fo=1) > 0:
2424
mlay = CH().add_H([L.derH for L in L_])
25-
frame.derH.append_(mlay) # redo with append to He.layt and recursive feedback
25+
layt.append_(mlay); frame.Et += mlay.Et # append to root He.layt and recursive feedback
2626
pL_ = {l for n in N_ for l,_ in get_rim(n, fd=0)}
2727
if len(pL_) > ave_L:
28-
cluster_N_(frame, pL_, fd=0) # optional divisive clustering, may call alternating centroid clustering and agg_cluster
28+
cluster_N_([frame, mlay], pL_, fd=0) # optional divisive clustering, may call alternating centroid clustering and agg_cluster
29+
layt.depth = mlay.depth+1 # feedback depth in m fork
30+
2931
# dfork, derH.layt has 1|2 forks
3032
if val_(Et, mEt=Et,fo=1) > 0: # same root for L_, root.link_ was compared in root-forming for alt clustering
3133
for L in L_:
3234
L.extH, L.root, L.mL_t, L.rimt, L.aRad, L.visited_, L.Et = CH(), frame, [[],[]], [[],[]], 0, [L], copy(L.derH.Et)
3335
lN_,lL_,dEt = comp_link_(L_,Et)
3436
if val_(dEt, mEt=Et, fo=1) > 0:
3537
dlay = CH().add_H([L.derH for L in lL_])
36-
frame.derH.append_(dlay)
38+
layt.append_(dlay); frame.Et += dlay.Et # pack 2nd lay in layt
3739
plL_ = {l for n in lN_ for l,_ in get_rim(n, fd=1)}
3840
if len(plL_) > ave_L:
39-
cluster_N_(frame, plL_, fd=1)
41+
cluster_N_([frame, dlay], plL_, fd=1)
4042

41-
def cluster_N_(root, L_, fd, nest=0): # top-down segment L_ by >ave ratio of L.dists
43+
def cluster_N_(roott, L_, fd, nest=0): # top-down segment L_ by >ave ratio of L.dists
4244

4345
L_ = sorted(L_, key=lambda x: x.dist, reverse=True) # lower-dist links
4446
_L = L_[0]
@@ -54,7 +56,9 @@ def cluster_N_(root, L_, fd, nest=0): # top-down segment L_ by >ave ratio of L.
5456
min_dist = _L.dist
5557
Gt_ = []
5658
for N in N_: # cluster current distance segment
57-
if len(N.root) > nest: continue # merged, root[0] = edge
59+
# root may not be converted yet
60+
if not isinstance(N.root, list): N.root = [N.root]
61+
if len(N.root) > nest: continue # merged, root[0] = edge
5862
node_,link_, et = set(), set(), np.zeros(4)
5963
Gt = [node_,link_,et,min_dist]; N.root += [Gt]
6064
_eN_ = {N}
@@ -81,8 +85,8 @@ def cluster_N_(root, L_, fd, nest=0): # top-down segment L_ by >ave ratio of L.
8185
Gt[0] = list(node_)
8286
Gt_ += [Gt]
8387
# per dist segment:
84-
root.subG_ = [sum2graph(root, Gt, fd, nest) for Gt in Gt_]
85-
find_centroids(root)
88+
roott[0].subG_ = [sum2graph(roott[0], Gt, fd, nest) for Gt in Gt_]
89+
find_centroids(roott)
8690

8791
''' Hierarchical clustering should alternate between two phases: generative via connectivity and compressive via centroid.
8892
@@ -95,7 +99,7 @@ def cluster_N_(root, L_, fd, nest=0): # top-down segment L_ by >ave ratio of L.
9599
So connectivity clustering is a generative learning phase, forming new derivatives and structured composition levels,
96100
while centroid clustering is a compressive phase, reducing multiple similar comparands to a single exemplar. '''
97101

98-
def find_centroids(graph):
102+
def find_centroids(grapht):
99103

100104
def centroid(dnode_, node_, C=None): # sum|subtract and average Rim nodes
101105

@@ -111,7 +115,7 @@ def centroid(dnode_, node_, C=None): # sum|subtract and average Rim nodes
111115
if n.derH: C.derH.add_H(n.derH, dir=s, fc=1)
112116
if n.extH: C.extH.add_H(n.extH, dir=s, fc=1)
113117
# get averages:
114-
k = len(dnode_); C.Et/=k; C.latuple/=k; C.vertuple/=k; C.aRad/=k; C.yx /= k
118+
k = len(dnode_); C.Et/=k; C.latuple/=k; C.vert/=k; C.aRad/=k; C.yx /= k
115119
if C.derH: C.derH.norm_(k) # derH/=k
116120
C.box = reduce(extend_box, (n.box for n in node_))
117121
return C
@@ -165,7 +169,7 @@ def centroid_cluster(N): # refine and extend cluster with extN_
165169
return N # keep seed node
166170

167171
# find representative centroids for complemented Gs: m-core + d-contour, initially from unpacked edge
168-
N_ = sorted([N for N in graph.subG_ if any(N.Et)], key=lambda n: n.Et[0], reverse=True)
172+
N_ = sorted([N for N in grapht[0].subG_ if any(N.Et)], key=lambda n: n.Et[0], reverse=True)
169173
subG_ = []
170174
for N in N_:
171175
N.sign, N.m, N.fin = 1, 0, 0 # setattr: C update sign, inclusion val, prior C inclusion flag
@@ -176,9 +180,9 @@ def centroid_cluster(N): # refine and extend cluster with extN_
176180
else: # the rest of N_ M is lower
177181
subG_ += [N for N in N_[i:] if not N.fin]
178182
break
179-
graph.subG_ = subG_ # mix of Ns and Cs: exemplars of their network?
180-
if len(graph.subG_) > ave_L:
181-
cross_comp(graph) # selective connectivity clustering between exemplars, extrapolated to their node_
183+
grapht[0].subG_ = subG_ # mix of Ns and Cs: exemplars of their network?
184+
if len(grapht[0].subG_) > ave_L:
185+
cross_comp(*grapht) # selective connectivity clustering between exemplars, extrapolated to their node_
182186

183187

184188
if __name__ == "__main__":
@@ -191,7 +195,7 @@ def centroid_cluster(N): # refine and extend cluster with extN_
191195
subG_ = []
192196
for edge in frame.subG_:
193197
if edge.subG_: # or / and edge Et?
194-
find_centroids(edge) # no find_centroids in trace_edge
198+
find_centroids([edge, edge.derH]) # no find_centroids in trace_edge
195199
subG_ += edge.subG_ # unpack edge, or keep if connectivity cluster, or in flat blob altG_?
196200
frame.subG_ = subG_
197-
cross_comp(frame) # calls connectivity clustering
201+
cross_comp(frame, frame.derH) # calls connectivity clustering

frame_2D_alg/vectorize_edge_blob/vect_edge.py

+34-32
Original file line numberDiff line numberDiff line change
@@ -71,23 +71,23 @@ def __bool__(H): return bool(H.Et[3] != 0)
7171

7272
def copy_md_C(he, root, dir=1, fc=0): # dir is sign if called from centroid, which doesn't use dir
7373

74-
md_t = [np.array([m_ * dir if fc else copy(m_), d_ * dir]) for m_, d_ in he.H]
74+
md_t = [np.array([m_ * dir if fc else copy(m_), d_ * dir]) for m_, d_ in he.layt]
7575
# m_ * dir only if called from centroid()
7676
Et = he.Et * dir if fc else copy(he.Et)
7777

78-
return CH(root=root, H=md_t, node_=copy(he.node_), Et=Et, i=he.i, i_=he.i_)
78+
return CH(root=root, layt=md_t, node_=copy(he.node_), Et=Et, i=he.i, i_=he.i_)
7979

8080
def copy_(He, root, dir=1, fc=0): # comp direction may be reversed to -1
8181

8282
C = CH(root=root, node_=copy(He.node_), Et=copy(He.Et), i=He.i, i_=He.i_)
83-
for he in He.H:
84-
C.H += [he.copy_(root=C, dir=dir, fc=fc) if isinstance(he.H[0],CH) else
83+
for he in He.layt:
84+
C.layt += [he.copy_(root=C, dir=dir, fc=fc) if isinstance(he.layt[0],CH) else
8585
he.copy_md_C(root=C, dir=dir, fc=fc)]
8686
return C
8787

8888
def add_md_C(Lay, lay, dir=1, fc=0):
8989

90-
for Md_, md_ in zip(Lay.H, lay.H): # [mdext, ?vert, mdVer]
90+
for Md_, md_ in zip(Lay.layt, lay.layt): # [mdext, ?vert, mdVer]
9191
Md_ += np.array([md_[0]*dir if fc else md_[0].copy(), md_[1]*dir])
9292

9393
Lay.Et += lay.Et * dir if fc else copy(lay.Et)
@@ -96,14 +96,14 @@ def add_H(HE, He_, dir=1, fc=0): # unpack derHs down to numericals and sum them
9696
if not isinstance(He_,list): He_ = [He_]
9797

9898
for He in He_:
99-
for Lay, lay in zip_longest(HE.H, He.H, fillvalue=None):
99+
for Lay, lay in zip_longest(HE.layt, He.layt, fillvalue=None):
100100
if lay:
101101
if Lay: # unpack|add, same nesting in both lays
102-
Lay.add_H(lay,dir,fc) if isinstance(lay.H[0],CH) else Lay.add_md_C(lay,dir,fc)
102+
Lay.add_H(lay,dir,fc) if isinstance(lay.layt[0],CH) else Lay.add_md_C(lay,dir,fc)
103103
elif Lay is None:
104-
HE.append_( lay.copy_(root=HE, dir=dir, fc=fc) if isinstance(lay.H[0],CH) else lay.copy_md_C(root=HE, dir=dir, fc=fc))
104+
HE.append_( lay.copy_(root=HE, dir=dir, fc=fc) if isinstance(lay.layt[0],CH) else lay.copy_md_C(root=HE, dir=dir, fc=fc))
105105
elif lay is not None and Lay is None:
106-
HE.H += [CH()]
106+
HE.layt += [CH()]
107107

108108
HE.node_ += [node for node in He.node_ if node not in HE.node_] # empty in CL derH?
109109
HE.Et += He.Et * dir
@@ -113,37 +113,37 @@ def add_H(HE, He_, dir=1, fc=0): # unpack derHs down to numericals and sum them
113113
def append_(HE,He, flat=0):
114114

115115
if flat:
116-
for i, lay in enumerate(He.H):
116+
for i, lay in enumerate(He.layt):
117117
if lay:
118-
lay = lay.copy_(root=HE) if isinstance(lay.H[0],CH) else lay.copy_md_C(root=HE)
119-
lay.i = len(HE.H) + i
120-
HE.H += [lay] # lay may be empty to trace forks
118+
lay = lay.copy_(root=HE) if isinstance(lay.layt[0],CH) else lay.copy_md_C(root=HE)
119+
lay.i = len(HE.layt) + i
120+
HE.layt += [lay] # lay may be empty to trace forks
121121
else:
122-
He.i = len(HE.H); He.root = HE; HE.H += [He] # He can't be empty
123-
HE.H += [He]
122+
He.i = len(HE.layt); He.root = HE; HE.layt += [He] # He can't be empty
123+
HE.layt += [He]
124124
HE.Et += He.Et
125125
return HE
126126

127127
def comp_md_C(_md_C, md_C, rn, root, olp=1., dir=1):
128128

129129
der_md_t = []
130130
Et = np.zeros(2)
131-
for _md_, md_ in zip(_md_C.H, md_C.H): # [mdext, ?vert, mdvert]
131+
for _md_, md_ in zip(_md_C.layt, md_C.layt): # [mdext, ?vert, mdvert]
132132
# comp ds:
133133
der_md_, et = comp_md_(_md_[1], md_[1], rn, dir=dir)
134134
der_md_t += [der_md_]
135135
Et += et
136136

137-
return CH(root=root, H=der_md_t, Et=np.append(Et,[olp, .3 if len(der_md_t)==1 else 2.3])) # .3 in default comp ext)
137+
return CH(root=root, layt=der_md_t, Et=np.append(Et,[olp, .3 if len(der_md_t)==1 else 2.3])) # .3 in default comp ext)
138138

139139
def comp_H(_He, He, rn, root):
140140

141141
derH = CH(root=root) # derH.H ( flat lay.H, or nest per higher lay.H for selective access?
142142
# lay.H maps to higher Hs it was derived from, len lay.H = 2 ^ lay_depth (unpacked root H[:i])
143143

144-
for _lay, lay in zip(_He.H, He.H): # both may be empty CH to trace fork types
144+
for _lay, lay in zip(_He.layt, He.layt): # both may be empty CH to trace fork types
145145
if _lay and lay: # same depth
146-
if isinstance(lay.H[0], CH):
146+
if isinstance(lay.layt[0], CH):
147147
dLay = _lay.comp_H(lay, rn, root=derH) # deeper unpack -> comp_md_t
148148
else:
149149
dLay = _lay.comp_md_C(lay, rn=rn, root=derH, olp=(_He.Et[3]+He.Et[3]) /2) # comp shared layers, add n to olp?
@@ -154,26 +154,26 @@ def comp_H(_He, He, rn, root):
154154

155155
def norm_(He, n):
156156

157-
for lay in He.H: # not empty list
157+
for lay in He.layt: # not empty list
158158
if lay:
159-
if isinstance(lay.H[0], CH):
159+
if isinstance(lay.layt[0], CH):
160160
lay.norm_C(n)
161161
else:
162-
for md_ in lay.H: md_ *= n
162+
for md_ in lay.layt: md_ *= n
163163
lay.Et *= n
164164
He.Et *= n
165165

166166
# not updated:
167167
def sort_H(He, fd): # re-assign olp and form priority indices for comp_H, if selective and aligned
168168

169169
i_ = [] # priority indices
170-
for i, lay in enumerate(sorted(He.H, key=lambda lay: lay.Et[fd], reverse=True)):
170+
for i, lay in enumerate(sorted(He.layt, key=lambda lay: lay.Et[fd], reverse=True)):
171171
di = lay.i - i # lay index in H
172172
lay.olp += di # derR- valR
173173
i_ += [lay.i]
174174
He.i_ = i_ # comp_H priority indices: node/m | link/d
175175
if not fd:
176-
He.root.node_ = He.H[i_[0]].node_ # no He.node_ in CL?
176+
He.root.node_ = He.layt[i_[0]].node_ # no He.node_ in CL?
177177

178178

179179
class CG(CBase): # PP | graph | blob: params of single-fork node_ cluster
@@ -197,7 +197,7 @@ def __init__(G, fd=0, rng=1, root=[], node_=[], link_=[], subG_=[], subL_=[],
197197
G.rim = [] # flat links of any rng, may be nested in clustering
198198
G.aRad = 0 # average distance between graph center and node center
199199
G.box = [np.inf, np.inf, -np.inf, -np.inf] if box is None else box # y0,x0,yn,xn
200-
G.yx = np.array([0,0]) if yx is None else yx # init PP.yx = [(y0+yn)/2,(x0,xn)/2], then ave node yx
200+
G.yx = np.zeros(2) if yx is None else yx # init PP.yx = [(y0+yn)/2,(x0,xn)/2], then ave node yx
201201
G.altG = CG(altG=G) if altG is None else altG # adjacent gap+overlap graphs, vs. contour in frame_graphs (prevent cyclic)
202202
# G.fback_ = [] # always from CGs with fork merging, no dderHm_, dderHd_
203203
# id_H: list = z([[]]) # indices in all layers(forks, if no fback merge
@@ -219,7 +219,7 @@ def __init__(l, nodet=None, dist=None, derH=None, angle=None, box=None, H_=None,
219219
l.yx = [0,0] if yx is None else yx
220220
l.H_ = [] if H_ is None else H_ # if agg++| sub++?
221221
# add med, rimt, elay | extH in der+
222-
def __bool__(l): return bool(l.derH.H)
222+
def __bool__(l): return bool(l.derH.layt)
223223

224224
def vectorize_root(frame):
225225

@@ -232,7 +232,7 @@ def vectorize_root(frame):
232232
if blob.Et[0] * (len(blob.node_)-1)*(blob.rng+1) > ave:
233233
# init for agg+:
234234
if not hasattr(frame, 'derH'):
235-
frame.derH = CH(root=frame); frame.root = None; frame.subG_ = []
235+
frame.derH = CH(root=frame); frame.root = None; frame.subG_ = []; frame.Et = np.zeros(4)
236236
Y,X,_,_,_,_ = blob.latuple
237237
lat = np.array([.0,.0,.0,.0,.0,np.zeros(2)],dtype=object); vert = np.array([np.zeros(6), np.zeros(6)])
238238
for PP in blob.node_:
@@ -432,8 +432,8 @@ def comp_N(_N,N, rn, angle=None, dist=None, dir=1): # dir if fd, Link.derH=dH,
432432
md_t = [mdext, vert, md_vert]
433433
Et = np.array([mL+mA +et1[0]+et2[0], abs(dL)+abs(dA) +et1[1]+et2[1], 2.3, olp])
434434
# 1st lay:
435-
md_C = CH(H = md_t, Et=Et)
436-
derH = CH(H=[md_C], Et=copy(Et)) # no lay = CH(H=[md_C], Et=copy(Et), n=n)
435+
md_C = CH(layt = md_t, Et=Et)
436+
derH = CH(layt=[md_C], Et=copy(Et)) # no lay = CH(H=[md_C], Et=copy(Et), n=n)
437437
if _N.derH and N.derH:
438438
dderH = _N.derH.comp_H(N.derH, rn, root=derH) # comp shared layers
439439
derH.append_(dderH, flat=1)
@@ -476,14 +476,16 @@ def sum2graph(root, grapht, fd, nest): # sum node and link params into graph, a
476476
if fg:
477477
vert = N.vert; M += np.sum(vert[0]); D += np.sum(vert[1]); graph.vert += vert
478478
graph.latuple += N.latuple
479-
N.root[-1] = graph # replace Gt, if single root, else N.root[-1][-1] = graph
479+
if isinstance(N.root, list): N.root[-1] = graph # replace Gt, if single root, else N.root[-1][-1] = graph (agg++)
480+
else: N.root = graph
481+
480482
if fg:
481483
graph.Et[:2] += np.array([M,D]) * icoef**2
482484
if derH:
483485
graph.derH = derH # lower layers
484486
derLay = CH().add_H([link.derH for link in link_])
485-
for lay in derLay.H:
486-
lay.root = graph; graph.derH.H += [lay] # concat new layer, add node_? higher layers are added by feedback
487+
for lay in derLay.layt:
488+
lay.root = graph; graph.derH.layt += [lay] # concat new layer, add node_? higher layers are added by feedback
487489
graph.derH.Et += Et # arg Et
488490
L = len(node_)
489491
yx = np.divide(yx,L); graph.yx = yx

0 commit comments

Comments
 (0)