Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
GuillaumeLaplante-Anfossi
GitHub Repository: GuillaumeLaplante-Anfossi/Poissons
Path: blob/main/GeneratingDiagonalsViaShift/operadic_tree_nestings.py
1017 views
1
import sys
2
from itertools import permutations, chain, combinations, product
3
from copy import deepcopy
4
5
from diagonals_via_shift import SU_diag, LA_diag
6
7
class Tree:
8
def __init__(self, data = None, children = []):
9
self.data = data
10
self.children = children
11
12
#https://stackoverflow.com/questions/20242479/printing-a-tree-data-structure-in-python
13
def __str__(self, level=0):
14
ret = "\t"*level+repr(self.data)+"\n"
15
for child in self.children:
16
ret += child.__str__(level+1)
17
return ret
18
19
def __repr__(self):
20
return '<tree node representation>'
21
22
def non_empty_powerset(iterable):
23
s = list(iterable)
24
return chain.from_iterable(combinations(s, r) for r in range(1,len(s)+1))
25
26
def increment_tree(t,v):
27
'''Update the data of all vertices of t to data += v.'''
28
base = t
29
t.data = t.data + v
30
for child in t.children:
31
increment_tree(child,v)
32
33
return base
34
35
def PT(n):
36
'''The set of planar trees with n non-root vertices labelled under infix order.
37
38
Exploiting catalan recurrence for generation.
39
C = 1 + z C^2
40
'''
41
if n == 0:
42
return [Tree(0)]
43
44
trees = []
45
for k in range(n):
46
rec_1 = PT(k)
47
rec_2 = PT(n-1-k)
48
for t1 in rec_1:
49
for t2 in rec_2:
50
t = deepcopy(t1)
51
t.children.append(increment_tree(deepcopy(t2),k+1))
52
trees.append(t)
53
54
return trees
55
56
def connected_to_root(t):
57
'''Returns a set of all subtrees of t which are connected to root.'''
58
if t.children == []:
59
return [] #If no children then have no sub-trees
60
#Recurse
61
connected_to_children = []
62
for child in t.children:
63
child_and_edge_to_root = [[child.data]] #the edge to child is a trivial subtree
64
for x in connected_to_root(child):
65
x.append(child.data)
66
child_and_edge_to_root.append(x) #the edge to child, and each subtree of child is a subtree
67
connected_to_children.append(child_and_edge_to_root)
68
69
#Combine
70
all_conn_to_root = []
71
#Choose a non-emptyset of children to be connected to
72
for choose_conn_children in non_empty_powerset(connected_to_children):
73
#Construct the product of all sub-trees from this choice.
74
for p in product(*choose_conn_children):
75
sub = []
76
for e in p:
77
sub += e
78
all_conn_to_root.append(sub)
79
80
return all_conn_to_root
81
82
def compute_nests(t):
83
'''Computes all nests of a tree.
84
This is equivalent to computing all connected subtrees of t,
85
which is equivalent to the union of all vertices in t,
86
subtrees of t connected to root
87
'''
88
#base case
89
nests = connected_to_root(t)
90
#recursion
91
for child in t.children:
92
sub_nests = compute_nests(child)
93
if sub_nests != []:
94
nests += sub_nests
95
return nests
96
97
def check_nesting_of_tree(d,t):
98
'''
99
Checks that sigma, tau is a nesting of tree t.
100
101
By construction meets compatibility, and trivial nest.
102
So just need to check each element is a nest.
103
'''
104
sigma,tau = d
105
N = compute_nests(t)
106
N = [sorted(x) for x in N]
107
N.sort()
108
109
#Manipulate into sigma_1 | sigma_1 \cup sigma_2|...
110
sigma_nests = []
111
for i in range(1,len(sigma)+1):
112
sigma_nests.append(sorted(list(chain(*sigma[:i]))))
113
114
#check
115
for block in sigma_nests:
116
if block not in N:
117
return False
118
119
#repeat
120
tau_nests = []
121
for i in range(1,len(tau)+1):
122
tau_nests.append(sorted(list(chain(*tau[:i]))))
123
for block in tau_nests:
124
if block not in N:
125
return False
126
127
return True
128
129
def proj_nesting(sigma,t):
130
'''
131
Given an ordered partition sigma, projects it onto a tree t.
132
133
Ex tree from email:
134
135
'''
136
proj = []
137
N = compute_nests(t)
138
N = [sorted(x) for x in N]
139
N.sort()
140
141
print(N)
142
143
#Manipulate into sigma_1 | sigma_1 \cup sigma_2|...
144
merged = []
145
for i in range(1,len(sigma)+1):
146
merged.append(sorted(list(chain(*sigma[:i]))))
147
148
for block in merged:
149
if block in N:
150
proj.append(block)
151
152
def construct_tree_nesting_dict(n, diag = "SU"):
153
if diag == "SU":
154
computed_diag = SU_diag(n)
155
elif diag == "LA":
156
computed_diag = LA_diag(n)
157
158
pt = PT(n)
159
tree_nesting_dict = {}
160
for t in pt:
161
#Use strings to uniquely identify trees
162
s = str(t)
163
tree_nesting_dict[s] = []
164
#Incredibly weird bug, can only iterate through computed diag once...
165
#Maybe did something weired with iterators, can't remember.
166
#Fine as is, but finicky.
167
for d in computed_diag:
168
sigma,tau = d
169
for t in pt:
170
if (not check_proj_nesting(sigma,t)) or (not check_proj_nesting(tau,t)):
171
continue
172
s = str(t)
173
tree_nesting_dict[s].append(d)
174
175
return tree_nesting_dict
176
177
def check_proj_nesting(sigma,t):
178
''''''
179
return len(sigma) == len(proj_nesting(sigma,t))
180
181
def proj_nesting(sigma,t):
182
'''
183
Given an ordered partition sigma, projects it onto a tree t.
184
Ex tree from email:
185
'''
186
proj = []
187
N = compute_nests(t)
188
N = [sorted(x) for x in N]
189
N.sort()
190
191
#Manipulate into sigma_1 | sigma_1 \cup sigma_2|...
192
merged = []
193
for i in range(1,len(sigma)+1):
194
merged.append(sorted(list(chain(*sigma[:i]))))
195
196
#print(N)
197
#print(sigma)
198
#print(merged)
199
#print("loop")
200
201
#Break each merged block into minimal nests
202
min_nesting = []
203
for block in merged:
204
#print("block",block)
205
min_nests_block = []
206
207
start = 0
208
for i in range(1,len(block)+1):
209
#print(block[start:i],block[start:i] in N)
210
if block[start:i] in N:
211
continue
212
else:
213
#print("found", i, block[start:(i-1)])
214
min_nests_block.append(block[start:(i-1)])
215
start=i-1
216
#Wrap up
217
if start<len(block)+1:
218
min_nests_block.append(block[start:])
219
#inefficient
220
for m in min_nests_block:
221
if m not in min_nesting:
222
min_nesting.append(m)
223
#print("min_nesting",min_nesting)
224
#print("\n")
225
return min_nesting
226
227
if __name__ == '__main__':
228
229
orig_stdout = sys.stdout
230
f = open('bijection_check.txt', 'w')
231
sys.stdout = f
232
233
234
n = 5
235
pt = PT(n)
236
'''
237
t = pt[0]
238
print(t)
239
print(proj_nesting([[1, 4], [2, 3]],t))
240
print(check_proj_nesting([[1, 4], [2, 3]],t))
241
print(proj_nesting([[1, 4], [2], [3]],t))
242
print(check_proj_nesting([[1, 4], [2], [3]],t))
243
print(proj_nesting([[3, 4], [2], [1]],t))
244
print(check_proj_nesting([[3, 4], [2], [1]],t))
245
246
print(proj_nesting([[1, 3], [2], [4]],t))
247
print(check_proj_nesting([[1, 3], [2], [4]],t))
248
249
exit()
250
251
252
nesting_dict_SU = construct_tree_nesting_dict(n, diag = "SU")
253
nesting_dict_LA = construct_tree_nesting_dict(n, diag = "LA")
254
t = pt[33]
255
s = str(t)
256
print(s)
257
print("countLA",len(nesting_dict_LA[s]))
258
print("countSU",len(nesting_dict_SU[s]))
259
diffLA = []
260
diffSU = []
261
for x in nesting_dict_LA[s]:
262
if x not in nesting_dict_SU[s]:
263
diffLA.append(x)
264
for x in nesting_dict_SU[s]:
265
if x not in nesting_dict_LA[s]:
266
diffSU.append(x)
267
print("in LA but not in SU",len(diffLA))
268
print("in SU but not in LA",len(diffSU))
269
270
sortedLA = [[sorted(x[0]),sorted(x[1])] for x in nesting_dict_LA[s]]
271
sortedSU = [[sorted(x[0]),sorted(x[1])] for x in nesting_dict_SU[s]]
272
273
print("In SU and reordering of blocks is not in LA")
274
for i in range(len(nesting_dict_SU[s])):
275
if sortedSU[i] not in sortedLA:
276
print(nesting_dict_SU[s][i])
277
print("In LA and reordering of blocks is not in SU")
278
for i in range(len(nesting_dict_LA[s])):
279
if sortedLA[i] not in sortedSU:
280
print(nesting_dict_LA[s][i])
281
282
print("\n")
283
print("All LA")
284
for x in nesting_dict_LA[s]:
285
print(x)
286
287
print("\n")
288
print("All SU")
289
for x in nesting_dict_LA[s]:
290
print(x)
291
292
exit()
293
'''
294
295
for n in range(3,5+1):
296
print("For n=",n)
297
nesting_dict_SU = construct_tree_nesting_dict(n, diag = "SU")
298
nesting_dict_LA = construct_tree_nesting_dict(n, diag = "LA")
299
trees = PT(n)
300
for i in range(len(trees)):
301
t = trees[i]
302
s = str(t)
303
304
if len(nesting_dict_SU[s]) != len(nesting_dict_LA[s]):
305
print("Tree:")
306
print(s)
307
#print(compute_nests(t))
308
print("SU Count:",len(nesting_dict_SU[s]))
309
print("LA Count:",len(nesting_dict_LA[s]))
310
311
diffLA = []
312
diffSU = []
313
for x in nesting_dict_LA[s]:
314
if x not in nesting_dict_SU[s]:
315
diffLA.append(x)
316
for x in nesting_dict_SU[s]:
317
if x not in nesting_dict_LA[s]:
318
diffSU.append(x)
319
320
print("disjoint",len(diffLA),len(diffSU))
321
322
else:
323
print("For tree i=",i+1,"shared count=",len(nesting_dict_SU[s]))
324
325
326
sys.stdout = orig_stdout
327
f.close()
328