jsMath

ptolemy presentation at ICERM

Demonstration of the ptolemy module

Setting:

  • Let M be an orientable 3-manifold with boundary consisting of one or more tori given as ideal triangulation.
  • A representation
    ρ:π1(M)SL(n,)orPSL(n,
    is called boundary-unipotent if each peripheal subgroup is taken into a conjugate of N, the subgroup of unit triangular matrices.

Goal:

Find all boundary-unipotent representations (up to conjugacy)

and compute invariants such as (complex) volume, trace field, ...

Motivation:

  • If M is hyperbolic, then the universal cover M˜ is 3 , the Decktransformations are in Isom+(3)=~PSL(2, and we get a boundary-unipotent PSL(2,-representation called the geometric representation.
  • A lot of invariants associated to the hyperbolic structure generalize to generic boundary-unipotent PSL(n,-representations.

It is all in SnapPy:

from snappy import * 
       

And can be done in just one line, here for complex volumes for m003, PSL(2,:

vols = Manifold("m003").ptolemy_variety(2,'all').compute_solutions().complex_volume_numerical().flatten(2) for vol in vols: print vol 
       
0.E-19 - 0.328986813369645*I
1.88267370443418 E-14 + 0.328986813369648*I
-2.02988321281931 + 3.69387680165811 E-16*I
2.02988321281931 + 3.69387680165811 E-16*I

Note that one of the volumes is the hyperbolic volume:

Manifold("m003").volume() 
       
2.0298832128

And that the trivial volumes are coming from a number field (here trace field) with two real roots:

Manifold("m003").ptolemy_variety(N = 2, obstruction_class = 'all').compute_solutions().number_field() 
       
[[x^2 - x - 1], [x^2 - x + 1]]

But there are also non-trivial "exotic volumes" not coming from the geometric representation:

vols = Manifold("m011").ptolemy_variety(2,'all').compute_solutions().volume_numerical(drop_negative_vols=True).flatten(2) for vol in sorted(vols,key=lambda x:x.real()): print vol 
       
-4.29669320956005 E-16
3.94150857785380 E-15
4.64797471344536 E-15
0.942707362776931
2.78183391239608

Some of them might look familiar:

OrientableClosedCensus[0].volume() 
       
0.94270736278

And we can do this also for PSL(3,:

vols=Manifold("m032").ptolemy_variety(3,'all').retrieve_solutions(numerical=True).volume_numerical().flatten(2) for vol in sorted(vols): print vol 
       
Retrieving solutions from
http://ptolemy.unhyperbolic.org/data/pgl3/OrientableCuspedCensus/04_\
tetrahedra/m032__sl3_c0.magma_out ...
Parsing...
Retrieving solutions from
http://ptolemy.unhyperbolic.org/data/pgl3/OrientableCuspedCensus/04_\
tetrahedra/m032__sl3_c1.magma_out ...
Parsing...
-12.6558529155326
-9.71673302356478
-9.71673302356477
-5.66041958906225
-4.84455411034372
-4.84455411034372
-3.58170732556836
-3.58170732556836
-2.82812208833079
-2.82812208833079
-2.82812208833079
-2.82812208833078
-2.13410408402112 E-14
-1.40700168529961 E-14
-7.12917138517843 E-15
-6.63951857902967 E-15
-6.19144492619572 E-15
-6.09004491801401 E-15
-5.69282034706964 E-15
-4.75872596536475 E-15
-3.09366247897014 E-15
-2.43934646787514 E-15
-2.43278704473160 E-15
-1.63335057284941 E-15
1.63335057284941 E-15
2.43257020429710 E-15
2.43918383754926 E-15
3.09349984864427 E-15
4.75850912493025 E-15
5.69271192685239 E-15
6.09015333823126 E-15
6.19166176663022 E-15
6.63973541946417 E-15
1.40699084327789 E-14
2.82812208833078
2.82812208833079
2.82812208833079
2.82812208833079
3.58170732556836
3.58170732556836
4.84455411034372
4.84455411034372
5.66041958906225
9.71673302356477
9.71673302356478
12.6558529155326

Note that one volume is just 4 times the hyperbolic volume:

4*Manifold("m032").volume() 
       
12.655852915532575

To find the volume of 52 as an exotic PSL(3, volume of 61=~ m032:

Manifold("5_2").volume() 
       

Time to show the database: ptolemy.unhyperbolic.org

Let's break above line into parts...

M=Manifold("m011") 
       

Tab completion is your friend:

M.ptolemy_variety 
       

There is help!

help(M.ptolemy_variety) 
       

Get the Ptolemy variety for SL(2,:

p=M.ptolemy_variety(2) p 
       
Ptolemy Variety for m011, N = 2

These are the equations:

for eqn in p.equations: print eqn 
       
- c_0011_0 * c_0101_1 - c_0011_0^2 - c_0101_1 * c_0101_2
- c_0011_0 * c_0101_1 - c_0011_0^2 - c_0101_1 * c_0101_2
- c_0011_0 * c_0101_1 - c_0101_1^2 + c_0101_2^2
- 1 + c_0011_0

Compute the solutions:

sols=p.compute_solutions() # retrieve_solutions() for getting them from database sols 
       
[{'c_1001_1': Mod(1, x^3 - x^2 + 1), 'c_1001_0': Mod(-x + 1, x^3 -
x^2 + 1), 'c_1001_2': Mod(-x^2 + x, x^3 - x^2 + 1), 'c_0110_1':
Mod(-1, x^3 - x^2 + 1), 'c_0110_0': Mod(x^2 - x, x^3 - x^2 + 1),
'c_0110_2': Mod(x^2 - x, x^3 - x^2 + 1), 'c_1010_2': Mod(-x + 1, x^3
- x^2 + 1), 'c_1010_1': Mod(x - 1, x^3 - x^2 + 1), 'c_1010_0':
Mod(-x^2 + x, x^3 - x^2 + 1), 'c_1100_1': Mod(x^2 - x, x^3 - x^2 +
1), 'c_1100_0': Mod(-1, x^3 - x^2 + 1), 'c_1100_2': Mod(x^2 - x, x^3
- x^2 + 1), 'c_0101_2': Mod(x - 1, x^3 - x^2 + 1), 'c_0101_1':
Mod(x^2 - x, x^3 - x^2 + 1), 'c_0101_0': Mod(-1, x^3 - x^2 + 1),
'c_0011_1': Mod(-1, x^3 - x^2 + 1), 'c_0011_0': Mod(1, x^3 - x^2 +
1), 'c_0011_2': Mod(-1, x^3 - x^2 + 1)}]

Pick one solution:

sol = sols[0] sol 
       
{'c_1001_1': Mod(1, x^3 - x^2 + 1), 'c_1001_0': Mod(-x + 1, x^3 -
x^2 + 1), 'c_1001_2': Mod(-x^2 + x, x^3 - x^2 + 1), 'c_0110_1':
Mod(-1, x^3 - x^2 + 1), 'c_0110_0': Mod(x^2 - x, x^3 - x^2 + 1),
'c_0110_2': Mod(x^2 - x, x^3 - x^2 + 1), 'c_1010_2': Mod(-x + 1, x^3
- x^2 + 1), 'c_1010_1': Mod(x - 1, x^3 - x^2 + 1), 'c_1010_0':
Mod(-x^2 + x, x^3 - x^2 + 1), 'c_1100_1': Mod(x^2 - x, x^3 - x^2 +
1), 'c_1100_0': Mod(-1, x^3 - x^2 + 1), 'c_1100_2': Mod(x^2 - x, x^3
- x^2 + 1), 'c_0101_2': Mod(x - 1, x^3 - x^2 + 1), 'c_0101_1':
Mod(x^2 - x, x^3 - x^2 + 1), 'c_0101_0': Mod(-1, x^3 - x^2 + 1),
'c_0011_1': Mod(-1, x^3 - x^2 + 1), 'c_0011_0': Mod(1, x^3 - x^2 +
1), 'c_0011_2': Mod(-1, x^3 - x^2 + 1)}

If you like cross ratios:

sol.cross_ratios() 
       
{'z_0000_0': Mod(x^2, x^3 - x^2 + 1), 'z_0000_1': Mod(x^2 - x + 1,
x^3 - x^2 + 1), 'z_0000_2': Mod(-x + 1, x^3 - x^2 + 1), 'zp_0000_1':
Mod(x, x^3 - x^2 + 1), 'zp_0000_0': Mod(x^2 - x + 1, x^3 - x^2 + 1),
'zp_0000_2': Mod(-x^2 + x, x^3 - x^2 + 1), 'zpp_0000_2': Mod(-x^2 +
1, x^3 - x^2 + 1), 'zpp_0000_0': Mod(x, x^3 - x^2 + 1),
'zpp_0000_1': Mod(x^2, x^3 - x^2 + 1)}

... to numerical to high precision:

pari.set_real_precision(65) sol.cross_ratios_numerical()[0] 
       
{'z_0000_0':
0.56984029099805326591139995811956864883979743912894022054473107966
+ 0.E-77*I, 'z_0000_1':
2.3247179572447460259609088544780973407344040569017333645340150503 +
0.E-76*I, 'z_0000_2':
1.7548776662466927600495088963585286918946066177727931439892839706 +
0.E-76*I, 'zp_0000_1':
-0.75487766624669276004950889635852869189460661777279314398928397065
+ 0.E-76*I, 'zp_0000_0':
2.3247179572447460259609088544780973407344040569017333645340150503 +
0.E-76*I, 'zp_0000_2':
-1.3247179572447460259609088544780973407344040569017333645340150503
+ 0.E-76*I, 'zpp_0000_2':
0.43015970900194673408860004188043135116020256087105977945526892034
+ 0.E-76*I, 'zpp_0000_0':
-0.75487766624669276004950889635852869189460661777279314398928397065
+ 0.E-76*I, 'zpp_0000_1':
0.56984029099805326591139995811956864883979743912894022054473107966
+ 0.E-77*I}

Compute an invariant (converts to numerical solutions automatically):

pari.set_real_precision(15) sol.complex_volume_numerical() 
       
[-4.29669320956005 E-16 + 0.725471193740844*I, -0.942707362776931 +
0.459731436553693*I, 0.942707362776931 + 0.459731436553693*I]

ptolemy methods can be used on lists (though not listed in tab completion):

sols.complex_volume_numerical() 
       
[[-4.29669320956005 E-16 + 0.725471193740844*I, -0.942707362776931 +
0.459731436553693*I, 0.942707362776931 + 0.459731436553693*I]]

Note that the hyperbolic volume is missing:

M.volume() 
       
2.7818339124

We can fix that using obstruction classes to find boundary-unipotent PSL(2,-representations:

M.ptolemy_variety(N=2,obstruction_class='all') 
       
[Ptolemy Variety for m011, N = 2, obstruction_class = 0, Ptolemy
Variety for m011, N = 2, obstruction_class = 1]

And chain it all together:

vols=M.ptolemy_variety(N=2,obstruction_class='all').compute_solutions().complex_volume_numerical() vols 
       
[[[-4.29669320956005 E-16 + 0.725471193740844*I, -0.942707362776931
+ 0.459731436553693*I, 0.942707362776931 + 0.459731436553693*I]],
[[3.94150857785380 E-15 + 0.312682687518267*I, 4.64797471344536 E-15
+ 0.680993020093457*I, -2.78183391239608 - 0.496837853805869*I,
2.78183391239608 - 0.496837853805869*I]]]

This is a nested structure, to just get a list do:

vols.flatten(depth=2) 
       
[-4.29669320956005 E-16 + 0.725471193740844*I, -0.942707362776931 +
0.459731436553693*I, 0.942707362776931 + 0.459731436553693*I,
3.94150857785380 E-15 + 0.312682687518267*I, 4.64797471344536 E-15 +
0.680993020093457*I, -2.78183391239608 - 0.496837853805869*I,
2.78183391239608 - 0.496837853805869*I]

Future work:

  • Explicitly give the matrices for the SnapPy fundamental group generators
  • Generalize to non-boundary unipotent representations
  • Trace fields, invariant trace fields, shape fields