Calculus of Fano varieties associated to a root system.

Alvaro Rittatore & Pierre-Louis Montagard

This computations here are more "brutal" than in a last version of the paper: indeed, we do not use here the results of Khare on the description of the faces of the Weyl Polytopes.

In [1]:
import numpy as np

Please introduce the type of the root system ( $A$, $B$, $C$, $D$, $E$, $F$ or $G$ ) in the first argument of the following function.

In [2]:
Type='F'

Please introduce the rank of the root system

In [3]:
n=4

We initialize several auxiliar lists.

In [4]:
OrbitsList=[[] for i in range(2^n-1) ];
OrbitsListQQ=list([[] for i in range(2^n-1) ]);
ConeList=[[] for i in range(2^n-1)];
RaysConeList=[[] for i in range(2^n-1)]; 
AffSpaceList=[[] for i in range(2^n-1)]; 
RankList=[0 for i in range(2^n-1)]; 
MatAffSpaceList=[[] for i in range(2^n-1)];  
NormalList=[[0 for i in range(n)] for j in range(2^n-1)] ; 
VectDomList=[[] for i in range(2^n-1)];
CaseList=[[[],[],[],[],[]] for i in range(2^n-1)]
table=np.dtype([('Dominant Weights',object),('Normal vector',object),('Fano',bool),('Smooth',bool),('Gorenstein',bool)])
CaseList=np.empty(shape=(2^n-1,1),dtype=table)

we create the list of dominant weights with coordinates 1 or 0 (and eliminate the null vector) This list parametrize the set $L^c$.

In [5]:
List=list(VectorSpace(GF(2),n));
for l in range(2^n-1):
    VectDomList[l]=list(vector(QQ,List[l+1]))
    VectDomListNP=np.array(VectDomList)
    CaseList[l,0][0]=vector(QQ,List[l+1])

To verify the convention, we print the Dynkin diagram associated and the numerotation of vertices.

In [6]:
R=RootSystem([Type,n]);
R.dynkin_diagram()
Out[6]:
O---O=>=O---O
1   2   3   4   
F4

For each elements in $L^c$, we compute orbits of fundamental weights.

In [7]:
P_lattice=R.weight_space()
W=P_lattice.weyl_group()
gensW=np.array((W.simple_reflections()))
for l in range(2^n-1):
    L=VectDomListNP[l]
    gensW_L=set(gensW[L==0])
    res=set(P_lattice.fundamental_weights())
    new=res
    while len(new)>0: 
            for w in gensW_L:
                for v in res:  
                    new=new.union({w.action(v)})
            new=new.difference(res)
            res=res.union(new)
    OrbitsList[l]=list(res)        

We convert the elements of orbits of fundamental weights in vector over $\mathbb{Q}$.

In [8]:
for l in range(2^n-1):
    OrbitsListQQ[l]=[[] for i in range(len(OrbitsList[l]))]
    for u in range(len(OrbitsList[l])):
        OrbitsListQQ[l][u]=vector(QQ,OrbitsList[l][u])

For each element of orbitslambdalist, we compute the convex cone $\sigma_\lambda$, the rays of this cone, the affine space generated by the elements of $Prim(\sigma_\lambda)$ and its dimension.

In [9]:
for i in range(2^n-1):
        # cone calculation
    orbit=OrbitsListQQ[i]
    cone=Cone(orbit)
    ConeList[i]=cone
    # rays calculation
    rays=cone.rays()
    print(VectDomList[i])
    print("rays")
    print(rays)
    RaysConeList[i]=rays
    # affine space  calculation
    s=len(rays)
    AffSpace=[[] for j in range(s-1)]
    for j in range(1,s):
        direction=list(rays[j]-rays[0])
        AffSpace[j-1]=direction
        AffSpace[j-1]
    AffSpaceList[i]=AffSpace
    MatrixAffSpace=matrix(QQ,AffSpace)
    rank=MatrixAffSpace.rank()
    RankList[i]=rank
    MatAffSpaceList[i]=MatrixAffSpace
[1, 0, 0, 0]
rays
N(0,  0,  0,  1),
N(0,  0,  1, -1),
N(0,  1, -1,  0),
N(1, -1,  1,  0),
N(1,  0, -1,  1),
N(1,  0,  0, -1)
in 4-d lattice N
[0, 1, 0, 0]
rays
N(-1, 1,  0,  0),
N( 0, 0,  0,  1),
N( 0, 0,  1, -1),
N( 0, 1, -1,  0),
N( 1, 0,  0,  0)
in 4-d lattice N
[1, 1, 0, 0]
rays
N(0, 0,  0,  1),
N(0, 0,  1, -1),
N(0, 1, -1,  0),
N(1, 0,  0,  0)
in 4-d lattice N
[0, 0, 1, 0]
rays
N( 1,  0, 0,  0),
N(-1,  1, 0,  0),
N( 0, -1, 2,  0),
N( 0,  0, 0,  1),
N( 0,  0, 1, -1)
in 4-d lattice N
[1, 0, 1, 0]
rays
N(0,  0, 0,  1),
N(0,  0, 1, -1),
N(0,  1, 0,  0),
N(1, -1, 2,  0),
N(1,  0, 0,  0)
in 4-d lattice N
[0, 1, 1, 0]
rays
N(-1, 1, 0,  0),
N( 0, 0, 0,  1),
N( 0, 0, 1, -1),
N( 1, 0, 0,  0)
in 4-d lattice N
[1, 1, 1, 0]
rays
N(0, 0, 0,  1),
N(0, 0, 1, -1),
N(0, 1, 0,  0),
N(1, 0, 0,  0)
in 4-d lattice N
[0, 0, 0, 1]
rays
N( 1,  0,  0, 0),
N( 1, -1,  0, 2),
N(-1,  0,  0, 2),
N( 0,  1, -2, 2),
N( 0, -1,  2, 0),
N(-1,  1,  0, 0)
in 4-d lattice N
[1, 0, 0, 1]
rays
N(1,  0,  0, 0),
N(1,  1, -2, 2),
N(0,  1, -1, 1),
N(1,  0, -1, 2),
N(0,  1,  0, 0),
N(0,  0,  0, 1),
N(0,  0,  1, 0),
N(1, -1,  2, 0),
N(2, -1,  0, 2),
N(1, -1,  1, 1)
in 4-d lattice N
[0, 1, 0, 1]
rays
N(-1, 1,  0, 0),
N( 0, 0,  0, 1),
N( 0, 0,  1, 0),
N( 0, 1, -1, 1),
N( 1, 0,  0, 0)
in 4-d lattice N
[1, 1, 0, 1]
rays
N(0, 1, -1, 1),
N(0, 1,  0, 0),
N(0, 0,  0, 1),
N(0, 0,  1, 0),
N(1, 0,  0, 0)
in 4-d lattice N
[0, 0, 1, 1]
rays
N( 1,  0, 0, 0),
N(-1,  1, 0, 0),
N( 0, -1, 2, 0),
N( 0,  0, 0, 1)
in 4-d lattice N
[1, 0, 1, 1]
rays
N(0,  1, 0, 0),
N(0,  0, 0, 1),
N(0,  0, 1, 0),
N(1,  0, 0, 0),
N(1, -1, 2, 0)
in 4-d lattice N
[0, 1, 1, 1]
rays
N(-1, 1, 0, 0),
N( 0, 0, 0, 1),
N( 0, 0, 1, 0),
N( 1, 0, 0, 0)
in 4-d lattice N
[1, 1, 1, 1]
rays
N(0, 0, 1, 0),
N(1, 0, 0, 0),
N(0, 1, 0, 0),
N(0, 0, 0, 1)
in 4-d lattice N

We compute the matrix which gives the scalar product in the fundamental weights basis.

In [10]:
ScalarProdMatrix=matrix(QQ,((((CartanType([Type,n]).dual()).cartan_matrix()).symmetrized_matrix())^(-1)))
ScalarProdMatrix
Out[10]:
[  2   3   2   1]
[  3   6   4   2]
[  2   4   3 3/2]
[  1   2 3/2   1]

If the affine space $\langle Prim(\sigma_{\lambda})\rangle_{\mathbb R}$ has dimension $(n-1)$, we compute the normal of this space.

In [11]:
for i in range (0,2^n-1):
     if RankList[i]==n-1:
          A=MatAffSpaceList[i]*ScalarProdMatrix
          basis=A.right_kernel().basis()
          vectbasis=(basis[0])
          NormalList[i]=vectbasis
          CaseList[i,0][1]=vectbasis
print('done')
done

Convert some list in Numpy to test if the normal of the affine space $\langle Prim(\sigma_{\lambda})\rangle_{\mathbb R}$ belongs to the interior $\sigma_{\lambda})$. For this, we test first if the affine space is of dimension $n-1$, then if the coordinates of the normal are non negative and finally if this normal vector have the same nul coordinate as the dominant weight $\lambda$. We put the result in CaseList.

In [12]:
NormalListNP=np.array(NormalList)
In [13]:
for i in range(0,2^n-1):
    if RankList[i]==n-1 and np.all(NormalListNP[i]>=0) and np.all((VectDomListNP[i]==0)+(NormalListNP[i]!=0))==True:
        CaseList[i,0][2]=True
    else:  CaseList[i,0][2]=False
    

We test if the cone $\sigma_\lambda$ is smooth (and so the toric variety of fan $\Sigma_\lambda$. We put the result in CaseList.

In [14]:
for i in range(0,2^n-1):
     if ConeList[i].is_smooth():
           CaseList[i,0][3]=True
     else: CaseList[i,0][3]=False

If $\varphi_\lambda$ is the linear form such $\varphi_\lambda(\langle Prim(\sigma_{\lambda})\rangle_{\mathbb R}=1$, we test when $\varphi_\lambda$ is an integer linear form.

In [15]:
TestVector=[[]for i in range(2^n-1)]
TestScalar=[[] for i in range(2^n-1)]
for i in range(2^n-1):
    if CaseList[i,0][2]==True:
        TestScalar[i]=vector(QQ,NormalList[i])*ScalarProdMatrix*vector(RaysConeList[i][0])
        TestVector[i]=matrix(QQ,NormalList[i])
        if all(x in ZZ for x in ((1/TestScalar[i])*TestVector[i]*ScalarProdMatrix).list()):
             CaseList[i,0][4]=True
        else: CaseList[i,0][4]=False      
            

We extract for CaseList the Gorenstein Fano case and we print it. Each row contains the following item:

Dominant weight/Normal Vector/Is Fano?/Is Smooth?/Is Gorenstein?

In [16]:
print(CaseList[CaseList['Fano']==True])
[((1, 0, 0, 0), (1, 0, 0, 0),  True, False,  True)
 ((0, 0, 0, 1), (0, 0, 0, 1),  True, False, False)]