コード例 #1
0
ファイル: orb_product.py プロジェクト: niels-lubbes/orbital
def get_pmz_verify( o ):
    '''
    Parameters
    ----------
        o : OrbOutput
    
    Returns
    -------
    Boolean
        * Return "None" if the test could not be performed because
          either parametrization or implicit equation was not available.            
        * Return "True" if implicit equation of projected surface
          agrees with parametrization composed with projection.          
        * Return "False" if both parametrization and implicit equation were 
          available but do not agree.               
    '''

    if not o.input.do['pmz'] or not o.input.do['imp']:
        return None

    if o.prj_pol == -1 or o.gen == -2:
        return False

    OrbTools.p( 'Testing parametrization...' )
    c0, s0, c1, s1 = OrbRing.coerce( 'c0,s0,c1,s1' )
    x0, x1, x2, x3 = OrbRing.coerce( 'x0,x1,x2,x3' )
    f = o.prj_pol
    p = o.prj_pmz_lst
    fp = o.prj_pol.subs( {x0:p[0], x1:p[1], x2:p[2], x3:p[3]} )
    test = fp.reduce( [c0 * c0 + s0 * s0 - 1, c1 * c1 + s1 * s1 - 1] )
    OrbTools.p( test )
    if test != 0:
        return False

    return True
コード例 #2
0
ファイル: orb_product.py プロジェクト: niels-lubbes/orbital
def get_genus( pol, plane = 'x1+2*x2+17*x3+11*x0' ):
    '''
    The method requires that the maple-command 
    is in "os.environ['PATH']". 
    See [https://www.maplesoft.com].
    
    Parameters
    ----------
    pol : OrbRing.R
        A polynomial in QQ[x0,x1,x2,x3].
    
    plane : string 
        A String of a linear polynomial in QQ[x0,x1,x2,x3].
        
    Returns
    -------
    int
        An integer denoting the geometric genus of
        the curve given by the intersection of the 
        surface defined by "pol", with the plane defined 
        by "plane". If this geometric genus is not defined, 
        then -2 is returned. 
        If Maple is not installed then -3 is returned.
    '''
    OrbTools.p( pol )

    # obtain an equation for the curve defined
    # intersecting a plane with the zero-set of pol.
    plane = OrbRing.coerce( plane )
    K = sage_ideal( pol, plane ).groebner_basis()
    P = K[0]
    if P.total_degree() <= 1:
        P = K[1]
    P = P.subs( {OrbRing.coerce( 'x3' ):1} )

    # compute geometric genus with Maple.
    try:
        sage_maple.eval( 'with(algcurves);' )
    except:
        return -3

    sage_maple.eval( 'P := ' + str( P ) + ';' )
    gen = sage_maple.eval( 'genus(P,x1,x2);' )

    OrbTools.p( gen )

    try:
        return int( gen )
    except ValueError:
        return -2
コード例 #3
0
ファイル: orb_matrices.py プロジェクト: niels-lubbes/orbital
def get_omat(o_str):
    '''
    Parameters
    ----------
    o_str : string
        A string with format:
            'O****'
        where the *-symbol is a place holder for
        one of the following characters: r,s,m,p,a.  
                    
    Returns
    -------
    sage_matrix
        A 9x9 matrix over "OrbRing.num_field" of the shape     
             
            1  0  0  0  0  0  0  0  0 
            0  *  *  0  0  0  0  0  0 
            0  *  *  0  0  0  0  0  0  
            0  0  0  *  *  0  0  0  0  
            0  0  0  *  *  0  0  0  0  
            0  0  0  0  0  *  *  0  0  
            0  0  0  0  0  *  *  0  0  
            0  0  0  0  0  0  0  *  *  
            0  0  0  0  0  0  0  *  *
            
        where each 2x2 matrix on the diagonal is of either 
        one of the following shapes:
                  
            'r': c0 -s0    's': -c0  s0      
                 s0  c0         -s0 -c0

            'p': 1  0    'm': -1  0    'a': 1  0
                 0  1          0 -1         0 -1
    
    '''
    # parse input
    if o_str[0] != 'O' or len(o_str) != 5:
        raise ValueError('Incorrect input string: ', o_str)

    c0, s0 = OrbRing.coerce('c0,s0')

    br = [[c0, -s0], [s0, c0]]
    bs = [[-c0, s0], [-s0, -c0]]
    bp = [[1, 0], [0, 1]]
    bm = [[-1, 0], [0, -1]]
    ba = [[1, 0], [0, -1]]
    b_dct = {'r': br, 's': bs, 'p': bp, 'm': bm, 'a': ba}

    bmat_lst = []
    for ch in o_str[1:]:
        bmat_lst += [b_dct.get(ch, 'error')]

    omat = sage_identity_matrix(OrbRing.R, 9)
    idx = 1
    for bmat in bmat_lst:
        omat.set_block(idx, idx, sage_matrix(OrbRing.R, bmat))
        idx = idx + 2

    return omat
コード例 #4
0
    def test__get_project( self ):

        pol_lst = OrbRing.coerce( '[-x0^2+x1^2+x2^2+x3^2+x4^2+x5^2+x6^2+x7^2+x8^2, x8, x7, x6, x5, x1*x2-x0*x4]' )
        pmat = get_pmat( False )
        print( pmat )

        out = get_project( pol_lst, pmat )
        print( out )
        assert str( out ) == '(x0^4 - x0^2*x1^2 - x0^2*x2^2 - x1^2*x2^2 - x0^2*x3^2, -x^2*y^2 - x^2 - y^2 - z^2 + 1)'
コード例 #5
0
    def test__get_tmat(self):

        #
        # Setup inverse stereographic projection:
        # S: P^7 ---> S^7
        #
        v = OrbRing.coerce('[v0,v1,v2,v3,v4,v5,v6,v7,v8]')
        d = v[1]**2 + v[2]**2 + v[3]**2
        v0_2 = v[0]**2
        vec_lst = []
        vec_lst += [v0_2 + d]
        vec_lst += [2 * v[0] * v[1]]
        vec_lst += [2 * v[0] * v[2]]
        vec_lst += [2 * v[0] * v[3]]
        vec_lst += [2 * v[0] * v[4]]
        vec_lst += [2 * v[0] * v[5]]
        vec_lst += [2 * v[0] * v[6]]
        vec_lst += [2 * v[0] * v[7]]
        vec_lst += [-v0_2 + d]
        x = sage_vector(OrbRing.R, vec_lst)
        print(x)

        #
        # Setup Euclidean translation in S^7
        #    T:S^7--->S^7
        #
        tmat = get_tmat(None)
        print(tmat)

        #
        # Setup stereographic projection
        #     P:S^7--->P^7
        #
        pmat = []
        pmat += [[1, 0, 0, 0] + [0, 0, 0, 0, -1]]
        pmat += [[0, 1, 0, 0] + [0, 0, 0, 0, 0]]
        pmat += [[0, 0, 1, 0] + [0, 0, 0, 0, 0]]
        pmat += [[0, 0, 0, 1] + [0, 0, 0, 0, 0]]
        pmat += [[0, 0, 0, 0] + [1, 0, 0, 0, 0]]
        pmat += [[0, 0, 0, 0] + [0, 1, 0, 0, 0]]
        pmat += [[0, 0, 0, 0] + [0, 0, 1, 0, 0]]
        pmat += [[0, 0, 0, 0] + [0, 0, 0, 1, 0]]
        pmat = sage_matrix(pmat)
        print(pmat)

        # Check whether composition is an Euclidean
        # translation in P^7:
        #    PoToS
        #
        tv = pmat * tmat * x
        tv = tv / (2 * v[0])
        print(tv)

        assert str(
            tv
        ) == '(v0, v0*t1 + v1, v0*t2 + v2, v0*t3 + v3, v0*t4 + v4, v0*t5 + v5, v0*t6 + v6, v0*t7 + v7)'
コード例 #6
0
ファイル: povray_aux.py プロジェクト: niels-lubbes/orbital
def get_pmz_value( pmz_lst, v0, v1, prec = 50 ):
    '''
    Parameters
    ----------
    pmz_lst : list<sage_POLY> 
        A list of 4 polynomials in QQ[c0,s0,c1,s1].
    
    v0 : sage_REALNUMBER      
        A real number in [0,2*pi)
    
    v1 : sage_REALNUMBER       
        A real number in [0,2*pi)
    
    prec : int    
        Number of digits.

    scale : int
        A positive integer.
    
    Returns
    -------
    list<float>
        Returns a point in R^3 represented by a list of 3 float 
        values with precision "prec":  
            F(a,b)=[ x, y, z  ].
        Here F(a,b) is represented by "pmz_lst" and
        has the following domain and range:  
              F: [0,2*pi)X[0,2*pi) ---> R^3.
        The parametrization is a map in terms of cosine and sine.   
        
        If F is not defined at the point it first looks at (v0-dv,v1-dv) 
        where dv is very small. If that does not work, then we return None.
               
    '''
    c0, s0, c1, s1, t0, t1 = OrbRing.coerce( 'c0,s0,c1,s1,t0,t1' )

    dct = {c0:sage_cos( v0 ), s0:sage_sin( v0 ), c1:sage_cos( v1 ), s1:sage_sin( v1 ), t0:v0, t1:v1}


    if type( pmz_lst[0] ) == int:
        W = sage_QQ( pmz_lst[0] )
    else:
        W = pmz_lst[0].subs( dct )

    X = pmz_lst[1].subs( dct )
    Y = pmz_lst[2].subs( dct )
    Z = pmz_lst[3].subs( dct )

    if W == 0:
        return None

    XW = round( X / W, prec )
    YW = round( Y / W, prec )
    ZW = round( Z / W, prec )

    return [ XW, YW, ZW ]
コード例 #7
0
    def test__get_pmz_verify__perseus( self ):

        o = OrbOutput( OrbInput() )

        o.input.do['pmz'] = True
        o.input.do['imp'] = True

        o.prj_pmz_lst = '[-2*s1 + 3, 4/5*c0*c1 - 3/5*s0*c1 + 7/5*c0*s1 + 6/5*s0*s1 - 12/5*c0 - 11/5*s0 - 2*s1 + 3, 3/5*c0*c1 + 4/5*s0*c1 - 6/5*c0*s1 + 7/5*s0*s1 + 11/5*c0 - 12/5*s0, -2*s1 + 2]'
        o.prj_pmz_lst = OrbRing.coerce( o.prj_pmz_lst )

        o.prj_pol = '25*x0^4 + 100*x0^3*x1 + 50*x0^2*x1^2 - 100*x0*x1^3 + 25*x1^4 - 50*x0^2*x2^2 - 100*x0*x1*x2^2 + 50*x1^2*x2^2 + 25*x2^4 - 24*x0^3*x3 - 40*x0^2*x1*x3 + 20*x0*x1^2*x3 + 20*x0*x2^2*x3 - 41*x0^2*x3^2 - 100*x0*x1*x3^2 + 50*x1^2*x3^2 + 50*x2^2*x3^2 + 20*x0*x3^3 + 25*x3^4'
        o.prj_pol = OrbRing.coerce( o.prj_pol )

        o.gen = 1

        print( o )
        tst = get_pmz_verify( o )
        print( tst )
        assert tst == True
コード例 #8
0
    def test__get_orb_bp_tree( self ):
        pmz_lst = OrbRing.coerce( '[2,c0,s0,c1,s1,c0,s0,c1,s1]' )
        bp_tree = get_orb_bp_tree( pmz_lst )
        print( bp_tree )

        out = str( bp_tree )

        assert 'chart=xv, depth=0, mult=1, sol=(a0, (a0))' in out
        assert 'chart=xv, depth=0, mult=1, sol=(a0, (-a0))' in out
        assert 'chart=xv, depth=0, mult=1, sol=(-a0, (-a0))' in out
        assert 'chart=xv, depth=0, mult=1, sol=(-a0, (a0))' in out
コード例 #9
0
ファイル: orb_product.py プロジェクト: niels-lubbes/orbital
def get_pmz( pmat, omat, vmat ):
    '''
    Parameters
    ----------
    pmat : sage_matrix
        A 4x9 invertible matrix with entries in QQ. 
        A matrix represents a projection from 
        a 7-sphere in projective 8-space to projective 3-space.
        
    omat : sage_matrix 
        A 9x9 invertible matrix with entries in QQ[c1,s1]. 
        This matrix represents a projective curve 
        in the automorphism group of the projective 7-sphere.
        Thus "omat" represents a 1-parameter subgroup in Aut(S^7).
                    
    vmat : sage_matrix 
        A 9x9 invertible matrix with entries in QQ. 
        This matrix represents an element in Aut(S^7),
        which transforms a standard circle (see below).
        
    Returns
    -------
    list
        Two lists of elements in QQ[c0,s0,c1,s1].
        The 1st list has length 9 and the 2nd list has length 4.
        The 1st list represent a parametrization 
              S^1xS^1--->S^7
        of a surface in S^7 and the 2nd list the parametrization 
              S^1xS^1--->P^3
        of the surface projected into
        P^3 (projective 3-space) using "pmat". 
        Here (c0,s0) and (c1,s1) are points on S^1.
                    
    Notes
    -----
    The surface in S^7 is obtained by applying a 1-parameter subgroup to a 
    circle C. Here C is the "vmat"-transform of the standard circle B in S^7 
    where
    B = { x | -x0^2+x1^2+x2^2==0 } and S^7 = { x | -x0^2+x1^2+...+x8^2==0 }.             
    '''
    c1, s1 = OrbRing.coerce( 'c1,s1' )
    pmz_lst = list( omat * vmat * sage_vector( [1, c1, s1, 0, 0, 0, 0, 0, 0] ) )
    prj_pmz_lst = list( pmat * omat * vmat * sage_vector( [1, c1, s1, 0, 0, 0, 0, 0, 0] ) )

    return pmz_lst, prj_pmz_lst
コード例 #10
0
ファイル: orb_product.py プロジェクト: niels-lubbes/orbital
def get_imp( omat, vmat ):
    '''
    Parameters
    ----------
    omat : sage_matrix 
        A 9x9 invertible matrix with entries in QQ[c0,s0]. 
        This matrix represents a projective curve 
        in the automorphism group of the projective 7-sphere.
        Thus "omat" represents a 1-parameter subgroup in Aut(S^7).
                    
    vmat : sage_matrix  
        A 9x9 invertible matrix with entries in QQ. 
        This matrix represents an element in Aut(S^7),
        which transforms a standard circle.    

    Returns
    -------
    list<OrbRing.R>
        A list of elements in QQ[x0,...,x8].
        This list represent the generators of the ideal corresponding to 
        the variety, which is obtained by applying a 1-parameter subgroup to
        a circle C. Here C is the "vmat"-transform of 
        the standard circle B in S^7 where        
        B = { x | -x0^2+x1^2+x2^2==0 } and S^7 = { x | -x0^2+x1^2+...+x8^2==0 }.   
    '''

    # declare list of coordinate variables
    v_lst = OrbRing.coerce( '[v0,v1,v2,v3,v4,v5,v6,v7,v8]' )
    x_lst = OrbRing.coerce( '[x0,x1,x2,x3,x4,x5,x6,x7,x8]' )
    c_lst = OrbRing.coerce( '[c0,s0]' )

    # construct generators of ideal of orbital product
    g_lst = []

    # v[i] coordinates of points on a circle C in S^7
    vmatI = vmat.inverse()
    g_lst += list( vmatI * sage_vector( v_lst ) )[3:]
    g_lst += OrbRing.coerce( '[-v0^2+v1^2+v2^2+v3^2+v4^2+v5^2+v6^2+v7^2+v8^2]' )

    # consider all point that are an orbit of C
    # the 1-parameter subgroup of Aut(S^7)
    # represented by the matrix omat
    e_lst = list( omat * sage_vector( v_lst ) )
    g_lst += [ x_lst[i] - e_lst[i] for i in range( 0, 8 + 1 ) ]
    g_lst += OrbRing.coerce( '[-x0^2+x1^2+x2^2+x3^2+x4^2+x5^2+x6^2+x7^2+x8^2]' )
    g_lst += OrbRing.coerce( '[s0^2+c0^2-1]' )

    # compute the resulting variety by elimination
    g_ideal = OrbRing.R.ideal( g_lst )
    imp_lst = list( g_ideal.elimination_ideal( v_lst + c_lst ).gens() )

    return imp_lst
コード例 #11
0
    def test__get_sing_lst( self ):
        pol = OrbRing.coerce( '(x1^2+x2^2+x3^2+3*x0^2)^2-16*x0^2*(x1^2+x2^2)' )
        print( pol )

        os.environ['PATH'] += os.pathsep + '/home/niels/Desktop/n/app/magma/link'
        try:
            sage_magma.eval( 1 + 1 )
            print( 'Magma is installed.' )
        except:
            print( 'Magma is NOT installed.' )
            sng_lst = get_sing_lst( pol )
            print( sng_lst )
            assert sng_lst == []
            return

        sng_lst = get_sing_lst( pol )
        print( sng_lst )
        assert str( sng_lst ) == "[('[x0^2 + 1/3*x3^2,x1,x2]', 2), ('[x0,x1^2 + x2^2 + x3^2]', 2*t + 1)]"
コード例 #12
0
    def __str__(self):

        if OrbOutput.short_str:
            return self.get_short_str()

        s = '\n'
        s += 30 * '-' + '\n'

        s += str(self.input) + '\n'

        s += 'pmz_lst       = ' + str(self.pmz_lst) + '\n'
        s += 'prj_pmz_lst   = ' + str(self.prj_pmz_lst) + '\n'
        s += 'imp_lst       = ' + str(self.imp_lst) + '\n'
        s += 'emb           = ' + str(self.emb) + '\n'
        s += 'dim           = ' + str(self.dim) + '\n'
        s += 'deg           = ' + str(self.deg) + '\n'
        s += 'gen           = ' + str(self.gen) + '\n'
        s += 'prj_pol       = ' + str(self.prj_pol) + '\n'
        if self.prj_pol != None:
            s += 'prj_pol{x0:0} = ' + str(
                sage_factor(self.prj_pol.subs({OrbRing.coerce('x0'): 0
                                               }))) + '\n'
        s += 'xyz_pol       = ' + str(self.xyz_pol) + '\n'
        s += 'pmz_test      = ' + str(self.pmz_test) + '\n'

        if self.fct_lst != None:
            s += 'fct_lst       = ' + str(len(self.fct_lst)) + ' factors\n'
            if len(self.fct_lst) > 1:
                for fct in self.fct_lst:
                    s += '              ~ ' + str(fct) + '\n'

        if self.sng_lst != None:
            s += 'sng_lst       = ' + str(len(self.sng_lst)) + ' components\n'
            for sng in self.sng_lst:
                s += '              ~ ' + str(sng) + '\n'

        if self.bp_tree != None:
            s += 'bp_tree       = ' + str(self.bp_tree) + '\n'

        s += 'short_str     = '
        s += self.get_short_str() + '\n'

        s += 30 * '-' + '\n'
        return s
コード例 #13
0
ファイル: orb_matrices.py プロジェクト: niels-lubbes/orbital
def get_rmat(r_str):
    '''
    Parameters
    ----------
    r_str : string
        A string with the following format                                             
            'R****[%,%,%,%]'                   
        where: 
            *-symbol is a place holder for a character in ['r','s','m','p','a']                                                                   
            %-symbol denotes an integer in [0,360]
        
    Returns
    -------
    sage_matrix
        A 9x9 matrix over "OrbRing.num_field" of the same shape as 
            "get_omat( 'O****' )"          
        The "c0" and "s0" in each block are substituted
        with a rational approximation of cos(%) and sin(%)
        respectively.       
    '''

    omat = get_omat('O' + r_str[1:5])
    cs_lst = sage__eval(r_str[5:])
    c0, s0 = OrbRing.coerce('c0,s0')

    rmat = []
    idx = -1
    dct = {}
    for row in list(omat):

        if idx % 2 == 0:
            cv, sv = get_cs(cs_lst[idx / 2])
            dct = {c0: cv, s0: sv}
            if cv**2 + sv**2 != 1:
                raise Exception('Expect cos(%)^2+sin(%)^2=1.')

        idx = idx + 1

        rrow = []
        for col in row:
            rrow += [col.subs(dct)]
        rmat += [rrow]

    return sage_matrix(rmat)
コード例 #14
0
    def test__get_factor_lst( self ):

        pol = OrbRing.coerce( '(x1-x0)^3*(x1-3*x0)^2*(x2^2+x3^2)' )
        print( pol )

        os.environ['PATH'] += os.pathsep + '/home/niels/Desktop/n/app/maple/link/bin'
        try:
            sage_maple.eval( 'with(algcurves);' )
            print( 'Maple is installed.' )
        except:
            print( 'Maple is NOT installed.' )
            fct_lst = get_factor_lst( pol )
            print( fct_lst )
            assert fct_lst == []
            return

        fct_lst = get_factor_lst( pol )
        print( fct_lst )
        assert str( fct_lst ) == "[('x2-RootOf(_Z^2+1)*x3', '1'), ('x2+RootOf(_Z^2+1)*x3', '1'), ('x0-1/3*x1', '2'), ('x0-x1', '3')]"
コード例 #15
0
    def test__get_genus( self ):

        pol = OrbRing.coerce( '(x1^2+x2^2+x3^2+3*x0^2)^2-16*(x1^2+x2^2)' )
        print( pol )

        os.environ['PATH'] += os.pathsep + '/home/niels/Desktop/n/app/maple/link/bin'
        try:
            sage_maple.eval( '1 + 1' )
            print( 'Maple is installed.' )
        except:
            print( 'Maple is NOT installed.' )
            gen = get_genus( pol )
            print( gen )
            assert gen == -3
            return

        gen = get_genus( pol )
        print( gen )
        assert gen == 1
コード例 #16
0
ファイル: orb_product.py プロジェクト: niels-lubbes/orbital
def get_orb_bp_tree( pmz_lst ):
    '''
    Parameters
    ----------
    pmz_lst : list
        A list of 9 elements p0,...,p8 in QQ[c0,s0,c1,s1]
        such that -p0^2+p1^2+...+p8^2==0.
        Some of the polynomials can be equal to zero. 
        The list should represent a parametrization:
            S^1xS^1--->S^7.
        Here (c0,s0) is a points on S^1 such that
        thus c0^2+s0^2-1==0. Similarly for (c1,s1).
                                                                                 
    Returns
    -------
    linear_series.BasePointTree
        Base points of a parametrizing map given by the composition:
            P^1xP^1---->S^1xS^1--->S^7--->S^n          
        with 2<=n<=7. The composition of the latter two maps 
        are defined by omitting the zero polynomials from "pmz_lst". 
    '''

    # setup dictionary for reparametrization'
    #
    c0, s0, c1, s1 = OrbRing.coerce( 'c0,s0,c1,s1' )
    dct1 = {}
    dct1[c0] = '2*t0*t1/(t0^2+t1^2)'
    dct1[s0] = '(-t0^2+t1^2)/(t0^2+t1^2)'
    dct1[c1] = '2*v0*v1/(v0^2+v1^2)'
    dct1[s1] = '(-v0^2+v1^2)/(v0^2+v1^2)'
    for key in dct1: dct1[key] = OrbRing.coerce( dct1[key] )

    # apply reparametrization and multiply out denominators
    # where we only consider non-zero entries
    #
    ps_lst = [ pmz for pmz in pmz_lst if pmz != 0 ]
    gcm1 = OrbRing.coerce( '(t0^2+t1^2)*(v0^2+v1^2)' )
    ps_lst = [ OrbRing.coerce( ps.subs( dct1 ) * gcm1 ) for ps in ps_lst ]

    # ensure that polynomials are co-prime
    #
    gcd1 = sage_gcd( ps_lst )
    ps_lst = [ OrbRing.coerce( ps / gcd1 ) for ps in ps_lst ]
    OrbTools.p( 'gcd =', gcd1 )
    OrbTools.p( 'ps_lst =', ps_lst )

    # Verify whether "ps_lst" represents a map P^1xP^1--->S^n
    # where "n==len(ps_lst)".
    #
    sum1 = sum( [-ps_lst[0] ** 2] + [ ps ** 2 for ps in ps_lst[1:] ] )
    OrbTools.p( 'sum =', sum1 )
    if sum1 != 0:
        warnings.warn( 'Warning: Not parametrization of surface in S^7: ' + str( sum1 ), )

    # set coordinates x,y,v,w
    #
    t0, t1, v0, v1 = OrbRing.coerce( 't0,t1,v0,v1' )
    dct2 = {}
    dct2[t0] = sage_var( 'x' )
    dct2[t1] = sage_var( 'y' )
    dct2[v0] = sage_var( 'v' )
    dct2[v1] = sage_var( 'w' )
    xyvw_lst = [ str( ps.subs( dct2 ) ) for ps in ps_lst ]

    #
    # Compute base point tree using "linear_series" package
    #
    ls = LinearSeries( xyvw_lst, PolyRing( 'x,y,v,w', True ) )
    bp_tree = ls.get_bp_tree()
    OrbTools.p( ls )
    OrbTools.p( bp_tree )

    return bp_tree
コード例 #17
0
ファイル: orb_matrices.py プロジェクト: niels-lubbes/orbital
def get_tmat(t_str=None):
    '''
    Parameters
    ----------
    t_str : string 
        A String with either one of the following 3 formats:
            * A string with format:
                'T[#,#,#,#,#,#,#]'
              where # are in "OrbRing.num_field".
            * 'tT'.
            * "None".
    
    Returns
    -------
    sage_matrix
        A 9x9 matrix defined over "OrbRing.num_field" representing an 
        Euclidean translation of S^7. This map is obtained as the composition 
        of a stereographic projection with center 
            (1:0:0:0:0:0:0:0:1), 
        an Euclidean translation in R^7, and the inverse stereographic projection.
        If "t_str==None", then the entries of the translation matrix are indeterminates  
        t1,...,t7 in "OrbRing.R".          
        If "t_str=='tT'", then the indeterminates are set to [c0,s0,0,0,0,0,0]. 
        Thus the translations along a circle.
    '''

    t = OrbRing.coerce('[t1,t2,t3,t4,t5,t6,t7]')

    # construct a translation matrix with undetermined
    # translations in t1,...,t7
    a = (sage_QQ(1) / 2) * sum([ti**2 for ti in t])
    mat = []
    mat += [[1 + a] + list(t) + [-a]]
    for i in range(0, 7):
        mat += [[t[i]] + sage_identity_matrix(OrbRing.R, 7).row(i).list() +
                [-t[i]]]
    mat += [[a] + list(t) + [1 - a]]

    if t_str == None:
        # return matrix with indeterminates
        return sage_matrix(OrbRing.R, mat)

    elif t_str == 'tT':
        # translations along a circle
        c0, s0 = OrbRing.coerce('c0,s0')
        q = [c0, s0, 0, 0, 0, 0, 0]

    else:
        # Substitute coordinates [#,#,#,#,#,#,#]
        # for the t0,...,t7 variables.
        q = sage__eval(t_str[1:])
        if len(q) != 7:
            raise ValueError('Expect 7 translation coordinates: ', t_str)

    # substitute q for t
    smat = []
    for row in mat:
        srow = []
        for col in row:
            srow += [col.subs({t[i]: q[i] for i in range(7)})]
        smat += [srow]

    if t_str == 'tT':
        return sage_matrix(OrbRing.R, smat)
    else:
        return sage_matrix(OrbRing.num_field, smat)
コード例 #18
0
 def test__coerce(self):
     assert OrbRing.coerce('x8+v8+s1+c1+t7') in OrbRing.R
コード例 #19
0
ファイル: orb_product.py プロジェクト: niels-lubbes/orbital
def get_sing_lst( pol, probable = True ):
    '''
    The method requires that the magma-command 
    is in "os.environ['PATH']".    
    See [http://magma.maths.usyd.edu.au/magma/].
    
    Parameters
    ----------
    pol : OrbRing.R       
        A homogeneous polynomial in QQ[x0,x1,x2,x3].
        
    probable : boolean
        If True, performs a non-deterministic version of a 
        radical decomposition algorithm, which is faster.
        The correctness of output is not guaranteed in this case.
    
    Returns
    -------
    list
        Suppose that X is the surface defined by the zero-set of "pol".
        The output is a list           
            [ (<I>, <H>), ... ]          
        where <I> is the ideal of a component in singular locus of X, 
        and <H> is the Hilbert polynomial of this ideal.
        If Magma is not accessible, then the empty-list [] is returned.
        
    '''
    x0, x1, x2, x3 = OrbRing.coerce( 'x0,x1,x2,x3' )
    df_str = str( [sage_diff( pol, x0 ), sage_diff( pol, x1 ), sage_diff( pol, x2 ), sage_diff( pol, x3 )] )[1:-1]

    OrbTools.p( df_str )

    mi = ''
    mi += 'P<x0,x1,x2,x3> := PolynomialRing(RationalField(), 4);\n'
    mi += 'MI := ideal< P |' + df_str + '>;\n'

    if probable:
        mi += 'MD := ProbableRadicalDecomposition( MI );\n'
    else:
        mi += 'MD := RadicalDecomposition( MI );\n'
    mi += '#MD;\n'

    try:
        mo1 = int( sage_magma.eval( mi ) )
    except:
        return []

    sing_lst = []
    Ry = sage_PolynomialRing( OrbRing.num_field, sage_var( 'y0,y1,y2,y3' ), order = 'degrevlex' )
    for idx in range( mo1 ):

        comp = str( sage_magma.eval( 'Basis(MD[' + str( idx + 1 ) + ']);\n' ) )
        comp = comp.replace( '\n', '' )

        # compute hilbert polynomial of component in singular locus
        compy = sage__eval( comp.replace( 'x', 'y' ), Ry.gens_dict() )
        idy = Ry.ideal( compy )
        hpol = idy.hilbert_polynomial()

        sing_lst += [( comp, hpol )]
        OrbTools.p( idx, sing_lst[-1] )

    OrbTools.p( sing_lst )

    return sing_lst
コード例 #20
0
ファイル: povray_aux.py プロジェクト: niels-lubbes/orbital
def get_curve_lst( pin, fam ):
    '''
    Parameters
    ----------
    pin : PovInput
        The following attributes of the PovInput object are used:
        * "pin.pmz_dct"
        * "pin.scale"
        * "pin.curve_dct"
        * "pin.curve_lst_dct"
                                         
    fam : string 
        A key string for a family id (eg. 'A').
        
    Returns
    -------
    list
        Returns a list of lists of points. Each list of points
        defines points on a curve. v1_lstD
        
        Returns "pin.curve_lst_dct[<fam>]"  if 
            "pin.curve_lst_dct[<fam>]!=None". 
    
        Otherwise let us assume w.l.o.g. that "fam=='A'"
        such that "pin.curve_lst_dct['A']==None".          
        
        We set "pin.curve_lst_dct['A']" as follows:
            pin.curve_lst_dct['A'] = [ <curveA<0>>, <curveA<1>>, ... ]            
        where           
          * <curveA<n>> is a list of points 
                [x,y,z] 
            on a curve in family with id 'A', which are 
            scaled with "pin.scale". 
          
          * The space between points in <curveA<n>> is 
            determined by "pin.curve_dct['A']['step0']".

          * The space between <curveA<n>> and <curveA<n+1>> is  
            determined by values in "pin.curve_dct['A']['step1']".

          * The precision of points in <curveA<n>> is 
            determined by values in "pin.curve_dct['A']['prec']".          
          
        Returns pin.curve_lst_dct['A'].
    '''

    OrbTools.p( fam )

    if fam in pin.curve_lst_dct and pin.curve_lst_dct[fam] != None:
        OrbTools.p( 'Already computed ', fam )
        return pin.curve_lst_dct[fam]

    pmz_lst, fam_id = pin.pmz_dct[fam]
    pmz_lst = OrbRing.coerce( pmz_lst )

    # loop through lists of parameter values
    pin.curve_lst_dct[fam] = []
    for v1 in pin.curve_dct[fam]['step1']:
        curve = []
        for v0 in pin.curve_dct[fam]['step0']:

            if fam_id == 0:
                point = get_pmz_value( pmz_lst, v0, v1, pin.curve_dct[fam]['prec'] )
            elif fam_id == 1:
                point = get_pmz_value( pmz_lst, v1, v0, pin.curve_dct[fam]['prec'] )
            else:
                raise ValueError( 'Expect pin.pmz_dct[fam][1] in [0,1]: ', fam_id )

            # add points to curve if map is defined
            if point != None:
                point = [ coord * pin.scale for coord in point  ]
                curve += [point]


        # need at least 3 points for cubic interpolation
        if len( curve ) >= 3:

            # add curve to family
            pin.curve_lst_dct[fam] += [curve]

    return pin.curve_lst_dct[fam]
コード例 #21
0
ファイル: orb_product.py プロジェクト: niels-lubbes/orbital
def get_project( pol_lst, pmat ):
    '''
    Parameters
    ----------
    pol_lst : list<OrbRing.R> 
        A list of homogeneous polynomials in QQ[x0,...,x8].
    
    pmat : sage_matrix    
        A matrix defined over the rationals QQ.    
    
    Returns
    -------
    tuple
        A 2-tuple of polynomials:        
        * a homogeneous polynomial F in QQ[x0,x1,x2,x3].             
        * F(1,x,y,z) in QQ[x,y,z] (affine polynomial)
    '''

    Ry = sage_PolynomialRing( sage_GF( 2 ), sage_var( 'y0,y1,y2,y3,y4,y5,y6,y7,y8' ), order = 'degrevlex' )
    v = OrbRing.coerce( '[v0,v1,v2,v3,v4,v5,v6,v7,v8]' )
    x = OrbRing.coerce( '[x0,x1,x2,x3,x4,x5,x6,x7,x8]' )
    vx_dct = {v[i]:x[i] for i in range( 9 )}

    OrbTools.p( "\n" + str( pmat ) )

    tries = 0
    projected = False
    while not projected:

        # obtain the linear equations of the projection map
        pmat = sage_matrix( OrbRing.R, list( pmat ) )
        leq_lst = list( pmat * sage_vector( x ) )

        # compute the image of this projection map
        proj_lst = [ v[i] - leq_lst[i] for i in range( len( leq_lst ) ) ]
        p_lst = sage_ideal( pol_lst + proj_lst ).elimination_ideal( x ).gens()

        # obtain a polynomial in x0,...,x8
        p_lst = [p.subs( vx_dct ) for p in p_lst]
        fx = p_lst[0]

        tries += 1
        if len( fx.variables() ) < 4 or len( p_lst ) != 1:

            pmat = get_pmat( True )

            if tries % 100 == 0:
                OrbTools.p( 'tries =', tries, p_lst )

            if tries == 1000:
                return -1
        else:
            projected = True

    w0, w1, w2, w3 = fx.variables()
    fx = fx.subs( {w0:x[0], w1:x[1], w2:x[2], w3:x[3]} )

    x0, x1, x2, x3 = OrbRing.coerce( 'x0,x1,x2,x3' )
    x, y, z = sage_var( 'x,y,z' )
    fxyz = fx.subs( {x0:1, x1:x, x2:y, x3:z} )

    OrbTools.p( fx )
    OrbTools.p( fxyz )

    return fx, fxyz
コード例 #22
0
ファイル: orb_matrices.py プロジェクト: niels-lubbes/orbital
def get_mat(A_str, B_str, C_str):
    '''
    Parameters
    ----------
    A_str : string 
        
        A string of either one of the following forms:                            
        
            'O****'
            'tT'                  
            'T[#,#,#,#,#,#,#]'                   
            'R****[%,%,%,%]'                   
            'I'                   
            'P1'                  
            'P0'
            'M<list of a 9x9 matrix>'
            'E[$,$,$,$,$,$,$,$]'
            'E'
            'X[%,%,%]'
        
        where:                          
            
            *-symbol is a place holder for one of the following characters: 
              r,s,m,p,a                                       
            
            #-symbol denotes an element of "OrbRing.num_field".                     
            
            %-symbol denotes an integer in [0,360].
            
            $-symbol denotes an integer in [1,8] such that each
              integer occurs only once. For example 'E[2,1,3,4,5,6,7,8]'
              is correct, but 'E[1,1,3,4,5,6,7,8]' is incorrect.
                     
    B_str : string 
        Same specs as "A_str".
        
    C_str : string        
       Same specs as "A_str".  
    
    Returns
    -------
    sage_matrix
        Let matrix A over QQ[c0,s0,c1,s1] be defined as follows,
        where we make a case distinction on "A_str":
              
             "A_str[0] == 'O' " : "A = get_omat( A_str )".
             "A_str[0] == 'T' " : "A = get_tmat( A_str )".
             "A_str[0] == 'E' " : "A = get_emat( A_str )".
             "A_str[0] == 'X' " : "A = get_xmat( A_str )".  
             "A_str    == 'tT'" : "A = get_tmat('tT')".
             "A_str[0] == 'R' " : "A = get_rmat( A_str )".
             "A_str    == 'I' " : "A = sage_identity_matrix(9,9)".      
             "A_str    == 'P1'" : "A = get_pmat( True )".
             "A_str    == 'P0'" : "A = get_pmat( False )".
             "A_str[0] == 'M' " : "A = sage_matrix(<list of a matrix>)".
          
          Similarly, we obtain matrices B and C.          
          We return the matrix A*B*C.
    '''

    M_lst = []
    for M_str in [A_str, B_str, C_str]:

        if M_str[0] == 'O': M_lst += [get_omat(M_str)]
        elif M_str[0] == 'T': M_lst += [get_tmat(M_str)]
        elif M_str[0] == 'E': M_lst += [get_emat(M_str)]
        elif M_str[0] == 'X': M_lst += [get_xmat(M_str)]
        elif M_str == 'tT': M_lst += [get_tmat('tT')]
        elif M_str[0] == 'R': M_lst += [get_rmat(M_str)]
        elif M_str == 'I':
            M_lst += [sage_identity_matrix(OrbRing.num_field, 9, 9)]
        elif M_str == 'P1':
            M_lst += [get_pmat(True)]
        elif M_str == 'P0':
            M_lst += [get_pmat(False)]
        elif M_str[0] == 'M':
            mat_lst = OrbRing.coerce(M_str[1:])
            M_lst += [sage_matrix(mat_lst)]

    return M_lst[0] * M_lst[1] * M_lst[2]
コード例 #23
0
 def test__get_emb_dim( self ):
     imp_lst = OrbRing.coerce( '[-x0^2+x1^2+x2^2+x3^2+x4^2+x5^2+x6^2+x7^2+x8^2, x8, x7, x6, x5, x1*x2-x0*x4]' )
     emb = get_emb_dim( imp_lst )
     print( emb )
     assert emb == 3
コード例 #24
0
    def test__get_deg_dim_2( self ):

        imp_lst = OrbRing.coerce( '[-x0^2+x1^2+x2^2+x3^2+x4^2+x5^2+x6^2+x7^2+x8^2, x8, x7, x6, x5, x4, x3]' )
        deg_dim = get_deg_dim( imp_lst )
        print( deg_dim )
        assert deg_dim == ( 2, 1 )
コード例 #25
0
def quadric_smooth():
    '''
    Construct povray image of rulings on hyperboloid of one sheet.
    '''

    # construct the two rulings on the hyperboloid
    # by rotating lines L1 and L2
    c0, s0, c1, s1, t0 = OrbRing.coerce('c0,s0,c1,s1,t0')
    P = sage_vector([-2, -1, -0.5])
    Q = sage_vector([2, -1, -0.5])
    L0 = t0 * P + (t0 - 1) * Q
    L1 = t0 * Q + (t0 - 1) * P
    M = sage_matrix([(c1, s1, 0), (-s1, c1, 0), (0, 0, 1)])
    pmz_A_lst = [1] + list(M * L0)
    pmz_B_lst = [1] + list(M * L1)

    OrbTools.p('pmz_A_lst =', pmz_A_lst)
    for pmz in pmz_A_lst:
        OrbTools.p('\t\t', pmz)

    OrbTools.p('pmz_B_lst =', pmz_B_lst)
    for pmz in pmz_B_lst:
        OrbTools.p('\t\t', pmz)

    # PovInput ring cyclide
    #
    pin = PovInput()

    pin.path = './' + get_time_str() + '_quadric_smooth/'
    pin.fname = 'orb'
    pin.scale = 1
    pin.cam_dct['location'] = (0, -10, 0)
    pin.cam_dct['lookat'] = (0, 0, 0)
    pin.cam_dct['rotate'] = (0, 0, 0)
    pin.shadow = True
    pin.light_lst = [(0, 0, -5), (0, -5, 0), (-5, 0, 0), (0, 0, 5), (0, 5, 0),
                     (5, 0, 0)]
    pin.axes_dct['show'] = False
    pin.axes_dct['len'] = 1.2

    pin.width = 400
    pin.height = 800
    pin.quality = 11
    pin.ani_delay = 10

    pin.impl = None

    pin.pmz_dct['A'] = (pmz_A_lst, 0)
    pin.pmz_dct['B'] = (pmz_B_lst, 0)
    pin.pmz_dct['FA'] = (pmz_A_lst, 0)
    pin.pmz_dct['FB'] = (pmz_B_lst, 0)

    v0_lst = [sage_QQ(i) / 10 for i in range(-15, 30, 5)]  # -15, 35
    v1_lst = [(sage_QQ(i) / 180) * sage_pi for i in range(0, 360, 36)]
    v1_lst_F = [(sage_QQ(i) / 180) * sage_pi for i in range(0, 360, 2)]

    pin.curve_dct['A'] = {
        'step0': v0_lst,
        'step1': v1_lst,
        'prec': 10,
        'width': 0.1
    }
    pin.curve_dct['B'] = {
        'step0': v0_lst,
        'step1': v1_lst,
        'prec': 10,
        'width': 0.1
    }
    pin.curve_dct['FA'] = {
        'step0': v0_lst,
        'step1': v1_lst_F,
        'prec': 10,
        'width': 0.01
    }
    pin.curve_dct['FB'] = {
        'step0': v0_lst,
        'step1': v1_lst_F,
        'prec': 10,
        'width': 0.01
    }

    col_A = (0.5, 0.0, 0.0, 0.0)  # red
    col_B = rgbt2pov((28, 125, 154, 0))  # blue

    pin.text_dct['A'] = [True, col_A, 'phong 0.2 phong_size 5']
    pin.text_dct['B'] = [True, col_B, 'phong 0.2 phong_size 5']
    pin.text_dct['FA'] = [True, (0.1, 0.1, 0.1, 0.0), 'phong 0.2 phong_size 5']
    pin.text_dct['FB'] = [True, (0.1, 0.1, 0.1, 0.0), 'phong 0.2 phong_size 5']

    # raytrace image/animation
    create_pov(pin, ['A', 'B', 'FA', 'FB'])
コード例 #26
0
    def test__get_deg_dim_3( self ):

        imp_lst = OrbRing.coerce( '[-x0^2+x1^2+x2^2+x3^2+x4^2+x5^2+x6^2+x7^2+x8^2, x8, x7, x6, x5, x1*x2-x0*x4]' )
        deg_dim = get_deg_dim( imp_lst )
        print( deg_dim )
        assert deg_dim == ( 4, 2 )
コード例 #27
0
def get_imp(A, B, prj, sng, snp):
    '''
    Computes implicit equation of a stereographic projection S of 
    the pointwise Hamiltonian product of circles in the sphere S^3 
    defined by transformations of the standard circle [1,cos(a),sin(a),0,0]
    by A and B respectively.     
        
    Parameters
    ----------
    A : sage_Matrix<sage_QQ>
        Represents a linear transformation S^3--->S^3
    
    B : sage_Matrix<sage_QQ>
        Represents a linear transformation S^3--->S^3
    
    prj : int
        Choice for stereographic projection S^3--->P^3: 
        0: (x0:x1:x2:x3:x4) |--> (x0-x4:x1:x2:x3)
        1: (x0:x1:x2:x3:x4) |--> (x0-x1:x4:x2:x3)
        2: (x0:x1:x2:x3:x4) |--> (x0-x2:x1:x4:x3)
        3: (x0:x1:x2:x3:x4) |--> (x0-x3:x1:x2:x4)
    
    sng : boolean
        If true computes singular locus of S. Needs Magma path set
        in os.environ['PATH']. Otherwise the empty-list is returned.

    snp : boolean
        If true and if sng is True, then the singular locus is 
        computed with a probablistic method, which is faster but
        the correctness of the output is not guaranteed.
        
    Returns
    -------
    dict
        {   
            'Agreat' : boolean
                If True, then circle A is great.
                
            'Bgreat' : boolean
                If True, then circle B is great.
            
            'eqn_x'  : sage_PolynomialRing
                Equation of S in x0,...,x3

            'eqn_str':
                Formatted equation in x0,...,x3 of the 
                form f(x1:x2:x3)+x0*g(x0:x1:x2:x3).
            
            'eqn_xyz':
                Equation of S in x,y,z
                        
            'sng_lst':
                Empty-list if Magma is not installed or 
                list of singularities of S otherwise.
        }
        
    '''

    dct = {}  # output

    # create polynomial ring
    #
    R = sage_PolynomialRing(sage_QQ,
                            'x0,x1,x2,x3,a0,a1,a2,a3,a4,b0,b1,b2,b3,b4')
    x0, x1, x2, x3, a0, a1, a2, a3, a4, b0, b1, b2, b3, b4 = R.gens()

    # construct ideal for A
    #
    sv = [0, 0, 0, 1, 0]
    tv = [0, 0, 0, 0, 1]
    u0, u1, u2, u3, u4 = list(A * sage_vector(sv))
    v0, v1, v2, v3, v4 = list(A * sage_vector(tv))
    eqA = [-a0**2 + a1**2 + a2**2 + a3**2 + a4**2]
    eqA += [u0 * a0 + u1 * a1 + u2 * a2 + u3 * a3 + u4 * a4]
    eqA += [v0 * a0 + v1 * a1 + v2 * a2 + v3 * a3 + v4 * a4]
    dct['Agreat'] = u0 == v0 == 0

    # construct ideal for B
    #
    u0, u1, u2, u3, u4 = list(B * sage_vector(sv))
    v0, v1, v2, v3, v4 = list(B * sage_vector(tv))
    eqB = [-b0**2 + b1**2 + b2**2 + b3**2 + b4**2]
    eqB += [u0 * b0 + u1 * b1 + u2 * b2 + u3 * b3 + u4 * b4]
    eqB += [v0 * b0 + v1 * b1 + v2 * b2 + v3 * b3 + v4 * b4]
    dct['Bgreat'] = u0 == v0 == 0

    # stereographic projection
    #
    if prj == 0: j, i_lst = 4, [1, 2, 3]
    if prj == 1: j, i_lst = 1, [4, 2, 3]
    if prj == 2: j, i_lst = 2, [1, 4, 3]
    if prj == 3: j, i_lst = 3, [1, 2, 4]

    # construct equation of for projection of A*B
    #
    c = c0, c1, c2, c3, c4 = get_hp_P4([a0, a1, a2, a3, a4],
                                       [b0, b1, b2, b3, b4])
    x = [x0, x1, x2, x3]
    i1, i2, i3 = i_lst
    id = [x[0] -
          (c[0] - c[j]), x[1] - c[i1], x2 - c[i2], x3 - c[i3]] + eqA + eqB
    dct['eqn_x'] = eqn_x = R.ideal(id).elimination_ideal(
        [a0, a1, a2, a3, a4, b0, b1, b2, b3, b4]).gens()[0]

    # get equation in string form
    #
    f = eqn_x.subs({x0: 0})
    dct['eqn_str'] = str(sage_factor(f)) + '+' + str(sage_factor(eqn_x - f))
    xs, ys, zs = sage_var('x,y,z')
    dct['eqn_xyz'] = sage_SR(eqn_x.subs({x0: 1, x1: xs, x2: ys, x3: zs}))

    # compute singular locus
    #
    dct['sng_lst'] = []
    if sng:
        dct['sng_lst'] = get_sing_lst(OrbRing.coerce(eqn_x), snp)

    return dct
コード例 #28
0
def dp8_clifford():
    '''    
    Construct povray image of octic del Pezzo surface in S^3.
    The surface is created as the Clifford translation of a
    great circle along a little circle.        
    '''

    # construct surface as pointwise hamiltonian product of
    # two circles in S^3
    #
    T = get_trn_S3([0, 0, 0])
    R = get_rot_S3(6 * [0])
    S = get_scale_S3(1)
    A = S * R * T

    q32 = sage_QQ(3) / 2
    T = get_trn_S3([q32, 0, 0])
    R = get_rot_S3(6 * [0])
    S = get_scale_S3(1)
    B = S * R * T

    c0, s0, c1, s1 = OrbRing.coerce('c0,s0,c1,s1')
    u = list(A * sage_vector([1, c0, s0, 0, 0]))
    v = list(B * sage_vector([1, c1, s1, 0, 0]))
    p = get_hp_P4(u, v)
    pmz_AB_lst = [p[0] - p[4], p[1], p[2], p[3]]

    for pmz in pmz_AB_lst:
        OrbTools.p('\t\t', sage_factor(pmz))

    # PovInput dp8 clifford
    #
    pin = PovInput()

    pin.path = './' + get_time_str() + '_dp8_clifford/'
    pin.fname = 'orb'
    pin.scale = 1
    pin.cam_dct['location'] = (0, 0, 4)
    pin.cam_dct['lookat'] = (0, 0, 0)
    pin.cam_dct['rotate'] = (0, 0, 0)
    pin.shadow = True
    pin.light_lst = [(0, 0, -10), (0, -10, 0), (-10, 0, 0), (0, 0, 10),
                     (0, 10, 0), (10, 0, 0)]
    pin.axes_dct['show'] = False
    pin.axes_dct['len'] = 1.2
    pin.height = 400
    pin.width = 800
    pin.quality = 11
    pin.ani_delay = 10

    pin.impl = None

    pin.pmz_dct['A'] = (pmz_AB_lst, 0)
    pin.pmz_dct['B'] = (pmz_AB_lst, 1)

    pin.pmz_dct['FA'] = (pmz_AB_lst, 0)
    pin.pmz_dct['FB'] = (pmz_AB_lst, 1)

    v0_lst = [(sage_QQ(i) / 180) * sage_pi for i in range(0, 360, 5)]
    v1_lst_A = [(sage_QQ(i) / 180) * sage_pi for i in range(0, 180, 10)]
    v1_lst_A += [(sage_QQ(i) / 180) * sage_pi for i in range(180, 360, 20)]
    v1_lst_B = [(sage_QQ(i) / 180) * sage_pi for i in range(0, 360, 10)]

    v1_lst_FA = [(sage_QQ(i) / 180) * sage_pi for i in range(0, 180, 1)]
    v1_lst_FA += [(sage_QQ(i) / 180) * sage_pi for i in range(180, 360, 2)]
    v1_lst_FB = [(sage_QQ(i) / 180) * sage_pi for i in range(0, 360, 1)]

    pin.curve_dct['A'] = {
        'step0': v0_lst,
        'step1': v1_lst_A,
        'prec': 10,
        'width': 0.04
    }
    pin.curve_dct['B'] = {
        'step0': v0_lst,
        'step1': v1_lst_B,
        'prec': 10,
        'width': 0.04
    }
    pin.curve_dct['FA'] = {
        'step0': v0_lst,
        'step1': v1_lst_FA,
        'prec': 10,
        'width': 0.02
    }
    pin.curve_dct['FB'] = {
        'step0': v0_lst,
        'step1': v1_lst_FB,
        'prec': 10,
        'width': 0.02
    }

    col_A = (0.6, 0.4, 0.1, 0.0)
    col_B = (0.1, 0.15, 0.0, 0.0)
    colFF = (0.1, 0.1, 0.1, 0.0)
    pin.text_dct['A'] = [True, col_A, 'phong 0.2 phong_size 5']
    pin.text_dct['B'] = [True, col_B, 'phong 0.2 phong_size 5']
    pin.text_dct['FA'] = [True, colFF, 'phong 0.2 phong_size 5']
    pin.text_dct['FB'] = [True, colFF, 'phong 0.2 phong_size 5']

    # raytrace image/animation
    create_pov(pin, ['A', 'B'])
    create_pov(pin, ['A', 'B', 'FA', 'FB'])
    create_pov(pin, ['A', 'FA', 'FB'])
    create_pov(pin, ['B', 'FA', 'FB'])