Exemplo n.º 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))
Exemplo n.º 2
0
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
Exemplo n.º 3
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
Exemplo n.º 4
0
def is_integral_involution(M):
    '''
    Parameters
    ----------
    M : sage_matrix
        A matrix M.
    
    Returns
    -------
    bool
        Returns True if the matrix is an involution, 
        preserves inner product with signature (1,r) 
        and has integral coefficients.
    '''

    nrows, ncols = M.dimensions()

    # check whether involution
    if M * M != sage_identity_matrix(nrows):
        return False

    # check whether inner product is preserved
    S = sage_diagonal_matrix([1] + (ncols - 1) * [-1])
    if M.transpose() * S * M != S:
        return False

    # check whether coefficients are integral
    for r in range(nrows):
        for c in range(ncols):
            if M[r][c] not in sage_ZZ:
                return False

    # check whether canonical class is preserved
    ak = get_ak(nrows)
    if ak.mat_mul(M) != ak:
        return False

    return True
Exemplo n.º 5
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
Exemplo n.º 6
0
    def get_num_types(inv, bas, bas_lst):
        '''
        Returns the number of root bases in the 
        eigenspace of eigenvalue 1 of the involution 
        defined by M.inv.   
        
        If this number is unknown, then -1 is returned.

        This method is used by get_cls() before 
        calling seek_bases().
        
        Parameters
        ----------
        inv : DPLattice
        
        bas : DPLattice
        
        bas_lst : list<DPLattice>
            We expect this to be the output of get_bas_lst()
            Thus a list of inequivalent DPLattice objects
                  
        Returns
        -------
        int
            If there does not exists a DPLattice in bas_lst whose type is 
            inv.Mtype and bas.type combined, then return 0. 
            Otherwise return either -1 or the 
            number of root bases in the eigenspace of eigenvalue 1 
            of the involution defined by M.inv. 
            We expect this number to be at most 3.                         
        '''

        # check whether the combined type exists in bas_lst
        t1_lst = convert_type(inv.Mtype)
        t2_lst = convert_type(bas.type)
        type_exists = False
        for bas2 in bas_lst:
            if sorted(t1_lst + t2_lst) == convert_type(bas2.type):
                type_exists = True
                break
        if not type_exists:
            return 0

        # computes the roots in the eigenspace of eigenvalue 1
        # of the involution defined by inv
        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]

        if len(s_lst) == 30:  # D6 since #roots=60=2*30
            if bas.type in ['2A1', 'A3', '4A1', '2A1+A3', 'A5']:
                return 2
            if bas.type in ['3A1', 'A1+A3']:
                return 3
            return 1

        if len(s_lst) == 63:  # E7 since #roots=126=2*63
            if bas.type in ['3A1', '4A1', 'A5', 'A1+A3', '2A1+A3', 'A1+A5']:
                return 2
            return 1

        return -1
Exemplo n.º 7
0
    def set_attributes(self, level=9):
        '''
        Sets attributes of this object, depending
        on the input level.
        For constructing a classification we instantiate
        many DPLattice objects. This method allows us 
        to minimize the number of attributes that computed
        (thus we use lazy evaluation).
        
        Parameter
        ---------
        self: DPLattice
            At least self.M, self.Md_lst and self.d_lst        
            should be initialized.
        
        level : int
            A non-negative number.
        '''

        # M, Md_lst and d_lst are set.

        if self.m1_lst == None:
            all_m1_lst = get_divs(get_ak(self.get_rank()), 1, -1, True)
            self.m1_lst = get_indecomp_divs(all_m1_lst, self.d_lst)

        if level < 1: return

        if self.fam_lst == None:
            all_fam_lst = get_divs(get_ak(self.get_rank()), 2, 0, True)
            self.fam_lst = get_indecomp_divs(all_fam_lst, self.d_lst)

        if level < 2: return

        if self.real_d_lst == None:
            self.real_d_lst = [d for d in self.d_lst if d.mat_mul(self.M) == d]

        if level < 3: return

        if self.real_m1_lst == None:
            self.real_m1_lst = [
                m1 for m1 in self.m1_lst if m1.mat_mul(self.M) == m1
            ]

        if level < 4: return

        if self.real_fam_lst == None:
            self.real_fam_lst = [
                f for f in self.fam_lst if f.mat_mul(self.M) == f
            ]

        if level < 5: return

        if self.or_lst == None:
            self.or_lst = []
            for m2 in get_divs(get_ak(self.get_rank()), 0, -2, True):
                if [m2 * d for d in self.d_lst] == len(self.d_lst) * [0]:
                    self.or_lst += [m2]

        if level < 6: return

        if self.sr_lst == None:
            V = sage_VectorSpace(sage_QQ, self.get_rank())
            W = V.subspace([d.e_lst for d in self.d_lst])
            self.sr_lst = []
            for m2 in get_divs(get_ak(self.get_rank()), 0, -2, True):
                if sage_vector(m2.e_lst) in W:
                    self.sr_lst += [m2]

        if level < 7: return

        if self.type == None:
            self.type = get_dynkin_type(self.d_lst)

        if level < 8: return

        if self.Mtype == None:
            self.Mtype = get_dynkin_type(self.Md_lst)

        if level < 9: return

        if self.G == None:
            self.G = get_ext_graph(self.d_lst + self.m1_lst, self.M)