def usecase__get_classes_dp1(rank): ''' Computes classes in the Neron-Severi lattice with predefined self-intersection and intersection with the canonical class. Parameters ---------- rank : int ''' # canonical class d = get_ak(rank) # basis change a_lst = ['e0-e1', 'e0-e2'] a_lst = [Div.new(a, rank) for a in a_lst] m1_lst = get_divs(d, 1, -1, True) print(d) M = sage_identity_matrix(rank) d_lst = [] d_tup_lst = get_bases_lst(a_lst, M, d_lst, m1_lst, False) B = sage_matrix(sage_ZZ, [dt.e_lst for dt in d_tup_lst[0]]) # list the classes for (dc, cc) in [(2, 0), (1, -1), (0, -2), (2, 2), (2, 4), (3, 1)]: NSTools.p('(dc, cc) =', (dc, cc)) c_lst = get_divs(d, dc, cc, False) for c in c_lst: NSTools.p('\t\t', c, '\t\t', c.get_basis_change(B))
def basis_to_involution(d_lst, rank): ''' Parameters ---------- d_lst : list<Div> A list of "Div" objects of rank "rank". rank : int An integer in [3,...,9]. Returns ------- sage_MATRIX<sage_QQ> Returns matrix over QQ that correspond to an involution of ZZ<h,e1,...,er> here r=rank-1. The first columns correspond to the elements in d_lst (where d_lst is sorted). The appended columns are orthogonal to the first "len(d_lst)" columns. ''' if d_lst == []: return sage_identity_matrix(sage_QQ, rank) l = len(d_lst) V = complete_basis(d_lst) D = sage_diagonal_matrix(l * [-1] + (rank - l) * [1]) M = V * D * V.inverse() # MV=VD return M
def get_webs(dpl): ''' Returns lists of families of conics for each possible complex basis change. The n-th family in each list correspond to a fixed family wrt. different bases for each n. Parameters ---------- dpl : DPLattice Represents the Neron-Severi lattice of a weak del Pezzo surface. Returns ------- list<list<Div>> A list of lists of Div objects. Each Div object f has the property that f*(3e0-e1-...-er)=2, f*f==0 and f*d>=0 for all d in dpl.d_lst. Such a Div object corresponds geometrically to a family of conics. For each index i, the i-th entry of each list of Div object corresponds to the same family of conics. ''' key = 'get_webs__' + str(dpl).replace('\n', '---') if key in NSTools.get_tool_dct(): return NSTools.get_tool_dct()[key] ak = get_ak(dpl.get_rank()) all_m1_lst = get_divs(ak, 1, -1, True) akc, cc = (3, 1) M = sage_identity_matrix(dpl.get_rank()) fam_lst_lst = [] for e0 in get_divs(ak, akc, cc, True): NSTools.p('e0 =', e0) for B_lst in get_bases_lst([e0], M, dpl.d_lst, all_m1_lst, True): B = sage_matrix(sage_ZZ, [d.e_lst for d in B_lst]) dplB = dpl.get_basis_change(B) fam_lst_lst += [dplB.real_fam_lst] # reduce fam_lst pat_lst_lst = [] rfam_lst_lst = [] for fam_lst in fam_lst_lst: pat_lst = [0 if fam[0] != 1 else 1 for fam in fam_lst] if pat_lst not in pat_lst_lst: pat_lst_lst += [pat_lst] rfam_lst_lst += [fam_lst] # cache output NSTools.get_tool_dct()[key] = rfam_lst_lst NSTools.save_tool_dct() return rfam_lst_lst
def __str__(self): self.set_attributes() s = '\n' s += 50 * '=' + '\n' s += 'Degree = ' + str(self.get_degree()) + '\n' s += 'Rank = ' + str(self.get_rank()) + '\n' s += 'Intersection = ' + str(list(self.m1_lst[0].int_mat)) + '\n' s += 'Real structure = ' + str(self.get_marked_Mtype()) + '\n' s += 'Singularities = ' + str(self.type) + '\n' s += 'Cardinalities = ' + '(' + str(len(self.or_lst)) + ', ' + str( len(self.sr_lst)) + ')\n' arrow = ' ---> ' s += 'Real involution:\n' b_lst = [ Div(row) for row in sage_identity_matrix(sage_ZZ, self.get_rank()).rows() ] for b in b_lst: s += '\t' + str(b) + arrow + str(b.mat_mul(self.M)) + '\n' s += 'Indecomposable (-2)-classes:\n' for d in self.d_lst: s += '\t' + str(d) + arrow + str(d.mat_mul(self.M)) + '\n' s += '\t#real = ' + str(len(self.real_d_lst)) + '\n' s += 'Indecomposable (-1)-classes:\n' for m1 in self.m1_lst: s += '\t' + str(m1) + arrow + str(m1.mat_mul(self.M)) + '\n' s += '\t#real = ' + str(len(self.real_m1_lst)) + '\n' s += 'Classes of conical families:\n' for fam in self.fam_lst: s += '\t' + str(fam) + arrow + str(fam.mat_mul(self.M)) + '\n' s += '\t#real = ' + str(len(self.real_fam_lst)) + '\n' s += 50 * '=' + '\n' return s
def usecase__construct_surfaces(): ''' We construct a surface parametrization and its Neron-Severi lattice. Requires the linear_series package. ''' # Blowup of projective plane in 3 colinear points # and 2 infinitely near points. The image of the # map associated to the linear series is a quartic # del Pezzo surface with 5 families of conics. # Moreover the surface contains 8 straight lines. # ring = PolyRing('x,y,z', True) p1 = (-1, 0) p2 = (0, 0) p3 = (1, 0) p4 = (0, 1) p5 = (2, 0) bp_tree = BasePointTree() bp_tree.add('z', p1, 1) bp_tree.add('z', p2, 1) bp_tree.add('z', p3, 1) bp = bp_tree.add('z', p4, 1) bp.add('t', p5, 1) ls = LinearSeries.get([3], bp_tree) NSTools.p(ls.get_bp_tree()) NSTools.p('implicit equation =\n\t', ls.get_implicit_image()) # construct NS-lattice where p1=e1,...,p5=e5 rank = 6 d_lst = ['e0-e1-e2-e3', 'e4-e5'] # basepoint p5 is infinitely near to p4 Md_lst = [] M = sage_identity_matrix(6) d_lst = [Div.new(d, rank) for d in d_lst] Md_lst = [Div.new(Md, rank) for Md in Md_lst] M = sage_matrix(M) dpl = DPLattice(d_lst, Md_lst, M) NSTools.p('Neron-Severi lattice =', dpl) # search representative for the equivalence class in classification assert dpl in DPLattice.get_cls(rank)
def is_integral_involution(M): ''' Parameters ---------- M : sage_matrix A matrix M. Returns ------- bool Returns True if the matrix is an involution, preserves inner product with signature (1,r) and has integral coefficients. ''' nrows, ncols = M.dimensions() # check whether involution if M * M != sage_identity_matrix(nrows): return False # check whether inner product is preserved S = sage_diagonal_matrix([1] + (ncols - 1) * [-1]) if M.transpose() * S * M != S: return False # check whether coefficients are integral for r in range(nrows): for c in range(ncols): if M[r][c] not in sage_ZZ: return False # check whether canonical class is preserved ak = get_ak(nrows) if ak.mat_mul(M) != ak: return False return True
def cls_to_tex(): ''' Create tex code for the output of DPLattice.get_cls() Returns ------- string A string representing a table of tables in Tex format. The table represent the classification of Neron-Severi lattice of weak del Pezzo surfaces. ''' # create a list of occuring divisors # div_lst = [] for rank in range(3, 9 + 1): for dpl in DPLattice.get_cls(rank): # construct list for involution (e0,...,er)|-->(i0,...,ir) i_lst = [ Div(row).mat_mul(dpl.M) for row in sage_identity_matrix(rank) ] # add each divisor that occurs to div_lst for elt in i_lst + dpl.d_lst: div_lst += [Div(elt.e_lst + (9 - len(elt.e_lst)) * [0])] div_lst = list(set(div_lst)) div_lst.sort() e0 = Div([1, 0, 0, 0, 0, 0, 0, 0, 0]) div_lst.remove(e0) div_lst = [e0] + div_lst # create dictionary characters for elements in div_lst # abc = 'abcdefghijklmnopqrstuvwxyz' ch_lst = [] ch_lst += [ '\\frac{' + ch1 + '}{' + ch2 + '}\\!' for ch1 in '0123456789' for ch2 in '0123456789' ] ch_lst += [ '\\frac{' + ch1 + '}{' + ch2 + '}\\!' for ch1 in '0123456789' for ch2 in 'abcdef' ] NSTools.p('(len(ch_lst), len(div_lst)) =', (len(ch_lst), len(div_lst))) assert len(ch_lst) >= len(div_lst) # create legend and dictionary # lgd_lst = [] sym_dct = {} for i in range(len(div_lst)): sym_dct.update({str(div_lst[i]): ch_lst[i]}) lgd_lst += [[ '$' + ch_lst[i] + '$ :', ('$' + str(div_lst[i]) + '$').replace('e', 'e_') ]] while len(lgd_lst) % 3 != 0: lgd_lst += [['', '']] nnrows = len(lgd_lst) / 3 # create tex for legend # tex_lgd = '' tex_lgd += '\\begin{table}\n' tex_lgd += '\\setstretch{1.4}\n' tex_lgd += '\\tiny\n' tex_lgd += '\\caption{Classification of Neron-Severi lattices of weak del Pezzo surfaces (see THM{nsl})}\n' tex_lgd += '\\label{tab:nsl}\n' tex_lgd += 'A dictionary for symbols in the columns $\\sigma_A$ and $B$:\n\\\\\n' tex_lgd += '\\begin{tabular}{@{}l@{}l@{~~~~}l@{}l@{~~~~}l@{}l@{}}\n' for idx in range(nnrows): c1, c2, c3, c4, c5, c6 = lgd_lst[idx] + lgd_lst[ idx + nnrows] + lgd_lst[idx + 2 * nnrows] tex_lgd += c1 + ' & ' + c2 + ' & ' + c3 + ' & ' + c4 + ' & ' + c5 + ' & ' + c6 tex_lgd += '\\\\\n' tex_lgd += '\\end{tabular}\n' tex_lgd += '\\end{table}\n\n' # number of rows of the big table # nrows = 57 # dictionary for replacing string symbols # rep_dct = { 'A': 'A_', 'D': 'D_', 'E': 'E_', '{': '\\underline{', '[': '\\udot{', ']': '}' } # create classification table # tab_lst = [] # rank 1 and 2 tab9 = [['i ', '$9$', "$A_0 $", '$A_0$', '$0$', '$1$', '']] tab8 = [['ii ', '$8$', "$A_0 $", '$A_0$', '$0$', '$2$', ''], ['iii', '$8$', "$A_0 $", '$A_0$', '$0$', '$1$', ''], ['iv ', '$8$', "$A_0 $", '$A_0$', '$1$', '$1$', ''], ['v ', '$8$', "$A_0 $", '$A_1$', '$0$', '$1$', '']] tab_lst += [tab9, tab8] # rank 3,4,5,6,7,8 and 9 idx = 0 Mtype_lst = ['A1', '4A1'] # for breaking up table for degree 2 case for rank in range(3, 9 + 1): tab = [] for dpl in DPLattice.get_cls(rank): col1 = '$' + str(idx) + '$' col2 = '$' + str(dpl.get_degree()) + '$' col3 = '$' + str(dpl.get_marked_Mtype()) + '$' for key in rep_dct: col3 = str(col3).replace(key, rep_dct[key]) col4 = '$' + str(dpl.get_real_type()) + '$' for key in rep_dct: col4 = str(col4).replace(key, rep_dct[key]) col5 = '$' + str(dpl.get_numbers()[4]) + '$' col6 = '$' + str(dpl.get_numbers()[5]) + '$' i_lst = [ str(Div(rw).mat_mul(dpl.M)) for rw in sage_identity_matrix(rank) ] col7 = '' for i in i_lst: col7 += sym_dct[i] if col7 in [ '012', '0123', '01234', '012345', '0123456', '01234567', '012345678' ]: col7 = '' col8 = '' for d in dpl.d_lst: col8 += sym_dct[str(d)] # these subroot systems cannot be realized as weak del Pezzo surfaces if col4 in [ '$7\underline{A_1}$', '$8\underline{A_1}$', '$4\underline{A_1}+\underline{D_4}$' ]: col1 = '$\\times$' # break (sometimes) the table for degree 2 according to Mtype if dpl.get_degree() == 2 and dpl.Mtype in Mtype_lst: nheaders = len( tab) / nrows # each header shifts the row number while len( tab ) % nrows != nrows - 1 - nheaders: # add rows until end of table tab += [7 * ['']] Mtype_lst.remove(dpl.Mtype) # add row tab += [[ col1, col2, col3, col4, col5, col6, '$' + col7 + '||\!' + col8 + '$' ]] idx += 1 tab_lst += [tab] # reformat table # # i d A B E G Ac%Bc hl = '@{~}l@{~~~}l@{~~~}l@{~~}l@{~~}l@{~~}l@{~~}l@{}' hrow = ['', 'd', '$D(A)$', '$D(B)$', '$\#E$', '$\#G$', '$\sigma_A||B$'] etab_lst = [] etab = [hrow] tab_idx = 0 for tab in tab_lst: for row in tab: if len(etab) >= nrows: etab_lst += [etab] etab = [hrow] etab += [row] if len(etab) < nrows and tab_idx <= 3: etab += [ 7 * [''], 7 * [''] ] # add two empty rows to separate tables with different rank else: while len(etab) < nrows: etab += [7 * ['']] # add empty rows to fill up table etab_lst += [etab] etab = [hrow] tab_idx += 1 NSTools.p('etab_lst: ', [len(etab) for etab in etab_lst]) # create tex for main classification table # tex_tab = '' tab_idx = 0 for etab in etab_lst: if tab_idx % 2 == 0: tex_tab += '\\begin{table}\n' tex_tab += '\\setstretch{1.6}\n' tex_tab += '\\centering\\tiny\n' tex_tab += '\\begin{tabular}{@{}l@{\\hspace{1cm}}l@{}}\n' elif tab_idx % 2 == 1: tex_tab += '&\n' tex_tab += '\\begin{tabular}{' + hl + '}\n' for row in etab: col1, col2, col3, col4, col5, col6, col78 = row tex_tab += col1 + ' & ' + col2 + ' & ' + col3 + ' & ' + col4 + ' & ' tex_tab += col5 + ' & ' + col6 + ' & ' + col78 tex_tab += ' \\\\\n' if row == hrow: tex_tab += '\\hline\n' tex_tab += '\\end{tabular}\n' if tab_idx % 2 == 1: tex_tab += '\\end{tabular}\n' tex_tab += '\\end{table}\n\n' tab_idx += 1 if tab_idx % 2 == 1: tex_tab += '&\n' tex_tab += '\\end{tabular}\n\n' # creating tex for commands tex_cmd = '' tex_cmd += '\\newcommand{\\udot}[1]{\\tikz[baseline=(todotted.base)]{\\node[inner sep=1pt,outer sep=0pt] (todotted) {$#1$};\\draw[densely dotted] (todotted.south west) -- (todotted.south east);}}' tex_cmd += '\n' tex_cmd += '\\newcommand{\\udash}[1]{\\tikz[baseline=(todotted.base)]{\\node[inner sep=1pt,outer sep=0pt] (todotted) {$#1$};\\draw[densely dashed] (todotted.south west) -- (todotted.south east);}}' tex_cmd += '\n\n' out = tex_cmd + tex_lgd + tex_tab return out
def get_bas_lst(rank=9): ''' See [Algorithm 5, http://arxiv.org/abs/1302.6678] for more info. Parameters ---------- rank : int An integer in [3,...,9]. Returns ------- list<DPLattice> A list of "DPLattice" objects dpl such that dpl.d_lst is the bases of a root subsystem and dpl.Mtype == A0. The list contains exactly one representative for all root subsystems up to equivalence. The list represents a classification of root subsystems of the root system with Dynkin type either: A1, A1+A2, A4, D5, E6, E7 or E8, corresponding to ranks 3, 4, 5, 6, 7, 8 and 9 respectively (eg. A1+A2 if rank equals 4, and E8 if rank equals 9). Note that the root systems live in a subspace of the vector space associated to the Neron-Severi lattice of a weak Del Pezzo surface. ''' # check whether classification of root bases is in cache key = 'get_bas_lst__' + str(rank) if key in NSTools.get_tool_dct(): return NSTools.get_tool_dct()[key] NSTools.p('start') A = [12, 23, 34, 45, 56, 67, 78] B = [1123, 1145, 1456, 1567, 1678, 278] C = [1127, 1347, 1567, 234, 278, 308] D = [1123, 1345, 1156, 1258, 1367, 1247, 1468, 1178] dpl_lst = [] for (lst1, lst2) in [(A, []), (A, B), (A, C), ([], D)]: # restrict to divisors in list, that are of rank at most "max_rank" lst1 = [ Div.new(str(e), rank) for e in lst1 if rank >= Div.get_min_rank(str(e)) ] lst2 = [ Div.new(str(e), rank) for e in lst2 if rank >= Div.get_min_rank(str(e)) ] # the involution is trivial Md_lst = [] M = sage_identity_matrix(sage_QQ, rank) # loop through the lists sub1 = sage_Subsets(range(len(lst1))) sub2 = sage_Subsets(range(len(lst2))) eta = ETA(len(sub1) * len(sub2), 20) for idx2_lst in sub2: for idx1_lst in sub1: eta.update('get_bas_lst rank =', rank) d_lst = [lst1[idx1] for idx1 in idx1_lst] d_lst += [lst2[idx2] for idx2 in idx2_lst] if not is_root_basis(d_lst): continue dpl = DPLattice(d_lst, Md_lst, M) if dpl not in dpl_lst: dpl.set_attributes() dpl_lst += [dpl] # cache output dpl_lst.sort() NSTools.get_tool_dct()[key] = dpl_lst NSTools.save_tool_dct() return dpl_lst