unlisted
ubuntu2004import itertools1from math import ceil23from sympy.utilities.iterables import partitions, permutations, multiset_partitions45# pylint does not know sage6from sage.graphs.graph import Graph # pylint: disable=import-error7# sage documentation says compositions are better than OrderedPartitions,8# no idea why....9from sage.combinat.composition import Compositions as sage_part # pylint: disable=import-error10from sage.combinat.partition import OrderedPartitions # pylint: disable=import-error11from sage.misc.cachefunc import cached_function # pylint: disable=import-error1213import admcycles.diffstrata.levelgraph14from admcycles.diffstrata.sig import Signature1516############################################################17############################################################18# Old BIC generation:19# This was the first attempt at generating BICs20# (generating all stable graphs with admcycles and then21# putting all possible bipartite structures etc on them).22# It's nice for historic reasons but painfully slow!23# Definitely use bic_alt below instead!!!24############################################################25############################################################262728def SageGraph(gr):29# converts stgraph gr in Sage graph30legdic = {i: vnum for vnum in range(31len(gr.legs(copy=False))) for i in gr.legs(vnum, copy=False)}32return Graph([(legdic[a], legdic[b])33for (a, b) in gr.edges(copy=False)], loops=True, multiedges=True)343536def bics(g, orders):37"""38Generate BICs for stratum with signature orders of genus g.3940DO NOT USE!!! USE bic_alt instead!!!4142Args:43g (int): genus44orders (tuple): signature tuple4546Returns:47list: list of BICs48"""49print('WARNING! This is not the normal BIC generation algorithm!')50print("Only use if you know what you're doing!")51n = len(orders)52bound = g + n53result = [] # list of levelgraphs54orderdict = {i + 1: orders[i] for i in range(n)}5556for e in range(1, bound + 1):57# look at which stgraphs in Mbar_g,n with e edges are bipartite58for gr in new_list_strata(g, n, e):59check = SageGraph(gr).is_bipartite(True)60if check[0]:61# check[1] contains dictionary {vertices: 0 or 1}62vert1 = [v for v in check[1] if check[1][v] == 0]63vert2 = [v for v in check[1] if check[1][v] == 1]64result += bics_on_bipgr(gr, vert1, vert2, orderdict)65result += bics_on_bipgr(gr, vert2, vert1, orderdict)66return result676869def bics_on_bipgr(gr, vertup, vertdown, orderdict):70# takes stable graph and partition of range(len(gr.genera)) into vertup, vertdown71# creates list of possible pole orders at edges72result = []7374# removed from admcycles so reinserted here for legacy purposes:75def dicunion(*dicts):76return dict(itertools.chain.from_iterable(dct.items()77for dct in dicts))7879numvert = len(gr.genera(copy=False))80halfedges = gr.halfedges()81halfedgeinvers = dict(gr.edges(copy=False))82halfedgeinvers.update({e1: e0 for (e0, e1) in gr.edges(copy=False)})8384levels = [0 for i in range(numvert)]85for i in vertdown:86levels[i] = -18788helist = [[l for l in ll if l in halfedges]89for ll in gr.legs(copy=False)] # list of half-edges of each vertex90# list (with len numvert) of orders that need to be provided by pole91# orders of half-edges (not legs)92degs = []93for v in range(numvert):94degs.append(2 * gr.genera(v) - 2 - sum([orderdict[l]95for l in gr.list_markings(v)]))96# if degs<0:97# return []9899weightparts = []100for v in vertup:101vweightpart = []102for part in OrderedPartitions(degs[v] + len(helist[v]), len(helist[v])):103# dictionary of weights from edges connected to vertex v104vdic = {helist[v][i]: part[i] - 1 for i in range(len(helist[v]))}105vdic.update(106{halfedgeinvers[helist[v][i]]: -part[i] - 1 for i in range(len(helist[v]))})107# print vdic108vweightpart.append(vdic)109weightparts += [vweightpart]110# print weightparts111112for parts in itertools.product(*weightparts):113# print parts114poleorders = dicunion(orderdict, *parts)115CandGraph = admcycles.diffstrata.levelgraph.LevelGraph(116gr.genera(117copy=False), gr.legs(118copy=False), gr.edges(119copy=False), poleorders, levels, quiet=True)120if CandGraph.is_legal(True) and CandGraph.checkadmissible(True):121result.append(CandGraph)122return result123124125def new_list_strata(g, n, r):126return [lis[0] for lis in admcycles.admcycles.degeneration_graph(int(g), n, r)[1270][r]]128129############################################################130############################################################131132############################################################133############################################################134# New BIC generation. This is currently used.135############################################################136############################################################137138139@cached_function140def bic_alt_noiso(sig):141"""142Construct all non-horizontal divisors in the stratum sig.143144More precisely, each BIC is LevelGraph with two levels numbered 0, -1145and marked points 1,...,n where the i-th point corresponds to the element146i-1 of the signature.147148Note that this is the method called by GeneralisedStratum.gen_bic.149150Args:151sig (Signature): Signature of the stratum.152153Returns:154list: list of 2-level non-horizontal LevelGraphs.155156EXAMPLES::157158sage: from admcycles.diffstrata import *159sage: assert comp_list(bic_alt(Signature((1,1))),\160[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),\161LevelGraph([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),\162LevelGraph([1, 1],[[3], [1, 2, 4]],[(3, 4)],{1: 1, 2: 1, 3: 0, 4: -2},[0, -1],True),\163LevelGraph([2, 0],[[3], [1, 2, 4]],[(3, 4)],{1: 1, 2: 1, 3: 2, 4: -4},[0, -1],True)])164165sage: assert comp_list(bic_alt(Signature((2,))),\166[LevelGraph([1, 1],[[2], [1, 3]],[(2, 3)],{1: 2, 2: 0, 3: -2},[0, -1],True),\167LevelGraph([1, 0],[[2, 3], [1, 4, 5]],[(2, 4), (3, 5)],{1: 2, 2: 0, 3: 0, 4: -2, 5: -2},[0, -1],True)])168169sage: assert comp_list(bic_alt(Signature((4,))),\170[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),\171LevelGraph([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),\172LevelGraph([2, 0],[[2, 3], [1, 4, 5]],[(2, 4), (3, 5)],{1: 4, 2: 2, 3: 0, 4: -4, 5: -2},[0, -1],True),\173LevelGraph([2, 0],[[2, 3], [1, 4, 5]],[(2, 4), (3, 5)],{1: 4, 2: 1, 3: 1, 4: -3, 5: -3},[0, -1],True),\174LevelGraph([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),\175LevelGraph([1, 2],[[2], [1, 3]],[(2, 3)],{1: 4, 2: 0, 3: -2},[0, -1],True),\176LevelGraph([2, 1],[[2], [1, 3]],[(2, 3)],{1: 4, 2: 2, 3: -4},[0, -1],True),\177LevelGraph([1, 1],[[2, 3], [1, 4, 5]],[(2, 4), (3, 5)],{1: 4, 2: 0, 3: 0, 4: -2, 5: -2},[0, -1],True)])178179sage: len(bic_alt(Signature((1,1,1,1)))) # long time (2 seconds)180102181182sage: len(bic_alt(Signature((2,2,0,-2))))18361184185sage: len(bic_alt((2,2,0,-2)))18661187"""188if isinstance(sig, tuple):189sig = Signature(sig)190# for keeping track of the numbered half-edges, we remember the index191zeros = [i + 1 for i, a in enumerate(sig.sig) if a > 0]192z = sig.z193poles = [i + 1 for i, a in enumerate(sig.sig) if a < 0]194p = sig.p195marked_points = [i + 1 for i, a in enumerate(sig.sig) if a == 0]196mp = len(marked_points)197g = sig.g198orders = {i + 1: ord for i, ord in enumerate(sig.sig)}199200n = sig.n201202if sig.k == 1:203# As every g=0 top component needs at least one pole, the bottom max204# depends on this:205if p > 0:206g_bot_max = g207g_top_min = 0208pole_ind = [0, 1]209else:210g_bot_max = g - 1211g_top_min = 1212pole_ind = [0] # poles don't need to be distributed...213elif sig.k == 2:214# For quadratic differentials, g=0 top components without poles are215# possible.216g_bot_max = g217g_top_min = 0218pole_ind = [0, 1] if p > 0 else [0]219else:220raise ValueError("Not implemented for k>2")221222only_even = sig.k == 2 and sig.difftype == "gs"223224found = []225226for bot_comp_len in range(1, z + mp + 1):227# every component on bottom level needs at least one zero or two marked points228# (in case it's genus 0 and has only one edge with a pole of order -2k going up...)229# Therefore, we split the zeros into top and bottom and distribute230# these:231for parts in itertools.chain(232multiset_partitions(zeros, 2), iter([[zeros, []]])):233for i in [0, 1]:234if mp > 0 or len(parts[i]) >= bot_comp_len:235bottom_zeros = parts[i]236top_zeros = parts[1 - i]237else:238continue239# if there are no marked points, every component needs a zero240# otherwise we are more flexible (this could be improved, but241# is good enoug for now)242if mp == 0:243bot_zero_gen = _distribute_fully(244bottom_zeros, bot_comp_len)245else:246bot_zero_gen = _distribute_points(247bottom_zeros, bot_comp_len)248for distr_bot_zeros in bot_zero_gen:249# partition genus into top, bottom and graph:250for total_g_bot in range(g_bot_max + 1):251for total_g_top in range(252g_top_min, g - total_g_bot + 1):253total_g_graph = g - total_g_bot - total_g_top254# partition bottom genus into components255for distr_bot_g in _distribute_part_ordered(256total_g_bot, bot_comp_len):257# first test:258# orders on each component must add up to k(2g-2), from now on only poles get259# added and we need at least one edge going up (adding at least a pole of order -(k+1))260# So if sum(zeros) < k(2g-2)+(k+1), we're261# screwed262if not all(sum(orders[bz] for bz in distr_bot_zeros[c]) >= sig.k * (263distr_bot_g[c] - 2) + sig.k + 1 for c in range(bot_comp_len)):264continue265# start distributing poles, first between top266# and bottom:267for pole_parts in itertools.chain(268multiset_partitions(poles, 2), iter([[poles, []]])):269for ip in pole_ind: # no poles => nothing to distribute270bottom_poles = pole_parts[ip]271top_poles = pole_parts[1 - ip]272# if k == 1, poles on top necessary for g=0 components273if sig.k == 1 and total_g_top == 0 and len(274top_poles) == 0:275continue276# poles are optional (i.e. not every vertex needs a pole)277for distr_bot_poles in _distribute_points(278bottom_poles, bot_comp_len):279# we save the "space" left to distribute among poles from280# half-edges:281spaces_bot = [(-sum(orders[tz] for tz in distr_bot_zeros[c])282- sum(orders[tp] for tp in distr_bot_poles[c])283+ sig.k * (2 * distr_bot_g[c] - 2)) for c in range(bot_comp_len)]284# retest: each space must be at least -(k+1)285if not all(s <= -(sig.k + 1)286for s in spaces_bot):287continue288# get the total orders of poles on the top components.289# Note that for k>1 there are poles coming from the edges.290if sig.k == 1:291# the total order of all poles on the top components292max_total_pole_order_top = sum(293orders[p] for p in top_poles)294# the maximal number of poles on the top components295max_poles_top = len(top_poles)296elif sig.k == 2:297# we get poles of order -1 from edges at the top iff we can298# add edges with poles of order -3 at the bottom end299max_poles_from_edges = sum(300[(-s / 3) if s % 3 == 0 else (int(-s / 3) - 1) for s in spaces_bot])301max_total_pole_order_top = sum(302orders[p] for p in top_poles) - max_poles_from_edges303max_poles_top = len(304top_poles) + max_poles_from_edges305else:306raise ValueError(307"Not implemented for k>2")308# each g=0 component on top level needs at least poles of total order -2*k309max_g0_top = min(310int(-max_total_pole_order_top / (2 * sig.k)), max_poles_top)311# iterate over top components312for top_comp_len in range(3131, total_g_top + max_g0_top + 1):314# now we know all vertices and the genus distribution, we know the number of edges:315num_of_edges = top_comp_len + bot_comp_len + total_g_graph - 1316# "global" condition on bottom: for each edge there will be317# at least another pole of order k+1318if (sum(sum(orders[bz] for bz in distr_bot_zeros[c])319+ sum(orders[bp] for bp in distr_bot_poles[c])320for c in range(bot_comp_len))321- (sig.k + 1) * num_of_edges < sig.k * (2 * total_g_bot - 2 * bot_comp_len)):322continue323# distribute genus and poles324for distr_top_g in _distribute_part_ordered(325total_g_top, top_comp_len):326for distr_top_poles in _distribute_points(327top_poles, top_comp_len):328# test: if orders add up to more than k(2g-2) this won't work329# (effectively this should only concern g=0 components here...)330if not all(sum(orders[tp] for tp in distr_top_poles[c])331# Edges may give additional poles if k > 1332+ (1 - sig.k) * \333num_of_edges334<= sig.k * (2 * distr_top_g[c] - 2)335for c in range(top_comp_len)):336continue337# distribute remaining zeros optionally338for distr_top_zeros in _distribute_points(339top_zeros, top_comp_len):340# again, we record the spaces:341spaces_top = [-sum(orders[tp] for tp in distr_top_poles[c])342- sum(orders[tz] for tz in distr_top_zeros[c])343+ sig.k *344(2 *345distr_top_g[c] - 2)346for c in range(top_comp_len)] # yapf: disable347# retest:348if not all(349s >= (1 - sig.k) * num_of_edges for s in spaces_top):350continue351# We distribute the edges together with their prongs/poleorders352# before we check for connectednes353# We start on bottom level, because there each half-edge354# comes with a mandatory pole:355for half_edges_bot, orders_he in _place_legs_on_bot(356spaces_bot, num_of_edges, n + num_of_edges, sig.k, only_even):357# note for the numbering of half-edges:358# * the HE on bot are numbered n+num_of_edges+1,...,n+2*num_of_edges359# * the HE on top are numbered the same for now, i.e. edges are (l,l) ,360# (and will be renumbered n+1,...,n+num_of_edges in a moment)361for half_edges_top in _place_legs_on_top(362spaces_top, orders_he, sig.k):363# check if graph is connected364if not is_connected(365half_edges_bot, half_edges_top):366continue367# add in the orders for top edges (note the offset)368for c in half_edges_bot:369for l in c:370orders_he[l - num_of_edges] = - \3712 * sig.k - orders_he[l]372genera = distr_top_g + distr_bot_g373# Distribute order 0 marked points374for distr_mp in _distribute_points(375marked_points, len(genera)):376# combine nested lists of legs:377legs = ([distr_top_zeros[c] + distr_top_poles[c]378+ distr_mp[c]379# renumber top HE380+ [l - num_of_edges for l in half_edges_top[c]]381for c in range(top_comp_len)] # top component382+ [distr_bot_zeros[c] + distr_bot_poles[c]383# offset384+ distr_mp[c + top_comp_len]385+ half_edges_bot[c]386for c in range(bot_comp_len)] # bot component387) # yapf: disable388# check stability:389if any(390len(ls) < 3 for c, ls in enumerate(legs) if genera[c] == 0):391continue392lg_data = (genera, legs,393[(l, l + num_of_edges) for l in range(394n + 1, n + num_of_edges + 1)],395# orders as dict396_merge_dicts(397orders, orders_he),398# levels399[0] * top_comp_len + \400[-1] * \401bot_comp_len,402# True403# #404# quiet405)406if sig.k == 1:407LG = admcycles.diffstrata.levelgraph.LevelGraph(408*lg_data)409elif sig.k == 2:410LG = admcycles.diffstrata.quadraticlevelgraph.QuadraticLevelGraph(411*lg_data)412else:413raise ValueError(414"Not implemented for k>2")415if LG.checkadmissible(416quiet=True):417if sig.k == 1:418if LG.is_legal(419quiet=True):420found.append(421LG)422elif sig.k == 2:423if (sig.difftype == "gs" and LG.is_legal_global_square(quiet=True)) \424or (sig.difftype == "p" and LG.is_legal_primitive(quiet=True)):425found.append(426LG)427else:428raise ValueError(429"Not implemented for k>2")430else:431# this should not happen!432print(433"Not admissible(!): ", LG)434found_new = []435found_set = set()436for x in found:437if x not in found_set:438found_new.append(x)439found_set.add(x)440# found = list(set(found)) # remove duplicates441return found_new442443444def bic_alt(sig):445"""446The BICs of the stratum sig up to isomorphism of LevelGraphs.447448This should not be used directly, use a GeneralisedStratum or Stratum449instead to obtain EmbeddedLevelGraphs and the correct isomorphism classes.450451Args:452sig (tuple): signature tuple453454Returns:455list: list of LevelGraphs.456"""457return isom_rep(bic_alt_noiso(sig)) # remove duplicates up to iso458459460def _merge_dicts(x, y):461z = x.copy()462z.update(y)463return z464465466def _place_legs_on_bot(space, num_of_points, start, k, only_even):467# iterator distributing n legs with pole orders on (bottom) components according to space (each pole order is at least -(k+1))468# here space is a list of k(2g-2)-stuff we already placed on each bottom component469# return a pair (pointlist,orderdict) where470# * pointlist is a nested list of points (numbered start+1,...,n)471# * orderdict is a dictionary leg number : order472legal_splits = []473distr = [] # list to hold the current distribution474475def split(n):476# distribute n points onto space and add to distr477# note that space and distr are accessed from back to front...478if n == 0:479# done480# correct signs and reverse order481legal_splits.append([[-a for a in c] for c in reversed(distr)])482return483else:484if not space: # check if empty485return486current = space.pop()487remaining_comp = len(space)488# there is a sign issue here: partitions are of positive integers, our pole orders are negative489# each leg has pole order at least k+1, so we only list these partitions490# moreover, we may place at most n-remaining_comp points on this491# component492if only_even:493possibilities = [[c * 2 for c in pos]494for pos in sage_part(-current / 2, min_part=ceil((k + 1) / 2.), max_length=n - remaining_comp)]495else:496possibilities = sage_part(-current, min_part=k + 1,497max_length=n - remaining_comp).list()498if possibilities: # check if non-empty499for possibility in possibilities:500distr.append(possibility)501# recursion502split(n - len(possibility))503# undo damage504distr.pop()505space.append(current)506# generate splits:507split(num_of_points)508# we now convert the generated lists (of pole orders) into the format: nested list of numbered legs509# Note:510# * the legs are numbered starting from start+1 to start+num_of_points+1511# * the orders are saved in the list of dictionaries edge_orders_bot512for dist in legal_splits:513order_dic = {}514p = start + 1515for c in range(len(dist)):516for a in range(len(dist[c])):517order_dic[p] = dist[c][a]518dist[c][a] = p519p += 1520yield (dist, order_dic)521522523def _place_legs_on_top(space, orders_bot, k):524# iterator distributing n legs with zero orders (determined by their friends on the bottom component)525# onto the top components according to space526# here space is a list of k(2g_comp-2)-stuff we already placed on each top component527# return a pointlist (numbered according to keys of orders_bot for now...)528legal_splits = []529distr = [[] for _ in space] # list to hold current distribution530# we sort the points by order, as the ones with the highest order are the hardest to place531# note that this is actually reverse sorted, as the top order is -2k-bottom order, but this532# is good, as we want to manipulate the list from the end533ordered_keys = [l for l, _ in reversed(534sorted(orders_bot.items(), key=lambda o: o[1]))]535536def splits(keys):537# distribute the points (keys) onto spaces538if not keys:539# done if we hit all components and all spaces are 0540if all(distr) and all(s == 0 for s in space):541legal_splits.append([list(c) for c in distr])542return543else:544# check if there are enough points left545# components that don't have a point yet546remaining_comp = len([hit for hit in distr if not hit])547remaining_pole_order = 0 if k == 1 else sum(548o for o in [-2 * k - orders_bot[l] for l in keys] if o < 0)549if remaining_comp > len(keys):550return551current = keys.pop()552current_order = -2 * k - orders_bot[current]553# try to place current on all components554for i in range(len(space)):555if space[i] >= current_order + remaining_pole_order:556space[i] -= current_order557distr[i].append(current)558splits(keys) # recursion559# undo changes:560space[i] += current_order561distr[i].pop()562keys.append(current)563# generate splits:564splits(ordered_keys)565return legal_splits566567568def _distribute_fully(points, n):569# iterator distributing list of points onto n components, where each component gets at least one point570# return a nested list of points571# generate partitions into n subsets of permuted_points:572for part in multiset_partitions(points, n):573# we need to consider all permutations (multiset_partitions sorts!)574for permuted_points in permutations(part):575yield list(permuted_points) # permutations give tuples...576577578def _b_ary_gen(x, b, n):579# generator for reverse b-ary integers x of length n580for _ in itertools.repeat(None, n):581r = x % b582x = (x - r) // b583yield r584585586def _distribute_points(points, n):587# iterator distributing list of points onto n components (some might not receive any)588# return a nested list of points589l = len(points)590# n^l possibilities:591for i in range(n**l):592point_list = [[] for j in range(n)]593# n-ary representation of i tells us where the points should go594for pos, d in enumerate(_b_ary_gen(i, n, l)):595point_list[d].append(points[pos])596yield point_list597598599def _distribute_part_ordered(g, n):600# iterator of partitions (g_1,...,g_k) of g of length k <= n distributed onto n points601# return a list of length n (that sums to g)602if n < g:603maxi = n604else:605maxi = None606for part_dict in partitions(g, m=maxi):607# partitions are dictionaries {g_i : multiplicity}608part = []609for k in part_dict.keys():610part += [k] * part_dict[k]611# fill up with zeros:612part += (n - len(part)) * [0]613yield part614# we do not have to permute if everything else is permuted....615# for perm_part in set(permutations(part)):616# yield perm_part617618619def isom_rep(L):620"""621Return a list of representatives of isomorphism classes of L.622623TODO: optimise!624"""625dist_list = []626for g in L:627if all(not g.is_isomorphic(h) for h in dist_list):628dist_list.append(g)629return dist_list630631632def comp_list(L, H):633r"""634Compare two lists of LevelGraphs (up to isomorphism).635636Returns a tuple: (list L without H, list H without L)637"""638return ([g for g in L if not any(g.is_isomorphic(h) for h in H)],639[g for g in H if not any(g.is_isomorphic(h) for h in L)])640641642def is_connected(half_edges_top, half_edges_bottom):643"""644Check if graph given by the two sets of half edges is connected.645We do this by depth-first search.646Note that we assume that both ends of each edge have the same number,647i.e. each edge is of the form (j,j).648649EXAMPLES::650651sage: from admcycles.diffstrata.bic import is_connected652sage: is_connected([[1],[2]],[[1,2]])653True654sage: is_connected([[1],[2]],[[2],[1]])655False656"""657def _connected_comp(current_edges, other_edges,658seen_current, seen_other, current_vert=0):659seen_current.append(current_vert)660for e in current_edges[current_vert]:661for (i, edges) in enumerate(other_edges):662if e in edges:663if i not in seen_other:664_connected_comp(other_edges, current_edges,665seen_other, seen_current, i)666break667return (seen_current, seen_other)668seen_top = []669seen_bottom = []670_connected_comp(half_edges_top, half_edges_bottom, seen_top, seen_bottom)671return len(seen_top) == len(half_edges_top) and len(672seen_bottom) == len(half_edges_bottom)673674675def test_bic_algs(sig_list=None):676"""677Compare output of bics and bic_alt.678679EXAMPLES::680681sage: from admcycles.diffstrata import *682sage: test_bic_algs() # long time (45 seconds) # skip, not really needed + long # doctest: +SKIP683(1, 1): ([], [])684(1, 1, 0, 0, -2): ([], [])685(2, 0, -2): ([], [])686(1, 0, 0, 1): ([], [])687(1, -2, 2, 1): ([], [])688(2, 2): ([], [])689690sage: test_bic_algs([(0,0),(2,1,1)]) # long time (50 seconds) # doctest: +SKIP691(0, 0): ([], [])692(2, 1, 1): ([], [])693694sage: test_bic_algs([(1,0,-1),(2,),(4,),(1,-1)])695WARNING! This is not the normal BIC generation algorithm!696Only use if you know what you're doing!697(1, 0, -1): ([], [])698WARNING! This is not the normal BIC generation algorithm!699Only use if you know what you're doing!700(2,): ([], [])701WARNING! This is not the normal BIC generation algorithm!702Only use if you know what you're doing!703(4,): ([], [])704WARNING! This is not the normal BIC generation algorithm!705Only use if you know what you're doing!706(1, -1): ([], [])707"""708if sig_list is None:709sig_list = [(1, 1), (1, 1, 0, 0, -2), (2, 0, -2),710(1, 0, 0, 1), (1, -2, 2, 1), (2, 2)]711for sig in sig_list:712Sig = Signature(sig)713print(714"%r: %r" %715(Sig.sig,716comp_list(717bics(718Sig.g,719Sig.sig),720bic_alt(Sig))))721722723