Contact
CoCalc Logo Icon
StoreFeaturesDocsShareSupport News AboutSign UpSign In
| Download
Project: admcycles
Views: 724
Visibility: Unlisted (only visible to those who know the link)
Image: ubuntu2004
1
from __future__ import print_function
2
3
import itertools
4
5
from sympy.utilities.iterables import partitions, permutations, multiset_partitions
6
7
# pylint does not know sage
8
from sage.graphs.graph import Graph # pylint: disable=import-error
9
from sage.graphs.generators.basic import CompleteBipartiteGraph # pylint: disable=import-error
10
# sage documentation says compositions are better than OrderedPartitions, no idea why....
11
from sage.combinat.composition import Compositions as sage_part # pylint: disable=import-error
12
from sage.combinat.partition import OrderedPartitions # pylint: disable=import-error
13
from sage.misc.cachefunc import cached_function # pylint: disable=import-error
14
15
from admcycles.stable_graph import StableGraph as stgraph
16
import admcycles.diffstrata.levelgraph
17
import admcycles.diffstrata.levelstratum
18
from admcycles.diffstrata.sig import Signature
19
20
############################################################
21
############################################################
22
#### Old BIC generation:
23
#### This was the first attempt at generating BICs
24
#### (generating all stable graphs with admcycles and then
25
#### putting all possible bipartite structures etc on them).
26
#### It's nice for historic reasons but painfully slow!
27
#### Definitely use bic_alt below instead!!!
28
############################################################
29
############################################################
30
31
32
def SageGraph(gr):
33
# converts stgraph gr in Sage graph
34
legdic={i:vnum for vnum in range(len(gr.legs(copy=False))) for i in gr.legs(vnum,copy=False)}
35
return Graph([(legdic[a], legdic[b]) for (a,b) in gr.edges(copy=False)],loops=True, multiedges=True)
36
37
38
def bics(g,orders):
39
"""
40
Generate BICs for stratum with signature orders of genus g.
41
42
DO NOT USE!!! USE bic_alt instead!!!
43
44
Args:
45
g (int): genus
46
orders (tuple): signature tuple
47
48
Returns:
49
list: list of BICs
50
"""
51
print('WARNING! This is not the normal BIC generation algorithm!')
52
print("Only use if you know what you're doing!")
53
n=len(orders)
54
bound=g+n
55
result=[] # list of levelgraphs
56
orderdict={i+1:orders[i] for i in range(n)}
57
58
for e in range(1,bound+1):
59
# look at which stgraphs in Mbar_g,n with e edges are bipartite
60
for gr in new_list_strata(g,n,e):
61
check=SageGraph(gr).is_bipartite(True)
62
if check[0]:
63
# check[1] contains dictionary {vertices: 0 or 1}
64
vert1=[v for v in check[1] if check[1][v]==0]
65
vert2=[v for v in check[1] if check[1][v]==1]
66
result+=bics_on_bipgr(gr,vert1,vert2,orderdict)
67
result+=bics_on_bipgr(gr,vert2,vert1,orderdict)
68
return result
69
70
71
def bics_on_bipgr(gr,vertup,vertdown,orderdict):
72
# takes stable graph and partition of range(len(gr.genera)) into vertup, vertdown
73
# creates list of possible pole orders at edges
74
result=[]
75
76
# removed from admcycles so reinserted here for legacy purposes:
77
def dicunion(*dicts):
78
return dict(itertools.chain.from_iterable(dct.items() for dct in dicts))
79
80
numvert=len(gr.genera(copy=False))
81
halfedges=gr.halfedges()
82
halfedgeinvers={e0:e1 for (e0,e1) in gr.edges(copy=False)}
83
halfedgeinvers.update({e1:e0 for (e0,e1) in gr.edges(copy=False)})
84
85
levels=[0 for i in range(numvert)]
86
for i in vertdown:
87
levels[i]=-1
88
89
helist=[[l for l in ll if l in halfedges] for ll in gr.legs(copy=False)] #list of half-edges of each vertex
90
degs=[] # list (with len numvert) of orders that need to be provided by pole orders of half-edges (not legs)
91
for v in range(numvert):
92
degs.append(2*gr.genera(v)-2-sum([orderdict[l] for l in gr.list_markings(v)]))
93
# if degs<0:
94
# return []
95
96
weightparts=[]
97
for v in vertup:
98
vweightpart=[]
99
for part in OrderedPartitions(degs[v]+len(helist[v]),len(helist[v])):
100
# dictionary of weights from edges connected to vertex v
101
vdic={helist[v][i]:part[i]-1 for i in range(len(helist[v]))}
102
vdic.update({halfedgeinvers[helist[v][i]]:-part[i]-1 for i in range(len(helist[v]))})
103
#print vdic
104
vweightpart.append(vdic)
105
weightparts+=[vweightpart]
106
#print weightparts
107
108
for parts in itertools.product(*weightparts):
109
#print parts
110
poleorders=dicunion(orderdict,*parts)
111
CandGraph=admcycles.diffstrata.levelgraph.LevelGraph(gr.genera(copy=False),gr.legs(copy=False),gr.edges(copy=False),poleorders,levels,quiet=True)
112
if CandGraph.is_legal(True) and CandGraph.checkadmissible(True):
113
result.append(CandGraph)
114
return result
115
116
117
def new_list_strata(g, n, r):
118
return [lis[0] for lis in admcycles.admcycles.degeneration_graph(int(g), n, r)[0][r]]
119
120
############################################################
121
############################################################
122
123
############################################################
124
############################################################
125
#### New BIC generation. This is currently used.
126
############################################################
127
############################################################
128
129
130
@cached_function
131
def bic_alt_noiso(sig):
132
"""
133
Construct all non-horizontal divisors in the stratum sig.
134
135
More precisely, each BIC is LevelGraph with two levels numbered 0, -1
136
and marked points 1,...,n where the i-th point corresponds to the element
137
i-1 of the signature.
138
139
Note that this is the method called by GeneralisedStratum.gen_bic.
140
141
Args:
142
sig (Signature): Signature of the stratum.
143
144
Returns:
145
list: list of 2-level non-horizontal LevelGraphs.
146
147
EXAMPLES ::
148
149
sage: from admcycles.diffstrata import *
150
sage: assert comp_list(bic_alt(Signature((1,1))),\
151
[LevelGraph([1, 0],[[3, 4], [1, 2, 5, 6]],[(3, 5), (4, 6)],{1: 1, 2: 1, 3: 0, 4: 0, 5: -2, 6: -2},[0, -1],True),\
152
LevelGraph([1, 1, 0],[[4], [3], [1, 2, 5, 6]],[(3, 5), (4, 6)],{1: 1, 2: 1, 3: 0, 4: 0, 5: -2, 6: -2},[0, 0, -1],True),\
153
LevelGraph([1, 1],[[3], [1, 2, 4]],[(3, 4)],{1: 1, 2: 1, 3: 0, 4: -2},[0, -1],True),\
154
LevelGraph([2, 0],[[3], [1, 2, 4]],[(3, 4)],{1: 1, 2: 1, 3: 2, 4: -4},[0, -1],True)])
155
156
sage: assert comp_list(bic_alt(Signature((2,))),\
157
[LevelGraph([1, 1],[[2], [1, 3]],[(2, 3)],{1: 2, 2: 0, 3: -2},[0, -1],True),\
158
LevelGraph([1, 0],[[2, 3], [1, 4, 5]],[(2, 4), (3, 5)],{1: 2, 2: 0, 3: 0, 4: -2, 5: -2},[0, -1],True)])
159
160
sage: assert comp_list(bic_alt(Signature((4,))),\
161
[LevelGraph([1, 1, 0],[[2, 4], [3], [1, 5, 6, 7]],[(2, 5), (3, 6), (4, 7)],{1: 4, 2: 0, 3: 0, 4: 0, 5: -2, 6: -2, 7: -2},[0, 0, -1],True),\
162
LevelGraph([1, 1, 1],[[3], [2], [1, 4, 5]],[(2, 4), (3, 5)],{1: 4, 2: 0, 3: 0, 4: -2, 5: -2},[0, 0, -1],True),\
163
LevelGraph([2, 0],[[2, 3], [1, 4, 5]],[(2, 4), (3, 5)],{1: 4, 2: 2, 3: 0, 4: -4, 5: -2},[0, -1],True),\
164
LevelGraph([2, 0],[[2, 3], [1, 4, 5]],[(2, 4), (3, 5)],{1: 4, 2: 1, 3: 1, 4: -3, 5: -3},[0, -1],True),\
165
LevelGraph([1, 0],[[2, 3, 4], [1, 5, 6, 7]],[(2, 5), (3, 6), (4, 7)],{1: 4, 2: 0, 3: 0, 4: 0, 5: -2, 6: -2, 7: -2},[0, -1],True),\
166
LevelGraph([1, 2],[[2], [1, 3]],[(2, 3)],{1: 4, 2: 0, 3: -2},[0, -1],True),\
167
LevelGraph([2, 1],[[2], [1, 3]],[(2, 3)],{1: 4, 2: 2, 3: -4},[0, -1],True),\
168
LevelGraph([1, 1],[[2, 3], [1, 4, 5]],[(2, 4), (3, 5)],{1: 4, 2: 0, 3: 0, 4: -2, 5: -2},[0, -1],True)])
169
170
sage: len(bic_alt(Signature((1,1,1,1)))) # long time (2 seconds)
171
102
172
173
sage: len(bic_alt(Signature((2,2,0,-2))))
174
61
175
176
sage: len(bic_alt((2,2,0,-2)))
177
61
178
"""
179
if isinstance(sig, tuple):
180
sig = Signature(sig)
181
zeros = [i+1 for i,a in enumerate(sig.sig) if a > 0] # for keeping track of the numbered half-edges, we remember the index
182
z = sig.z
183
poles = [i+1 for i,a in enumerate(sig.sig) if a < 0]
184
p = sig.p
185
marked_points = [i+1 for i,a in enumerate(sig.sig) if a == 0]
186
mp = len(marked_points)
187
g = sig.g
188
orders = {i + 1: ord for i, ord in enumerate(sig.sig)}
189
190
n = sig.n
191
192
# As every g=0 top component needs at least one pole, the bottom max depends on this:
193
if p > 0:
194
g_bot_max = g
195
g_top_min = 0
196
pole_ind = [0,1]
197
else:
198
g_bot_max = g - 1
199
g_top_min = 1
200
pole_ind = [0] # poles don't need to be distributed...
201
202
found = []
203
204
for bot_comp_len in range(1,z+mp+1):
205
# every component on bottom level needs at least one zero or two marked points
206
# (in case it's genus 0 and has only one edge with a double pole going up...)
207
# Therefore, we split the zeros into top and bottom and distribute these:
208
for parts in itertools.chain(multiset_partitions(zeros,2), iter([[zeros,[]]])):
209
for i in [0,1]:
210
if mp > 0 or len(parts[i]) >= bot_comp_len:
211
bottom_zeros = parts[i]
212
top_zeros = parts[1-i]
213
else:
214
continue
215
# if there are no marked points, every component needs a zero
216
# otherwise we are more flexible (this could be improved, but is good enoug for now)
217
if mp == 0:
218
bot_zero_gen = _distribute_fully(bottom_zeros,bot_comp_len)
219
else:
220
bot_zero_gen = _distribute_points(bottom_zeros,bot_comp_len)
221
for distr_bot_zeros in bot_zero_gen:
222
# partition genus into top, bottom and graph:
223
for total_g_bot in range(g_bot_max+1):
224
for total_g_top in range(g_top_min, g - total_g_bot + 1):
225
total_g_graph = g - total_g_bot - total_g_top
226
# partition bottom genus into components
227
for distr_bot_g in _distribute_part_ordered(total_g_bot,bot_comp_len):
228
# first test:
229
# orders on each component must add up to 2g-2, from now on only poles get
230
# added and we need at least one edge going up (adding at least a pole of order 2)
231
# So if sum(zeros) < 2g, we're screwed
232
if not all(sum(orders[bz] for bz in distr_bot_zeros[c])
233
>= 2*distr_bot_g[c] for c in range(bot_comp_len)):
234
continue
235
# start distributing poles, first between top and bottom:
236
for pole_parts in itertools.chain(multiset_partitions(poles,2), iter([[poles,[]]])):
237
for ip in pole_ind: # no poles => nothing to distribute
238
bottom_poles = pole_parts[ip]
239
top_poles = pole_parts[1-ip]
240
# poles on top necessary for g=0 components
241
if total_g_top == 0 and len(top_poles) == 0:
242
continue
243
# poles are optional (i.e. not every vertex needs a pole)
244
for distr_bot_poles in _distribute_points(bottom_poles,bot_comp_len):
245
# we save the "space" left to distribute among poles from half-edges:
246
spaces_bot = [(-sum(orders[tz] for tz in distr_bot_zeros[c])
247
- sum(orders[tp] for tp in distr_bot_poles[c])
248
+ 2*distr_bot_g[c] - 2) for c in range(bot_comp_len)]
249
# retest: each space must be at least -2
250
if not all(s <= -2 for s in spaces_bot):
251
continue
252
# iterate over top components
253
for top_comp_len in range(1,total_g_top+len(top_poles)+1):
254
# now we know all vertices and the genus distribution, we know the number of edges:
255
num_of_edges = top_comp_len + bot_comp_len + total_g_graph - 1
256
# "global" condition on bottom:
257
# for each edge there will be at least another pole of order 2
258
if (sum(sum(orders[bz] for bz in distr_bot_zeros[c])
259
+ sum(orders[bp] for bp in distr_bot_poles[c])
260
for c in range(bot_comp_len))
261
- 2*num_of_edges < 2*total_g_bot - 2*bot_comp_len):
262
continue
263
# distribute genus and poles
264
for distr_top_g in _distribute_part_ordered(total_g_top,top_comp_len):
265
for distr_top_poles in _distribute_points(top_poles,top_comp_len):
266
# test: if orders add up to more than 2g-2 this won't work
267
# (effectively this should only concern g=0 components here...)
268
if not all(sum(orders[tp] for tp in distr_top_poles[c])
269
<= 2*distr_top_g[c] - 2
270
for c in range(top_comp_len)):
271
continue
272
# distribute remaining zeros optionally
273
for distr_top_zeros in _distribute_points(top_zeros,top_comp_len):
274
# again, we record the spaces:
275
spaces_top = [-sum(orders[tp] for tp in distr_top_poles[c])
276
- sum(orders[tz] for tz in distr_top_zeros[c])
277
+ 2*distr_top_g[c] - 2
278
for c in range(top_comp_len)] # yapf: disable
279
# retest:
280
if not all(s >= 0 for s in spaces_top):
281
continue
282
# We distribute the edges together with their prongs/poleorders
283
# before we check for connectednes
284
# We start on bottom level, because there each half-edge
285
# comes with a mandatory pole:
286
for half_edges_bot, orders_he in _place_legs_on_bot(spaces_bot, num_of_edges, n+num_of_edges):
287
# note for the numbering of half-edges:
288
# * the HE on bot are numbered n+num_of_edges+1,...,n+2*num_of_edges
289
# * the HE on top are numbered the same for now, i.e. edges are (l,l) ,
290
# (and will be renumbered n+1,...,n+num_of_edges in a moment)
291
for half_edges_top in _place_legs_on_top(spaces_top,orders_he):
292
# check if graph is connected!
293
# We create the associated sage graph
294
# this doesn't have multiple edges, but we only
295
# care about connectedness
296
# For this, we build a dictionary {leg: comp bottom}
297
edge_dict = {}
298
for j, c in enumerate(half_edges_bot):
299
for l in c:
300
# note that the vertices of G will be numbered
301
# 0,...,top_comp_len+bot_comp_len-1
302
# so the bot components are numbered by their index
303
# offset by top_comp_len
304
edge_dict[l] = j + top_comp_len
305
# add in the orders for top edges (note the offset)
306
orders_he[l-num_of_edges] = -2 - orders_he[l]
307
G = Graph([(j,edge_dict[l]) for j,c in enumerate(half_edges_top)
308
for l in c], multiedges=False)
309
if not G.is_connected():
310
continue
311
genera = distr_top_g+distr_bot_g
312
# Distribute order 0 marked points
313
for distr_mp in _distribute_points(marked_points,len(genera)):
314
# combine nested lists of legs:
315
legs = ([distr_top_zeros[c] + distr_top_poles[c]
316
+ distr_mp[c]
317
# renumber top HE
318
+ [l-num_of_edges for l in half_edges_top[c]]
319
for c in range(top_comp_len)] # top component
320
+ [distr_bot_zeros[c] + distr_bot_poles[c]
321
+ distr_mp[c+top_comp_len] # offset
322
+ half_edges_bot[c]
323
for c in range(bot_comp_len)] # bot component
324
) # yapf: disable
325
# check stability:
326
if any(len(ls) < 3 for c,ls in enumerate(legs)
327
if genera[c] == 0):
328
continue
329
lg_data = (genera, legs,
330
[(l,l+num_of_edges) for l in range(n+1,n+num_of_edges+1)],
331
_merge_dicts(orders,orders_he), # orders as dict
332
[0]*top_comp_len + [-1]*bot_comp_len, # levels
333
# True # quiet
334
)
335
LG = admcycles.diffstrata.levelgraph.LevelGraph(*lg_data)
336
if LG.checkadmissible(quiet=True):
337
if LG.is_legal(quiet=True):
338
found.append(LG)
339
else:
340
# this should not happen!
341
print("Not admissible(!): ", LG)
342
found = list(set(found)) # remove duplicates
343
return found
344
345
346
def bic_alt(sig):
347
"""
348
The BICs of the stratum sig up to isomorphism of LevelGraphs.
349
350
This should not be used directly, use a GeneralisedStratum or Stratum
351
instead to obtain EmbeddedLevelGraphs and the correct isomorphism classes.
352
353
Args:
354
sig (tuple): signature tuple
355
356
Returns:
357
list: list of LevelGraphs.
358
"""
359
return isom_rep(bic_alt_noiso(sig)) # remove duplicates up to iso
360
361
362
def _merge_dicts(x,y):
363
z = x.copy()
364
z.update(y)
365
return z
366
367
368
def _place_legs_on_bot(space,num_of_points,start):
369
## iterator distributing n legs with pole orders on (bottom) components according to space (each pole order is at least -2)
370
## here space is a list of 2g-2-stuff we already placed on each bottom component
371
## return a pair (pointlist,orderdict) where
372
## * pointlist is a nested list of points (numbered start+1,...,n)
373
## * orderdict is a dictionary leg number : order
374
legal_splits = []
375
distr = [] # list to hold the current distribution
376
377
def split(n):
378
## distribute n points onto space and add to distr
379
# note that space and distr are accessed from back to front...
380
if n==0:
381
# done
382
# correct signs and reverse order
383
legal_splits.append([[-a for a in c] for c in reversed(distr)])
384
return
385
else:
386
if not space: # check if empty
387
return
388
current = space.pop()
389
remaining_comp = len(space)
390
# there is a sign issue here: partitions are of positive integers, our pole orders are negative
391
# each leg has pole order at least 2, so we only list these partitions
392
# moreover, we may place at most n-remaining_comp points on this component
393
possibilities = sage_part(-current,min_part=2,max_length=n-remaining_comp).list()
394
if possibilities: # check if non-empty
395
for possibility in possibilities:
396
distr.append(possibility)
397
# recursion
398
split(n-len(possibility))
399
# undo damage
400
distr.pop()
401
space.append(current)
402
# generate splits:
403
split(num_of_points)
404
# we now convert the generated lists (of pole orders) into the format: nested list of numbered legs
405
# Note:
406
# * the legs are numbered starting from start+1 to start+num_of_points+1
407
# * the orders are saved in the list of dictionaries edge_orders_bot
408
for dist in legal_splits:
409
order_dic = {}
410
p = start + 1
411
for c in range(len(dist)):
412
for a in range(len(dist[c])):
413
order_dic[p] = dist[c][a]
414
dist[c][a] = p
415
p += 1
416
yield (dist, order_dic)
417
418
419
def _place_legs_on_top(space,orders_bot):
420
## iterator distributing n legs with zero orders (determined by their friends on the bottom component)
421
## onto the top components according to space
422
## here space is a list of 2g_comp-2-stuff we already placed on each top component
423
## return a pointlist (numbered according to keys of orders_bot for now...)
424
legal_splits = []
425
distr = [[] for _ in space] # list to hold current distribution
426
# we sort the points by order, as the ones with the highest order are the hardest to place
427
# note that this is actually reverse sorted, as the top order is -2-bottom order, but this
428
# is good, as we want to manipulate the list from the end
429
ordered_keys = [k for k,v in reversed(sorted(orders_bot.items(), key=lambda o: o[1]))]
430
431
def splits(keys):
432
# distribute the points (keys) onto spaces
433
if not keys:
434
# done if we hit all components and all spaces are 0
435
if all(distr) and all(s == 0 for s in space):
436
legal_splits.append([[a for a in c] for c in distr])
437
return
438
else:
439
# check if there are enough points left
440
remaining_comp = len([hit for hit in distr if not hit]) # components that don't have a point yet
441
if remaining_comp > len(keys):
442
return
443
current = keys.pop()
444
current_order = -2 - orders_bot[current]
445
# try to place current on all components
446
for i in range(len(space)):
447
if space[i] >= current_order:
448
space[i] -= current_order
449
distr[i].append(current)
450
splits(keys) # recursion
451
# undo changes:
452
space[i] += current_order
453
distr[i].pop()
454
keys.append(current)
455
# generate splits:
456
splits(ordered_keys)
457
return legal_splits
458
459
460
def _distribute_fully(points, n):
461
## iterator distributing list of points onto n components, where each component gets at least one point
462
## return a nested list of points
463
# generate partitions into n subsets of permuted_points:
464
for part in multiset_partitions(points, n):
465
# we need to consider all permutations (multiset_partitions sorts!)
466
for permuted_points in permutations(part):
467
yield list(permuted_points) # permutations give tuples...
468
469
470
def _b_ary_gen(x, b, n):
471
"""
472
generator for reverse b-ary integers x of length n
473
"""
474
for _ in itertools.repeat(None, n):
475
r = x % b
476
x = (x - r) // b
477
yield r
478
479
480
def _distribute_points(points,n):
481
## iterator distributing list of points onto n components (some might not receive any)
482
## return a nested list of points
483
l = len(points)
484
# n^l possibilities:
485
for i in range(n**l):
486
point_list = [[] for j in range(n)]
487
# n-ary representation of i tells us where the points should go
488
for pos,d in enumerate(_b_ary_gen(i,n,l)):
489
point_list[d].append(points[pos])
490
yield point_list
491
492
493
def _distribute_part_ordered(g,n):
494
## iterator of partitions (g_1,...,g_k) of g of length k <= n distributed onto n points
495
## return a list of length n (that sums to g)
496
if n < g:
497
maxi = n
498
else:
499
maxi = None
500
for part_dict in partitions(g,m=maxi):
501
# partitions are dictionaries {g_i : multiplicity}
502
part = []
503
for k in part_dict.keys():
504
part += [k]*part_dict[k]
505
# fill up with zeros:
506
part += (n-len(part))*[0]
507
yield part
508
# we do not have to permute if everything else is permuted....
509
# for perm_part in set(permutations(part)):
510
# yield perm_part
511
512
513
def isom_rep(L):
514
"""
515
Return a list of representatives of isomorphism classes of L.
516
517
TODO: optimise!
518
"""
519
dist_list = []
520
for g in L:
521
if all(not g.is_isomorphic(h) for h in dist_list):
522
dist_list.append(g)
523
return dist_list
524
525
526
def comp_list(L, H):
527
r"""
528
Compare two lists of LevelGraphs (up to isomorphism).
529
530
Returns a tuple: (list L without H, list H without L)
531
"""
532
return ([g for g in L if not any(g.is_isomorphic(h) for h in H)],
533
[g for g in H if not any(g.is_isomorphic(h) for h in L)])
534
535
536
def test_bic_algs(sig_list=None):
537
"""
538
Compare output of bics and bic_alt.
539
540
EXAMPLES::
541
542
sage: from admcycles.diffstrata import *
543
sage: test_bic_algs() # long time (45 seconds) # skip, not really needed + long # doctest: +SKIP
544
(1, 1): ([], [])
545
(1, 1, 0, 0, -2): ([], [])
546
(2, 0, -2): ([], [])
547
(1, 0, 0, 1): ([], [])
548
(1, -2, 2, 1): ([], [])
549
(2, 2): ([], [])
550
551
sage: test_bic_algs([(0,0),(2,1,1)]) # long time (50 seconds) # doctest: +SKIP
552
(0, 0): ([], [])
553
(2, 1, 1): ([], [])
554
555
sage: test_bic_algs([(1,0,-1),(2,),(4,),(1,-1)])
556
WARNING! This is not the normal BIC generation algorithm!
557
Only use if you know what you're doing!
558
(1, 0, -1): ([], [])
559
WARNING! This is not the normal BIC generation algorithm!
560
Only use if you know what you're doing!
561
(2,): ([], [])
562
WARNING! This is not the normal BIC generation algorithm!
563
Only use if you know what you're doing!
564
(4,): ([], [])
565
WARNING! This is not the normal BIC generation algorithm!
566
Only use if you know what you're doing!
567
(1, -1): ([], [])
568
"""
569
if sig_list is None:
570
sig_list = [(1,1),(1,1,0,0,-2),(2,0,-2),(1,0,0,1),(1,-2,2,1),(2,2)]
571
for sig in sig_list:
572
Sig = Signature(sig)
573
print("%r: %r" % (Sig.sig, comp_list(bics(Sig.g,Sig.sig),bic_alt(Sig))))
574
575