コード例 #1
0
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))
コード例 #2
0
    def import_cls(cls_lst, inv):
        '''
        This method is used by get_cls().
        
        Parameters
        ----------
        cls_lst : list<DPLattice>
            A list of DPLattice objects of rank "inv.get_rank()-1". 
            These lattices correspond to Neron-Severi lattices 
            of weak Del Pezzo surfaces.
            
        inv : DPLattice
            A DPLattice object representing an involution.
            We expect inv.Md_lst to be set.
        
        Returns
        -------
        list<DPLattice>
            A list of compatible DPLattice objects in cls_lst that are 
            converted so as to have the same rank and involution matrix as 
            inv.get_rank() and inv.M, respectively. 
            The returned list always contains inv itself.
        '''
        out_lst = []
        for cls in cls_lst:

            # convert divisors to new rank
            Md_lst = [Div.new(str(d), inv.get_rank()) for d in cls.Md_lst]
            d_lst = [Div.new(str(d), inv.get_rank()) for d in cls.d_lst]

            # import if the involution is compatible
            if set(Md_lst) == set(inv.Md_lst):
                NSTools.p('importing: ',
                          (inv.get_rank(), cls.get_marked_Mtype(),
                           cls.get_real_type()), Md_lst, '==', inv.Md_lst)
                out = DPLattice(d_lst, inv.Md_lst, inv.M)
                out.set_attributes()
                out_lst += [out]

        # always ensure that at least inv object is contained
        if out_lst == []:
            return [inv]

        # we expect that inv is contained in the out_lst
        # for correctness of the get_cls() algorithm.
        assert inv in out_lst

        return out_lst
コード例 #3
0
ファイル: ns_basis.py プロジェクト: niels-lubbes/ns_lattice
def triples(dpl, mval):
    '''
    Parameters
    ----------
    dpl  : DPLattice
    mval : integer
    
    Returns
    -------
    list<(Div,Div,Div)>
        List of triples in "dpl.fam_lst":
            [ (a,b,c),... ]
        so that 
            (1) There does not exists e in "dpl.m1_lst"
                with the property that a*e==b*e==c*e==0.
            (2) 1 <= max( a*b, a*c, b*c ) <= mval.
    '''
    key = 'triples__' + str(dpl).replace('\n', '---') + '---' + str(mval)
    if key in NSTools.get_tool_dct():
        return NSTools.get_tool_dct()[key]

    f_lst = dpl.fam_lst
    e_lst = dpl.m1_lst

    # obtain list of triples (a,b,c) in f_lst
    # that are not orthogonal to any element in e_lst
    t_lst = []
    idx_lst_lst = sage_Subsets(range(len(f_lst)), 3)
    eta = ETA(len(idx_lst_lst), 500000)
    for idx_lst in idx_lst_lst:
        eta.update('t_lst')

        t = [f_lst[idx] for idx in idx_lst]
        if t[0] * t[1] > mval: continue
        if t[0] * t[2] > mval: continue
        if t[1] * t[2] > mval: continue

        # elements in f_lst correspond to divisor classes of curves on a
        # surface and thus t[i]*t[j]>=1 for all i,j \in {0,1,2} so that i!=j.

        cont = False
        for e in e_lst:
            if [f * e for f in t] == [0, 0, 0]:
                cont = True
                break
        if cont: continue

        if not contains_perm(t_lst, t):
            t_lst += [t]

    NSTools.p('t_lst =', t_lst)

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

    return t_lst
コード例 #4
0
def usecase__get_cls(max_rank):
    '''
    Classification of root bases in root system of rank at most "max_rank".
    See "DPLattice.get_cls_root_bases()".
    
    Parameters
    ----------
    max_rank : int
        Maximal rank.  
    '''

    row_format = '{:>6}{:>5}{:>8}{:>16}{:>5}{:>5}{:>5}{:>5}{:>6}{:>7}{:>70}{:>135}{:>340}'
    rownr = 0
    for rank in range(3, max_rank + 1):

        dpl_lst = DPLattice.get_cls(rank)
        row_lst = [[
            'rownr', 'rank', 'Mtype', 'type', '#-2', '#-1', '#fam', '#-2R',
            '#-1R', '#famR', 'Md_lst', 'd_lst', 'M'
        ]]
        for dpl in sorted(dpl_lst):
            row_lst += [
                [rownr, rank,
                 dpl.get_marked_Mtype(),
                 dpl.get_real_type()] + list(dpl.get_numbers()) +
                [str(dpl.Md_lst)] + [str(dpl.d_lst)] + [str(list(dpl.M))]
            ]
            rownr += 1
        s = ''
        for row in row_lst:
            s += row_format.format(*row) + '\n'

        NSTools.p('Classification of root bases:\n' + s)
        NSTools.p('rank =', rank, ', len =', len(dpl_lst))
        NSTools.p(80 * '#')

    for rank in range(3, max_rank + 1):
        NSTools.p('rank =', rank, ', len =', len(DPLattice.get_cls(rank)))
    NSTools.p(80 * '#')
コード例 #5
0
ファイル: ns_basis.py プロジェクト: niels-lubbes/ns_lattice
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
コード例 #6
0
def get_ext_graph(d_lst, M):
    '''
    Parameters
    ----------
    d_lst : list<Div> 
        A list of "Div" objects of equal rank.
        
    M : sage_matrix<sage_ZZ>   
        A square matrix with integral coefficients
        of rank "d_lst[0].rank()" 
    
    Returns
    -------
        A labeled "sage_Graph()" where the elements 
        of "d_lst" are the vertices. 
        A pair of non-orthogonal vertices are connected 
        by and edge labeled with their 
        non-zero intersection product. 
        Two vertices which are related 
        via M are connected with an edge labeled 1000.
        Labeled self-loops are also included.        
    '''
    NSTools.p('d_lst =', len(d_lst), d_lst, ', M =', list(M))

    G = sage_Graph()
    G.add_vertices(range(len(d_lst)))

    for i in range(len(d_lst)):
        for j in range(len(d_lst)):
            if d_lst[i] * d_lst[j] != 0:
                G.add_edge(i, j, d_lst[i] * d_lst[j])

    for i in range(len(d_lst)):
        j = d_lst.index(d_lst[i].mat_mul(M))
        G.add_edge(i, j, 1000)

    return G
コード例 #7
0
    def update(self, *info_lst):
        '''
        Should be called inside a loop.
        
        Prints an estimation for the time it takes for a program to 
        terminate (ETA for short). We refer to the program termination 
        as arrival.
        
        Parameters
        ----------
        *info_lst : string
            Variable length argument list consisting of 
            additional information that is printed together with ETA.
        '''

        if self.counter % self.ival == 0:
            cur_time = self.time()

            ival_time = (cur_time - self.prv_time) / (60 * self.ival)
            passed_time = sage_n((cur_time - self.ini_time) / 60, digits=5)
            self.eta_time = sage_n(ival_time * (self.total - self.counter),
                                   digits=5)

            s = ''
            for info in info_lst:
                s += str(info) + ' '

            NSTools.p('ETA =', self.eta_time, 'm,', 'counter =', self.counter,
                      '/', self.total, ',', 'time =', passed_time, 'm,',
                      'info =', s)

            # update previous time
            self.prv_time = cur_time

        # increase counter
        self.counter += 1
コード例 #8
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)
コード例 #9
0
    def get_cls_slow(rank=7):
        '''        
        Use get_cls_real_dp() for a faster method. This method does not terminate
        within reasonable time if rank>7. We still keep the method in order to 
        compare the outcomes in case rank<=9.
        
        Parameters
        ----------
        max_rank : int
            An integer in [3,...,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). 
        '''
        # check cache
        key = 'get_cls_slow__' + str(rank)
        if key in NSTools.get_tool_dct():
            return NSTools.get_tool_dct()[key]

        inv_lst = DPLattice.get_inv_lst(rank)
        bas_lst = DPLattice.get_bas_lst(rank)

        # we fix an involution up to equivalence and go through
        # all possible root bases for singularities.
        dpl_lst = []
        eta = ETA(len(bas_lst) * len(inv_lst), 20)
        for inv in inv_lst:
            for bas in bas_lst:

                orbit_lst = get_root_bases_orbit(bas.d_lst)
                eta.update('len( orbit_lst ) =', len(orbit_lst))

                for d_lst in orbit_lst:

                    # check whether involution inv.M preserves d_lst
                    dm_lst = [d.mat_mul(inv.M) for d in d_lst]
                    dm_lst.sort()
                    if dm_lst != d_lst:
                        continue

                    # add to classification if not equivalent to objects
                    # in list, see "DPLattice.__eq__()".
                    dpl = DPLattice(d_lst, inv.Md_lst, inv.M)
                    if dpl not in dpl_lst:
                        dpl.set_attributes()
                        dpl_lst += [dpl]

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

        return dpl_lst
コード例 #10
0
def usecase__analyze_graphs(max_rank):
    '''
    We analyze the graphs of DPLattice objects in the output  
    of DPLattice.get_cls().
    
    Parameters
    ----------
    max_rank : int
        Maximal rank of DPLattice objects that are considered. 
    '''

    # Examine which of the graphs associated to DPLattices
    # are isomorphic to one of the constructed graphs.
    #
    NSTools.p('\t Compare contructed graphs with classified graphs...')
    rownr = -1
    max_verts = 0
    for rank in range(3, max_rank + 1):
        NSTools.p('\t ---')
        for dpl in DPLattice.get_cls(rank):
            rownr += 1

            # retrieve the graph SG for analysis
            SG, SG_data = dpl.get_SG()

            if SG.num_verts() <= 3:
                continue

            # check if each edge label is in [2,4]
            if [e for e in SG_data[3] if e not in [2, 4]] != []:
                continue

            # initialize string
            s = ''
            s += str(rownr) + ' ' + 'rank=' + str(rank) + ' '

            # Initialize G_lst which is a list of tuples (G,G_str)
            # where G is a constructed graph and G_str is its string identifier.
            # The identifiers are according Theorem 1 in arXiv:1807.05881v2.
            #
            G_lst = []
            for nv1 in range(1, SG.num_verts() + 1):
                for nv2 in range(1, SG.num_verts() + 1):

                    # determine list c_lst of 2-element subsets of [1,...,m]
                    # so that m is minimal under the condition that len(c_lst)>=nv1
                    c_lst = []
                    for i in range(2 * nv1):
                        c_lst = list(sage_Combinations(i, 2))
                        if len(c_lst) >= nv1:
                            break

                    # construct graphs
                    #
                    Gd = sage_Graph()
                    Gd.add_vertices(range(nv1))
                    G_lst += [(Gd, 'Gd:' + str(nv1))]

                    Ge = sage_Graph()
                    Ge.add_vertices(range(nv1))
                    for i in Ge.vertices():
                        for j in Ge.vertices():
                            Ge.add_edge(i, j, 2)
                    G_lst += [(Ge, 'Ge:' + str(nv1))]

                    Gf = sage_Graph()
                    Gf.add_vertices(range(len(c_lst)))
                    for i in Gf.vertices():
                        for j in Gf.vertices():
                            q = len([c for c in c_lst[i] if c in c_lst[j]])
                            Gf.add_edge(i, j, 4 - 2 * q)
                    G_lst += [(Gf, 'Gf:' + str(Gf.num_verts()))]

                    Gg = sage_Graph()
                    Gg.add_vertices(range(len(c_lst)))
                    for i in Gg.vertices():
                        for j in Gg.vertices():
                            q = len([c for c in c_lst[i] if c in c_lst[j]])
                            if q > 0:
                                Gg.add_edge(i, j, 2)
                    G_lst += [(Gg, 'Gg:' + str(Gg.num_verts()))]

                    # construct combined graphs
                    #
                    if nv1 + nv2 > SG.num_verts():
                        continue

                    Gd2 = sage_Graph()
                    Gd2.add_vertices(range(nv2))

                    Ge2 = sage_Graph()
                    Ge2.add_vertices(range(nv2))
                    for i in Ge2.vertices():
                        for j in Ge2.vertices():
                            Ge2.add_edge(i, j, 2)

                    if nv1 + nv2 == SG.num_verts():

                        if (Gd.num_verts(), Ge2.num_verts()) != (1, 1):
                            Gde = sage_Graph()
                            Gde.add_vertices(Ge2.vertices())
                            Gde.add_edges(Ge2.edges())
                            for i in range(Ge2.num_verts() - 1, -1, -1):
                                Gde.relabel({i: i + Gd.num_verts()})
                            Gde.add_vertices(Gd.vertices())
                            Gde.add_edges(Gd.edges())
                            for i in range(Gd.num_verts()):
                                for j in range(Gd.num_verts(),
                                               Gde.num_verts()):
                                    Gde.add_edge(i, j, 2)
                            G_lst += [(Gde, 'Gde:' + str(Gd.num_verts()) +
                                       '+' + str(Ge2.num_verts()))]

                    if len(c_lst) + nv2 == SG.num_verts():

                        Gfd = sage_Graph()
                        Gfd.add_vertices(Gd2.vertices())
                        Gfd.add_edges(Gd2.edges())
                        for i in range(Gd2.num_verts() - 1, -1, -1):
                            Gfd.relabel({i: i + Gf.num_verts()})
                        Gfd.add_vertices(Gf.vertices())
                        Gfd.add_edges(Gf.edges())
                        for i in range(Gf.num_verts()):
                            for j in range(Gf.num_verts(), Gfd.num_verts()):
                                Gfd.add_edge(i, j, 2)
                        G_lst += [(Gfd, 'Gfd:' + str(Gf.num_verts()) + '+' +
                                   str(Gd2.num_verts()))]

                        Gge = sage_Graph()
                        Gge.add_vertices(Ge2.vertices())
                        Gge.add_edges(Ge2.edges())
                        for i in range(Ge2.num_verts() - 1, -1, -1):
                            Gge.relabel({i: i + Gg.num_verts()})
                        Gge.add_vertices(Gg.vertices())
                        Gge.add_edges(Gg.edges())
                        for i in range(Gg.num_verts()):
                            for j in range(Gg.num_verts(), Gge.num_verts()):
                                Gge.add_edge(i, j, 2)
                        G_lst += [(Gge, 'Gge:' + str(Gg.num_verts()) + '+' +
                                   str(Ge2.num_verts()))]

            # check for each of the constructed graphs whether
            # it is isomorphic to dpl.get_SG()
            #
            for (G, G_str) in G_lst:
                if SG.is_isomorphic(G, edge_labels=True):
                    max_verts = max(max_verts, G.num_verts())
                    if G_str not in s:
                        s += G_str + ' '

            if ':' in s:
                NSTools.p('\t', s)

    NSTools.p('max_verts =', max_verts)
コード例 #11
0
    bp = bp_tree.add('z', b[1], 1)
    NSTools.p('basepoints =', b)
    NSTools.p(LinearSeries.get([1], bp_tree))

    return


if __name__ == '__main__':

    #  Debug output settings
    #
    mod_lst = []
    mod_lst += ['__main__.py']
    # mod_lst += ['class_dp_lattice.py']
    # mod_lst += ['class_eta.py']
    NSTools.filter(mod_lst)  # output only from specified modules
    NSTools.filter(None)  # print all verbose output, comment to disable.
    # NSTools.get_tool_dct().clear()  # uncomment to remove all cache!

    if 'OUTPUT_PATH' not in os.environ:
        os.environ['OUTPUT_PATH'] = './'

    NSTools.start_timer()

    #
    # Should be between 3 and 9.
    # computes classifications up to rank "max_rank".
    #
    max_rank = 9

    #########################################
コード例 #12
0
def usecase__graphs(max_rank):
    '''
    Lists attributes of simple family graphs.
    
    Parameters
    ----------
    max_rank : int
        Maximal rank of DPLattice objects that are considered.                        
    '''
    row_format = '{:<6}{:<5}{:<8}{:<16}{:<7}{:<10}{:<95}{:<30}{:<15}{:<15}{:<15}{:<15}'

    already_in_cache = True
    dpl_lst = []
    rownr = 0
    row_lst = [[
        'rownr', 'deg', 'Mtype', 'type', '#vert', '#edges', 'degrees',
        'labels', 'complete', 'connected', 'vert-xfer', 'edge-xfer'
    ]]
    for rank in range(3, max_rank + 1):

        NSTools.p('rank =', rank)

        for dpl in DPLattice.get_cls(rank):

            already_in_cache = already_in_cache and (dpl.SG != None)

            dpl_lst += [dpl]
            SG, SG_data = dpl.get_SG()
            row_lst += [[
                rownr, 10 - rank,
                dpl.get_marked_Mtype(),
                dpl.get_real_type()
            ] + SG_data]
            rownr += 1

            if rank == 9 and (rownr <= 390 or rownr % 100 == 0):
                NSTools.p('\t\trownr =', rownr)

    s = ''
    for row in row_lst:
        s += row_format.format(*row) + '\n'

    NSTools.p('Classification of simple family graphs:\n' + s)

    if not already_in_cache:
        NSTools.p('Saving data for simple family graphs...')
        NSTools.save_tool_dct()

    # example for how to plot a simple family graph
    #
    NSTools.p('Plotting a simple family graph...')
    SG, SG_data = DPLattice.get_cls(6)[0].get_SG()
    P = SG.graphplot(vertex_size=1,
                     vertex_labels=True,
                     edge_labels=True,
                     color_by_label=False,
                     layout='circular').plot()

    P.save(os.environ['OUTPUT_PATH'] + 'graph.png')
    NSTools.p('#components =', SG.connected_components_number())
コード例 #13
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
コード例 #14
0
ファイル: ns_basis.py プロジェクト: niels-lubbes/ns_lattice
def get_bases_lst(a_lst, M, d_lst, m1_lst, perm=False):
    '''
    Returns a list of basis with specified generators.
    
    Parameters
    ----------
    a_lst : list<Div>
        A list of linear independent Div objects of 
        the same rank with 3<=rank<=9.
        It is required that
        "set(a_lst)==set([ a.mat_mul(M) for a in a_lst ])".
    
    M : sage_matrix<sage_ZZ>
        A unimodular matrix representing an involution.
    
    d_lst : list<Div>
        A list of Div objects d of the same rank as any
        element in "a_lst", so that "d*k==0" and "d*d==-2".
        These represent a root basis for the indecomposable 
        (-2)-classes in the Neron-Severi lattice of a 
        weak del Pezzo surface.   

    m1_lst : list<Div>
        A list of Div objects d of the same rank as any
        element in "a_lst", so that "d*k==d*d==-1".
        These represent (-1)-classes in the Neron-Severi 
        lattice of a weak del Pezzo surface.     
    
    perm : bool
        If False, then we consider two bases the same if the 
        generators of the first basis can be obtained from 
        the second basis via a permutation matrix.
    
    Returns
    -------
    list<tuple<Div>>
        A list of tuples of Div objects. Each tuple of Div objects
        represents a basis for the Neron-Severi lattice determined
        by d_lst and m1_lst. The bases are of the form          
            < a1,...,as, b1,...,bt >
        with the following property
            * a1,...,as are defined by the input "a_lst"
            * bi is an element in m1_lst such that bi*bj=am*bi=0 
              for all 1<=i<j<=t and 1<=m<=s              
        If "a_lst==[]" then "[[]]" is returned.   
               
    '''
    key = 'get_bases_lst__' + str(
        (a_lst, M, d_lst, m1_lst, perm)) + '__' + str(M.rank())
    if key in NSTools.get_tool_dct():
        return NSTools.get_tool_dct()[key]

    if a_lst == []:
        return [[]]

    if len(a_lst) == a_lst[0].rank():
        return [tuple(a_lst)]

    e_lst = []
    for m1 in get_indecomp_divs(m1_lst, d_lst):
        if set([m1 * a for a in a_lst]) != {0}:
            continue
        if m1 * m1.mat_mul(M) > 0:
            continue
        e_lst += [m1]

    bas_lst = []
    for e in e_lst:

        Me = e.mat_mul(M)
        new_d_lst = [d for d in d_lst if d * e == d * Me == 0]
        new_m1_lst = [m1 for m1 in m1_lst if m1 * e == m1 * Me == 0]
        add_lst = [e]
        if e != Me: add_lst += [Me]
        bas2_lst = get_bases_lst(a_lst + add_lst, M, new_d_lst, new_m1_lst,
                                 perm)

        if perm:
            bas_lst += bas2_lst
        else:
            for bas2 in bas2_lst:
                found = False
                for bas in bas_lst:
                    # check whether the two bases are the same up to
                    # permutation of generators
                    if set(bas) == set(bas2):
                        found = True
                        break  # break out of nearest for loop
                if not found:
                    NSTools.p('found new basis: ', bas2, ', bas2_lst =',
                              bas2_lst)
                    bas_lst += [bas2]

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

    return bas_lst
コード例 #15
0
    def get_part_roots(inv):
        '''
        Return two subsets of roots using the input involution.
        
        This method is used by get_cls().        
                    
        Parameters
        ----------
        inv : DPLattice
            We expect inv.type=='A0'.
            We will use inv.Mtype and inv.M. 
        
        Returns
        -------
        list<Div>, list<Div>
            Let R be defined by the list
                get_divs( get_ak( inv.get_rank() ), 0, -2, True )
            whose elements are Div objects.
            If r is a Div object, then M(r) is shorthand notation for 
                r.mat_mul(inv.M).
            The two returned lists correspond respectively to                       
                S := { r in R | M(r)=r }            
            and
                Q union Q' := { r in R | M(r) not in {r,-r} and r*M(r)>0 }
            where Q = M(Q').                        
        '''
        r_lst = get_divs(get_ak(inv.get_rank()), 0, -2, True)
        s_lst = [r for r in r_lst if r.mat_mul(inv.M) == r]
        tq1_lst = [
            r for r in r_lst if r.mat_mul(inv.M) not in [r, r.int_mul(-1)]
        ]
        tq_lst = [q for q in tq1_lst if q * q.mat_mul(inv.M) >= 0]

        q_lst = []
        for q in sorted(tq_lst):
            if q not in q_lst and q.mat_mul(inv.M) not in q_lst:
                q_lst += [q]

        # q_lst += [ q.int_mul( -1 ) for q in q_lst ]

        NSTools.p('r_lst      =', len(r_lst), r_lst)
        NSTools.p('s_lst      =', len(s_lst), s_lst)
        NSTools.p('tq1_lst    =', len(tq1_lst), tq1_lst)
        NSTools.p('tq_lst     =', len(tq_lst), tq_lst)
        NSTools.p('q_lst      =', len(q_lst), q_lst)
        NSTools.p('       M -->', len(q_lst),
                  [q.mat_mul(inv.M) for q in q_lst])
        NSTools.p('inv.Md_lst =', inv.Mtype, inv.Md_lst, ', rank =',
                  inv.get_rank())

        return s_lst, q_lst
コード例 #16
0
    def get_inv_lst(rank=9):
        '''
        Outputs a list representing a classification of root 
        subsystems that define unimodular involutions on the 
        Neron-Severi lattice of a weak del Pezzo surface.
        We consider 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 root systems live in a subspace of 
        the vector space associated to the Neron-Severi lattice 
        of a weak Del Pezzo surface.        
        
                
        Parameters
        ----------
        max_rank : int
            An integer in [3,...,9].           
    
        Returns
        -------
        list<DPLattice>
            A list of "DPLattice" objects dpl such that dpl.Md_lst 
            is the bases of a root subsystem and dpl.type == A0. 
            The list contains exactly one representative for 
            root subsystems up to equivalence, so that the root
            subsystem defines a unimodular involution.  
        '''
        # check cache
        key = 'get_inv_lst__' + str(rank)
        if False and key in NSTools.get_tool_dct():
            return NSTools.get_tool_dct()[key]

        bas_lst = DPLattice.get_bas_lst(rank)

        NSTools.p('rank =', rank)

        amb_lst = []
        inv_lst = []
        eta = ETA(len(bas_lst), 1)
        for bas in bas_lst:
            eta.update(bas.type)

            M = basis_to_involution(bas.d_lst, rank)
            if not is_integral_involution(M):
                continue
            inv = DPLattice([], bas.d_lst, M)
            inv.set_attributes()

            NSTools.p('Found type of involution: ', bas.type)

            # real structures with different Dynkin types may be equivalent
            if inv not in inv_lst:
                inv_lst += [inv]
            else:
                inv_prv = [inv2 for inv2 in inv_lst if inv == inv2][0]
                inv_lst = [inv2 for inv2 in inv_lst if not inv2 == inv]
                amb_lst += [inv, inv_prv]
                if inv > inv_prv:
                    inv_lst += [inv]
                else:
                    inv_lst += [inv_prv]
                NSTools.p('\tAmbitious type:', inv.Mtype, '==', inv_prv.Mtype,
                          ' inv>inv_prv: ', inv > inv_prv,
                          ' ambitious types =',
                          [amb.Mtype for amb in amb_lst if amb == inv])

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

        return inv_lst
コード例 #17
0
    def get_SG(self):
        '''
        The simple family graph associated to the 
        Neron-Severi lattice of a weak del Pezzo surface
        is defined as the incidence diagram of self.real_fam_lst,
        with the edges labeled <=1 removed. 
        All vertices are labeled with the index of the element in 
        self.real_fam_lst. 
        
        In the mathematical version (see arxiv paper) the vertices 
        are labeled with the dimension of the linear series, which is 
        always 1 with one exception: 
        If len(self.real_fam_lst)==0 and rank==3, then
        the simple family graph consists of a single vertex labeled 2. 
        
        Example
        -------
        # The following graph is related to the E8 root system:
        #
        dpl = DPLattice.get_cls( 9 )[0]
        assert set(dpl.get_SG().num_verts()) == {2160}
        assert set(dpl.get_SG().get_degree()) == {2095}
        assert set(dpl.get_SG().edge_labels()) == {2,3,4,5,6,7,8}

        
        Returns
        -------
        sage_GRAPH, [int, int, list<int>, list<int>, bool, bool, bool, bool ]
            The simple family graph self.SG and a list self.SG_data 
            associated to the current DPLattice object.
            Here self.SG_data consists of data that describes self.SG.
            This method also initializes self.SG and self.SG_data.
        '''

        if self.SG != None:
            return self.SG, self.SG_data

        if self.get_rank() == 9 and self.get_numbers()[-1] > 800:
            NSTools.p(
                'Initializing simple family graph of current DPLattice object...',
                self.get_rank(), self.get_marked_Mtype(), self.get_real_type())

        f = self.real_fam_lst
        f_range = range(len(f))

        self.SG = sage_Graph()
        self.SG.add_vertices(f_range)
        for i in f_range:
            for j in f_range:
                if f[i] * f[j] > 1:
                    self.SG.add_edge(i, j, f[i] * f[j])

        self.SG_data = [
            self.SG.num_verts(),  # number of vertices
            self.SG.num_edges(),  # number of edges
            sorted(list(set(
                self.SG.degree()))),  # possible numbers of outgoing edges
            sorted(list(set(self.SG.edge_labels()))),  # possible edge labels
            self.SG.is_clique(),  # True iff the graph is complete.
            self.SG.is_connected(),
            self.SG.is_vertex_transitive(),
            self.SG.is_edge_transitive()
        ]

        return self.SG, self.SG_data
コード例 #18
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
コード例 #19
0
def get_root_bases_orbit(d_lst, positive=True):
    '''
    Computes the orbit of a root base under the Weyl group.
    
    Parameters
    ----------
    d_lst : list<Div>
        A list of lists of "Div" objects "d" of the same rank or the empty list.    

    positive : bool
    
    Returns
    -------
    list<list<Div>>
        A list of distinct lists of "Div" objects "d" of the same rank. 
        such that d*d=-2 and d*(-3h+e1+...+er)=0 where r=rank-1.
        
        If "d_lst" is the empty list, then "[]" is returned.
        
        Otherwise we return a list of root bases such that each root basis
        is obtained as follows from a root "s" such that s*s=-2 
        and s*(-3h+e1+...+er)=0: 
        
            [ d + (d*s)d for d in d_lst ]
        
        We do this for all possible roots in [s1,s2,s3,...]: 
        
            [ [ d + (d*s1)d for d in d_lst ],  [ d + (d*s2)d for d in d_lst ], ... ]
         
        Mathematically, this means that we consider the Weyl group 
        of the root system with Dynkin type determined by the rank of elements 
        in "d_lst". The Dynkin type is either 
            A1, A1+A2, A4, D5, E6, E7 or E8.
        We return the orbit of the elements in "d_lst" under
        the action of the Weyl group.
                
        If "positive==True" then the roots in the basis are all positive
        and thus of the form 
            <ij>, <1ijk>, <2ij>, <30i>
        with i<j<k. 
        For example '15' and '1124' but not '-15' or '-1124'. 
        See "Div.get_label()" for the notation.                           
    '''
    if d_lst == []:
        return [[]]

    rank = d_lst[0].rank()

    # in cache?
    key = 'get_root_bases_orbit_' + str(d_lst) + '_' + str(rank)
    if key in NSTools.get_tool_dct():
        return NSTools.get_tool_dct()[key]

    # obtain list of all positive (-2)-classes
    m2_lst = get_divs(get_ak(rank), 0, -2, True)
    # m2_lst += [ m2.int_mul( -1 ) for m2 in m2_lst]
    NSTools.p('d_lst  =', len(d_lst), d_lst, ', m2_lst =', len(m2_lst), m2_lst)

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

    d_lst.sort()
    d_lst_lst = [d_lst]
    for cd_lst in d_lst_lst:

        total = len(m2_lst) * len(d_lst_lst)
        for m2 in m2_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),
                          ', len(d_lst_lst) =', len(d_lst_lst), ', total =',
                          total)

            #
            # The action of roots on a root base is by reflection:
            #     cd - 2(cd*m2/m2*m2)m2
            # Notice that m2*m2==-2.
            #
            od_lst = [cd + m2.int_mul(cd * m2) for cd in cd_lst]
            # print( 'm2 =', m2, ', od_lst =', od_lst, ', cd_lst =', cd_lst, ', d_lst_lst =', d_lst_lst, ' positive =', positive )

            od_lst.sort()
            if od_lst not in d_lst_lst:
                d_lst_lst += [od_lst]

    # select positive roots if positive==True
    pd_lst_lst = []
    for d_lst in d_lst_lst:
        if positive and '-' in [d.get_label(True)[0] for d in d_lst]:
            continue  # continue with for loop since a negative root in basis
        pd_lst_lst += [d_lst]

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

    NSTools.p('#orbit(' + str(d_lst) + ') =', len(pd_lst_lst))

    return pd_lst_lst
コード例 #20
0
def get_dynkin_type(d_lst):
    '''
    Parameters
    ----------
    d_lst : list<Div>
        A list of lists of "Div" objects "d" of 
        the same rank, such that 
            d*d=-2 and d*(-3h+e1+...+er)=0 
        where 
            r=rank-1 and rank in [3,...,9].  
        We assume that "is_root_basis(d_lst)==True":
        linear independent, self intersection number -2
        and pairwise product either 0 or 1.            
                     
    Returns
    -------
    string
        Returns a string denoting the Dynkin type of a 
        root system with basis "d_lst".  
        Returns 'A0' if "d_lst==[]".
    
    Note
    ----
        For example:
        [<1145>, <1123>, <23>, <45>, <56>, <78>] --> '3A1+A3'
        where <1145> is shorthand for "Div.new('1145')".      
        
    Raises
    ------
    ValueError
        If the Dynkin type of d_lst cannot be recognized.
         
    '''
    if d_lst == []: return 'A0'

    # check whether values are cached
    #
    construct_dynkin_types = True
    max_r = d_lst[0].rank() - 1
    key = 'get_dynkin_type_' + str(max_r)
    for r in range(max_r, 8 + 1):
        if 'get_dynkin_type_' + str(r) in NSTools.get_tool_dct():
            key = 'get_dynkin_type_' + str(r)
            construct_dynkin_types = False

    # construct list of dynkin types if values are not cached
    #
    if construct_dynkin_types:
        NSTools.p('Constructing list of Dynkin types... max_r =', max_r)

        ade_lst = []
        for comb_lst in sage_Combinations(max_r * ['A', 'D', 'E'], max_r):
            for perm_lst in sage_Permutations(comb_lst):
                ade_lst += [perm_lst]
        #
        # "ade_lst" contains all combinations of 'A', 'D', 'E'
        # and looks as follows:
        #
        #     ade_lst[0] = ['A', 'A', 'A', 'A', 'A', 'A', 'A', 'A']
        #     ade_lst[1] = ['A', 'A', 'A', 'A', 'A', 'A', 'A', 'D']
        #     ade_lst[2] = ['A', 'A', 'A', 'A', 'A', 'A', 'D', 'A']
        #     ...
        #     ade_lst[?] = ['A', 'D', 'A', 'D', 'A', 'D', 'E', 'A']
        #     ...
        #     ade_lst[-1]= ['E', 'E', 'E', 'E', 'E', 'E', 'E', 'E']
        #

        type_lst = []
        ts_lst = []
        for ade in ade_lst:
            for r in range(1, max_r + 1):
                for p_lst in sage_Partitions(r + max_r, length=max_r):

                    # obtain type list
                    t_lst = [(ade[i], p_lst[i] - 1) for i in range(max_r)
                             if p_lst[i] != 1]
                    t_lst.sort()

                    # obtain Root system
                    # or continue if invalid Cartan/Dynkin type
                    if ('D', 2) in t_lst or ('D', 3) in t_lst:
                        continue
                    try:
                        rs = sage_RootSystem(t_lst)
                    except ValueError as err:
                        continue  # not a valid Cartan type

                    # obtain graph G
                    mat = list(-1 * rs.cartan_matrix())
                    G = sage_Graph()
                    G.add_vertices(range(len(mat)))
                    for i in range(len(mat)):
                        for j in range(len(mat[0])):
                            if mat[i][j] == 1:
                                G.add_edge(i, j)

                    # obtain string for type
                    # Example: [(A,1),(A,1),(A,1),(A,3)] ---> '3A1+A3'
                    tmp_lst = [t for t in t_lst]
                    ts = ''
                    while len(tmp_lst) > 0:
                        t = tmp_lst[0]
                        c = tmp_lst.count(t)
                        while t in tmp_lst:
                            tmp_lst.remove(t)
                        if ts != '':
                            ts += '+'
                        if c > 1:
                            ts += str(c)

                        ts += t[0] + str(t[1])

                    # add to type_lst if new
                    if ts not in ts_lst:
                        type_lst += [(G, ts, t_lst)]
                        ts_lst += [ts]
                        NSTools.p('added to list: ', ts,
                                  '\t\t...please wait...')

        NSTools.p('Finished constructing list of Dynkin types.')
        # cache the constructed "type_lst"
        NSTools.get_tool_dct()[key] = type_lst
        NSTools.save_tool_dct()

    # end if
    else:
        type_lst = NSTools.get_tool_dct()[key]
    G1 = get_graph(d_lst)

    # loop through all types and check equivalence
    for (G2, ts, t_lst) in type_lst:
        if G1.is_isomorphic(G2):
            return ts

    raise ValueError('Could not recognize Dynkin type: ', d_lst)
コード例 #21
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
コード例 #22
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
コード例 #23
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