Calculus of Fano varieties associated to a root system.

Alvaro Rittatore & Pierre-Louis Montagard

PLEASE read README.txt file! Be careful: here, the convention for Root System, specially numerotation of simple roots are not the same as Bourbaki, see the page: https://webusers.imj-prg.fr/~jean.michel/gap3/htm/chap085.htm. The 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]:
gap3= Gap3(command='/home/pierre-louis/Boulot/LogicielCalcul/gap3-jm/bin/gap.sh'); #To use gap3, replace by your path 
gap3.load_package('fanofans'); #load fanofans package
from sage.interfaces.gap3 import GAP3Element # GAP3Element allows to push results into gap3 interface
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]:
gap3('"F"',name='Type')
Out[2]:
"F"

Please introduce the rank of the root system

In [3]:
n=4
gap3(n,name='n') #For Gap
Out[3]:
4

We initialize several auxiliar lists.

In [4]:
OrbitsList=[[] 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)];
VectDomListGap=[[] for i in range(2^n-1)];
CaseList=[[[],[],[],[],[]] for i in range(2^n-1)]
Type=np.dtype([('Dominant Weights',object),('Normal vector',object),('Fano',bool),('Smooth',bool),('Gorenstein',bool)])
CaseList=np.empty(shape=(2^n-1,1),dtype=Type)

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]))
    CaseList[l,0][0]=vector(QQ,List[l+1])

For each $\lambda$ we compute orbits of fundamental weights using the GAP3 package fanofans.

In [6]:
for l in range(2^n-1):
    gap3(VectDomList[l],name='v')
    GAP3Element(gap3, value=list(VectDomList[l]), is_name=False, name='ll')
    OrbitsList[l]=gap3('OrbitsFanoGen(ll,CoxeterGroup(Type,n))').sage()
   

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 [7]:
for i in range(0,2^n-1):
        # cone calculation
    orbit=OrbitsList[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(0,  1,  0, 0),
N(1, -1,  2, 0),
N(1,  1, -2, 2),
N(2, -1,  0, 2),
N(0,  0,  1, 0),
N(0,  1, -1, 1),
N(1, -1,  1, 1),
N(1,  0, -1, 2),
N(0,  0,  0, 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(1, 0,  0, 0),
N(0, 1,  0, 0),
N(0, 0,  1, 0),
N(0, 1, -1, 1),
N(0, 0,  0, 1)
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(1,  0, 0, 0),
N(0,  1, 0, 0),
N(1, -1, 2, 0),
N(0,  0, 1, 0),
N(0,  0, 0, 1)
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(1, 0, 0, 0),
N(0, 1, 0, 0),
N(0, 0, 1, 0),
N(0, 0, 0, 1)
in 4-d lattice N

Using GAP, we compute the matrix that gives the scalar product in the fundamental weights basis.

In [8]:
ScalarProdMatrix=matrix(QQ,(gap3('ScalarMatrix(CoxeterGroup(Type,n))')).sage()); 
ScalarProdMatrix
Out[8]:
[ 4  6  4  2]
[ 6 12  8  4]
[ 4  8  6  3]
[ 2  4  3  2]

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

In [9]:
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 [10]:
NormalListNP=np.array(NormalList)
VectDomListNP=np.array(VectDomList)
In [11]:
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 [12]:
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 [13]:
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 [14]:
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)]