Esempio n. 1
0
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)
Esempio n. 2
0
def complete_basis(d_lst):
    '''
    Parameters
    ----------
    d_lst : list<Div>
        A list of "Div" objects.
    
    Returns
    -------
    sage_matrix<sage_QQ>
        Returns a square matrix over QQ of full rank. 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.
         
    Examples
    --------
        We explain with 3 examples where the dotted (:) vertical lines 
        denote which columns are appended. 
          
          | 0  0 : 1  0  0  0 | | 0  0  0 : 1  0  0 | | 0  0  0  1 : -3  0 |  
          | 0  0 : 0 -1  0  0 | | 0  0  0 : 0 -1  0 | | 1  0  0 -1 :  1  0 |
          | 0  0 : 0  0 -1  0 | | 1  0  0 : 0  0 -1 | |-1  1  0 -1 :  1  0 |
          | 1  0 : 0  0  0 -1 | |-1  1  0 : 0  0 -1 | | 0 -1  0 -1 :  1  0 |
          |-1  1 : 0  0  0 -1 | | 0 -1  1 : 0  0 -1 | | 0  0  1  0 :  0  1 |
          | 0 -1 : 0  0  0 -1 | | 0  0 -1 : 0  0 -1 | | 0  0 -1  0 :  0  1 |
             
    '''
    # sort
    d_lst = [d for d in d_lst]
    d_lst.sort()

    # extend with orthogonal vectors
    row_lst = [d.e_lst for d in d_lst]
    ext_lst = []
    for v_lst in sage_matrix(sage_ZZ, row_lst).right_kernel().basis():
        ext_lst += [[-v_lst[0]] + list(v_lst[1:])
                    ]  # accounts for signature (1,rank-1)
    mat = sage_matrix(sage_QQ, row_lst + ext_lst).transpose()

    # verify output
    if mat.rank() < d_lst[0].rank():
        raise Error('Matrix expected to have full rank: ', d_lst,
                    '\n' + str(mat))
    de_lst = [Div(ext) for ext in ext_lst]
    for de in de_lst:
        for d in d_lst:
            if d * de != 0:
                raise Error('Extended columns are expected to be orthogonal: ',
                            de, d, de_lst, d_lst, list(mat))

    return mat
Esempio n. 3
0
def get_ak(rank):
    '''
    Parameters
    ----------
    rank : int
    
    Returns
    -------
    Div
        A Div object of given rank of the form
        
            3e0 - e1 - ... - er
        
        Mathematically this is the anticanonical 
        class of the blowup of the projective plane.    
    '''
    return Div([3] + (rank - 1) * [-1])
Esempio n. 4
0
    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
Esempio n. 5
0
def usecase__roman_circles():
    '''
    We compute circles on a Roman surface.
    '''
    # parametrization of the Roman surface
    #
    p_lst = '[ z^2+x^2+y^2, -z*x, -x*y, z*y ]'

    # we consider the stereographic projection from
    #     S^3 = { x in P^4 | -x0^2+x1^2+x2^2+x3^2+x4^2 = 0 }
    # where the center of projection is (1:0:0:0:1):
    #     (x0:x1:x2:x3:x4) |---> (x0-x4:x1:x2:x3)

    # inverse stereographic projection into 3-sphere
    #
    s_lst = '[ y0^2+y1^2+y2^2+y3^2, 2*y0*y1, 2*y0*y2, 2*y0*y3, -y0^2+y1^2+y2^2+y3^2 ]'

    # compose p_lst with s_lst
    #
    ring = PolyRing('x,y,z,y0,y1,y2,y3')
    x, y, z, y0, y1, y2, y3 = ring.gens()
    p_lst = ring.coerce(p_lst)
    s_lst = ring.coerce(s_lst)
    dct = {y0: p_lst[0], y1: p_lst[1], y2: p_lst[2], y3: p_lst[3]}
    sp_lst = [s.subs(dct) for s in s_lst]
    NSTools.p('sp_lst =')
    for sp in sp_lst:
        NSTools.p('\t\t', sage_factor(sp))
    NSTools.p('gcd(sp_lst) =', sage_gcd(sp_lst))

    # determine base points
    #
    ring = PolyRing('x,y,z', True)
    sp_lst = ring.coerce(sp_lst)
    ls = LinearSeries(sp_lst, ring)
    NSTools.p(ls.get_bp_tree())

    # We expect that the basepoints come from the intersection
    # of the Roman surface with the absolute conic:
    #    A = { (y0:y1:y2:y3) in P^3 | y0=y1^2+y2^2+y3^2 = 0 }
    #
    # Circles are the image via p_lst of lines that pass through
    # complex conjugate points.
    #
    ring = PolyRing('x,y,z',
                    False)  # reinitialize ring with updated numberfield
    a0, a1, a2, a3 = ring.root_gens()

    # a0=(1-I*sqrt(3)) with conjugate a0-1 and minimal polynomial t^2-t+1

    # we compute candidate classes of circles
    #
    h = Div.new('4e0-e1-e2-e3-e4-e5-e6-e7-e8')
    div_lst = get_divs(h, 2, -2, False) + get_divs(h, 2, -1, False)
    NSTools.p('Classes of circles up to permutation:')
    for c in div_lst:
        NSTools.p('\t\t', c)

    # We recover the preimages of circles in the Roman surface
    # under the map p_lst, by constructing for each candidate
    # class the corresponding linear series.

    # 2e0-e1-e2-e3-e4-e5-e6-e7-e8
    b = [(a0 - 1, -a0), (-a0, a0 - 1)]
    b += [(-a0 + 1, a0), (a0, -a0 + 1)]
    b += [(a0 - 1, a0), (-a0, -a0 + 1)]
    b += [(-a0 + 1, -a0), (a0, a0 - 1)]
    bp_tree = BasePointTree()
    for i in range(6):
        bp_tree.add('z', b[i], 1)
    NSTools.p('basepoints =', b)
    NSTools.p(LinearSeries.get([2], bp_tree))

    # e0-e1-e2
    b = [(a0 - 1, -a0), (-a0, a0 - 1)]
    bp_tree = BasePointTree()
    bp = bp_tree.add('z', b[0], 1)
    bp = bp_tree.add('z', b[1], 1)
    NSTools.p('basepoints =', b)
    NSTools.p(LinearSeries.get([1], bp_tree))

    # e0-e3-e4
    b = [(-a0 + 1, a0), (a0, -a0 + 1)]
    bp_tree = BasePointTree()
    bp = bp_tree.add('z', b[0], 1)
    bp = bp_tree.add('z', b[1], 1)
    NSTools.p('basepoints =', b)
    NSTools.p(LinearSeries.get([1], bp_tree))

    # e0-e5-e6
    b = [(a0 - 1, a0), (-a0, -a0 + 1)]
    bp_tree = BasePointTree()
    bp = bp_tree.add('z', b[0], 1)
    bp = bp_tree.add('z', b[1], 1)
    NSTools.p('basepoints =', b)
    NSTools.p(LinearSeries.get([1], bp_tree))

    # e0-e7-e8
    b = [(-a0 + 1, -a0), (a0, a0 - 1)]
    bp_tree = BasePointTree()
    bp = bp_tree.add('z', b[0], 1)
    bp = bp_tree.add('z', b[1], 1)
    NSTools.p('basepoints =', b)
    NSTools.p(LinearSeries.get([1], bp_tree))

    return
Esempio n. 6
0
def get_divs(d, dc, cc, perm=False):
    '''
    Computes divisors in unimodular lattice with prescribed intersection product. 
    
    Parameters
    ---------- 
    d : Div    
        object d0*e0 + d1*e1 +...+ dr*er such that 
            * product signature equals (1,d.rank()-1)
            * d0>0
            * d1,...,dr<=0                         
    dc : int 
        A positive integer.
    
    cc : int        
        Self intersection.
        
    perm : boolean
        If True, then generators are permuted.      
    
    Returns
    -------
    list<Div> 
    
        Returns a sorted list of "Div" objects
        
            * c = c0*e0 + c1*e1 +...+ cr*er
          
        such that 
                        
            * d.rank() == r+1
            * dc       == d*c   (signature = (1,rank-1))
            * cc       == c*c   (signature = (1,rank-1))           
        
        and each Div object satisfies exactly one
        of the following conditions:    
        
            * c == ei - ej   for 0>i>j>=r,
            * c == ei        for i>0, or          
            * c0 > 0,   c1,...,cr <= 0
                           
        If "perm" is False, then then only one representative
        for each c is returned up to permutation of ei for i>0. 
        For example, e0-e1-e2 and e0-e1-e3 are considered equivalent, 
        and only e0-e1-e2 is returned, since e0-e1-e2>e0-e1-e3 
        (see "get_div_set()" for the ordering). In particular,
        c1 >= c2 >= ... >= cr.  
        
    Note
    ----
        If d=[3]+8*[-1], (dc,cc)==(0,-2) and perm=False 
        then the Div classes are 
        '12', '1123', '212' and '308'.
        See "Div.get_label()" for the notation.
        These classes correspond to the (-2)-classes 
        in the Neron-Severi lattice associated to 
        a weak del Pezzo surface.
        
        If perm==False then only one representative
        for each q is returned up to permutation of 
        ei for i>0. For example, e0-e1-e2 and e0-e1-e3
        are considered equivalent, and only e0-e1-e2
        is returned, since e0-e1-e2>e0-e1-e3 
        (see "Div.__lt__()" for the ordering).             
    '''

    # check if input was already computed
    #
    key = 'get_divs_' + str((d, dc, cc, perm))
    if key in NSTools.get_tool_dct():
        return NSTools.get_tool_dct()[key]

    # construct div set
    #
    NSTools.p('Constructing div set classes for ', (d, dc, cc, perm))
    out_lst = []

    # compute classes of the form ei or ei-ej for i,j>0
    #
    if (dc, cc) == (1, -1) or (dc, cc) == (0, -2):

        m2_lst = []  # list of divisors of the form ei-ej for i,j>0
        m1_lst = []  # list of divisors of the form ei for i>0
        if perm:

            # Example:
            #     >>> list(Combinations( [1,2,3,4], 2 ))
            #     [[1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4]]
            # Notice that r=d.rank()-1 if c = c0*e0 + c1*e1 +...+ cr*er.
            #
            for comb in sage_Combinations(range(1, d.rank()), 2):
                m2_lst += [Div.new(str(comb[0]) + str(comb[1]), d.rank())]
            m1_lst += [
                Div.new('e' + str(i), d.rank()) for i in range(1, d.rank())
            ]

        else:

            # up to permutation of the generators
            # we may assume that i==1 and j==2.
            #
            m2_lst += [Div.new('12', d.rank())]
            m1_lst += [Div.new('e1', d.rank())]

        # add the classes that satisfy return
        # specification to the output list
        #
        for c in m1_lst + m2_lst:
            if (dc, cc) == (d * c, c * c):
                out_lst += [c]

    #
    # Note: cc = c0^2 - c1^2 -...- cr^2
    #
    c0 = 0
    cur_eq_diff = -1
    while True:

        c0 = c0 + 1
        dc_tail = d[0] * c0 - dc  #    = d1*c1 +...+ dr*cr
        dd_tail = d[0]**2 - d * d  # = d1^2  +...+ dr^2
        cc_tail = c0**2 - cc  #      = c1^2  +...+ cr^2

        # not possible according to io-specs.
        #
        if dc_tail < 0 or dd_tail < 0 or cc_tail < 0:
            NSTools.p('continue... (c0, dc_tail, dd_tail, cc_tail) =',
                      (c0, dc_tail, dd_tail, cc_tail))
            if dd_tail < 0:
                raise Exception('dd_tail =', dd_tail)
            continue

        # Cauchy-Schwarz inequality <x,y>^2 <= <x,x>*<y,y> holds?
        #
        prv_eq_diff = cur_eq_diff
        cur_eq_diff = abs(dc_tail * dc_tail - dd_tail * cc_tail)
        if prv_eq_diff == -1:
            prv_eq_diff = cur_eq_diff

        NSTools.p('prv_eq_diff =', prv_eq_diff, ', cur_eq_diff =', cur_eq_diff,
                  ', dc_tail^2 =', dc_tail * dc_tail, ', dd_tail*cc_tail =',
                  dd_tail * cc_tail, ', (c0, dc_tail, dd_tail, cc_tail) =',
                  (c0, dc_tail, dd_tail, cc_tail))

        if prv_eq_diff < cur_eq_diff and dc_tail * dc_tail > dd_tail * cc_tail:
            NSTools.p('stop by Cauchy-Schwarz inequality...')
            break  # out of while loop

        # obtain all possible [d1*c1+1,...,dr*cr+1]
        #
        r = d.rank() - 1
        if perm and len(set(d[1:])) != 1:
            p_lst_lst = sage_Compositions(dc_tail + r, length=r)
        else:
            p_lst_lst = sage_Partitions(dc_tail + r, length=r)

        # data for ETA computation
        total = len(p_lst_lst)
        counter = 0
        ival = 5000

        # obtain [c1,...,cr] from [d1*c1+1,...,dr*cr+1]
        #
        for p_lst in p_lst_lst:

            # ETA
            if counter % ival == 0:
                start = time.time()
            counter += 1
            if counter % ival == 0:
                passed_time = time.time() - start
                NSTools.p('ETA in minutes =',
                          passed_time * (total - counter) / (ival * 60), ' (',
                          counter, '/', total, '), c0 =', c0,
                          ', prv_eq_diff =', prv_eq_diff, ', cur_eq_diff =',
                          cur_eq_diff)

            # dc_tail=d1*c1 +...+ dr*cr = p1 +...+ pr  with pi>=0
            p_lst = [p - 1 for p in p_lst]

            # obtain c_tail=[c1,...,cr] from [p1,...,pr]
            valid_part = True
            c_tail = []  # =[c1,...,cr]
            for i in range(0, len(p_lst)):
                if p_lst[i] == 0 or d[i + 1] == 0:
                    c_tail += [p_lst[i]]
                else:
                    quo, rem = sage_ZZ(p_lst[i]).quo_rem(d[i + 1])
                    if rem != 0:
                        valid_part = False
                        break  # out of i-for-loop
                    else:
                        c_tail += [quo]
            if not valid_part:
                continue

            # add to out list if valid
            #
            c = Div([c0] + c_tail)
            if c.rank() == d.rank() and (dc, cc) == (d * c, c * c):
                if perm and len(set(d[1:])) == 1:
                    # since d1==...==dr we do not have to
                    # check each permutation.
                    for pc_tail in sage_Permutations(c_tail):
                        out_lst += [Div([c0] + list(pc_tail))]
                else:
                    out_lst += [c]

    # sort list of "Div" objects
    out_lst.sort()

    # cache output
    NSTools.get_tool_dct()[key] = out_lst
    NSTools.save_tool_dct()

    return out_lst
Esempio n. 7
0
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
Esempio n. 8
0
    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
Esempio n. 9
0
    def get_cls(rank=9):
        '''
        Parameters
        ----------
        rank : int
            An integer in [1,...,9].           
                   
        Returns
        -------
        list<DPLattice>
            A list of DPLattice objects corresponding to Neron-Severi lattices 
            of weak Del Pezzo surfaces of degree (10-rank). The list contains
            exactly one representative for each equivalence class.
              
            All the Div objects referenced in the DPLattice objects of 
            the output have the default intersection matrix:
                diagonal matrix with diagonal: (1,-1,...,-1).
                
            If rank<3 then the empty list is returned. 
        '''
        if rank < 3:
            return []

        # check cache
        key = 'get_cls_' + str(rank)
        if key in NSTools.get_tool_dct():
            return NSTools.get_tool_dct()[key]
        NSTools.p('rank =', rank)

        # collect all lattices with either d_lst==[] of Md_lst==[]
        bas_lst = DPLattice.get_bas_lst(rank)
        inv_lst = DPLattice.get_inv_lst(rank)

        # we loop through all involutions
        NSTools.p('start looping through inv_lst: ', len(inv_lst),
                  [inv.get_marked_Mtype() for inv in inv_lst])
        dpl_lst = []
        for inv in inv_lst:

            NSTools.p('looping through inv_lst:',
                      (rank, inv.get_marked_Mtype(), inv.Md_lst))

            # recover the known classification
            if inv.Mtype == 'A0':
                NSTools.p(
                    'Since Mtype equals A0 we recover the classification from bas_lst.'
                )
                dpl_lst += [bas for bas in bas_lst]
                continue

            # partition the roots into two sets
            s_lst, q_lst = DPLattice.get_part_roots(inv)

            # import classification for rank-1
            bas1_lst = DPLattice.import_cls(DPLattice.get_cls(rank - 1), inv)
            NSTools.p(
                'looping through inv_lst continued after recursive call:',
                (rank, inv.get_marked_Mtype(), inv.Md_lst))

            # correct partition of roots (bas1_lst always contains inv)
            if len(bas1_lst) > 1:
                e = Div.new('e' + str(rank - 1), inv.get_rank())
                s_lst = [s for s in s_lst if s * e != 0]
                q_lst = [q for q in q_lst if q * e != 0]
            NSTools.p('bas1_lst =', len(bas1_lst),
                      [(bas1.Mtype, bas1.type) for bas1 in bas1_lst])
            NSTools.p('s_lst    =', len(s_lst), s_lst)
            NSTools.p('q_lst    =', len(q_lst), q_lst)

            # collect all possible root bases in s_lst and q_lst
            bas2_lst = []
            bas3_lst = []
            visited_type_lst = []
            eta = ETA(len(bas_lst), 1)
            for bas in bas_lst:

                # display progress info
                eta.update('get_cls seeking bases in s_lst and q_lst: ',
                           (rank, inv.get_marked_Mtype(), bas.get_real_type()))

                # each type in bas_lst is treated only once
                if bas.type in visited_type_lst:
                    continue
                visited_type_lst += [bas.type]

                # collect bases of type bas.type in s_lst
                if DPLattice.get_num_types(inv, bas, bas_lst) != 0:
                    bas2_lst += DPLattice.seek_bases(inv, bas.d_lst, s_lst)

                # collect bases of type bas.type in q_lst
                if 2 * len(bas.d_lst) > rank - 1:
                    continue  # the rank of a root subsystem is bounded by rank-1
                tmp_lst = DPLattice.seek_bases(inv, bas.d_lst, q_lst)
                for tmp in tmp_lst:
                    tmp.d_lst += [d.mat_mul(inv.M) for d in tmp.d_lst]
                    if is_root_basis(
                            tmp.d_lst
                    ):  # the roots and their involutions might have intersection product 1
                        tmp.d_lst.sort()
                        bas3_lst += [tmp]

            # debug info
            NSTools.p('Setting Dynkin types of', len(bas2_lst + bas3_lst),
                      'items...please wait...')
            eta = ETA(len(bas2_lst + bas3_lst), len(bas2_lst + bas3_lst) / 10)
            for bas in bas2_lst + bas3_lst:
                bas.type = get_dynkin_type(bas.d_lst)
                bas.Mtype = get_dynkin_type(bas.Md_lst)
                eta.update(bas.get_rank(), bas.get_marked_Mtype(), bas.type)
            bas1_lst.sort()
            bas2_lst.sort()
            bas3_lst.sort()
            t_lst1 = [bas.type for bas in bas1_lst]
            t_lst2 = [bas.type for bas in bas2_lst]
            t_lst3 = [bas.type for bas in bas3_lst]
            lst1 = sorted(list(set([(t, t_lst1.count(t)) for t in t_lst1])))
            lst2 = sorted(list(set([(t, t_lst2.count(t)) for t in t_lst2])))
            lst3 = sorted(list(set([(t, t_lst3.count(t)) for t in t_lst3])))
            NSTools.p('inv      =', inv.get_marked_Mtype(), ', rank =', rank)
            NSTools.p('bas1_lst =', len(bas1_lst), lst1)
            NSTools.p('bas2_lst =', len(bas2_lst), lst2)
            NSTools.p('bas3_lst =', len(bas3_lst), lst3)

            # construct a list of combinations of DPLattice objects in bas1_lst bas2_lst and
            comb_lst = []
            total = len(bas1_lst) * len(bas2_lst) * len(bas3_lst)
            step = total / 10 if total > 10 else total
            eta = ETA(total, step)
            for bas1 in bas1_lst:
                for bas2 in bas2_lst:
                    for bas3 in bas3_lst:
                        eta.update(
                            'last loop in get_cls: ( bas1.type, bas2.type, bas3.type )=',
                            (bas1.type, bas2.type, bas3.type))
                        d_lst = bas1.d_lst + bas2.d_lst + bas3.d_lst  # notice that d_lst can be equal to []
                        if len(d_lst) > rank - 1:
                            continue  # the rank of a root subsystem is bounded by rank-1
                        if is_root_basis(d_lst):
                            dpl = DPLattice(d_lst, inv.Md_lst, inv.M)
                            if dpl not in dpl_lst:
                                dpl.set_attributes()
                                dpl_lst += [dpl]
                                NSTools.p(
                                    '\t appended: ',
                                    (rank, dpl.get_marked_Mtype(),
                                     dpl.get_real_type()),
                                    ', ( bas1.type, bas2.type, bas3.type ) =',
                                    (bas1.type, bas2.type, bas3.type))

        # store in cache
        #
        dpl_lst.sort()
        NSTools.get_tool_dct()[key] = dpl_lst
        NSTools.save_tool_dct()

        return dpl_lst