2020-05-26 00:10:24 +02:00
|
|
|
|
using RamanujanGraphs
|
|
|
|
|
using LinearAlgebra
|
2020-11-14 19:23:21 +01:00
|
|
|
|
using Arblib
|
2020-09-03 10:58:44 +02:00
|
|
|
|
using ArgParse
|
2020-05-26 00:10:24 +02:00
|
|
|
|
|
2020-06-09 16:18:00 +02:00
|
|
|
|
using Logging
|
|
|
|
|
using Dates
|
2020-05-26 00:10:24 +02:00
|
|
|
|
|
2020-11-14 19:24:12 +01:00
|
|
|
|
import RamanujanGraphs.Primes: isprime
|
|
|
|
|
|
2020-11-14 19:23:21 +01:00
|
|
|
|
include(joinpath(@__DIR__, "src", "eigen_utils.jl"))
|
2020-05-26 00:10:24 +02:00
|
|
|
|
|
2020-11-14 19:24:12 +01:00
|
|
|
|
function SL2p_gens(p::Integer)
|
|
|
|
|
@assert isprime(p)
|
2020-09-01 22:12:59 +02:00
|
|
|
|
if p == 31
|
|
|
|
|
a, b = let
|
|
|
|
|
a = SL₂{p}([8 14; 4 11])
|
|
|
|
|
b = SL₂{p}([23 0; 14 27])
|
|
|
|
|
@assert isone(a^10)
|
|
|
|
|
@assert isone(b^10)
|
|
|
|
|
|
2020-09-03 14:11:29 +02:00
|
|
|
|
a, b
|
|
|
|
|
end
|
|
|
|
|
elseif p == 41
|
|
|
|
|
a, b = let
|
|
|
|
|
a = SL₂{p}([0 28; 19 35])
|
|
|
|
|
b = SL₂{p}([38 27; 2 9])
|
|
|
|
|
@assert isone(a^10)
|
|
|
|
|
@assert isone(b^10)
|
|
|
|
|
|
2020-09-01 22:12:59 +02:00
|
|
|
|
a, b
|
|
|
|
|
end
|
|
|
|
|
elseif p == 109
|
2020-06-09 10:52:55 +02:00
|
|
|
|
a, b = let
|
|
|
|
|
a = SL₂{p}([0 1; 108 11])
|
|
|
|
|
b = SL₂{p}([57 2; 52 42])
|
2020-05-26 00:10:24 +02:00
|
|
|
|
@assert isone(a^10)
|
|
|
|
|
@assert isone(b^10)
|
|
|
|
|
|
|
|
|
|
a, b
|
|
|
|
|
end
|
|
|
|
|
elseif p == 131
|
2020-06-09 10:52:55 +02:00
|
|
|
|
a, b = let
|
2020-05-26 00:10:24 +02:00
|
|
|
|
a = SL₂{p}([-58 -24; -58 46])
|
|
|
|
|
b = SL₂{p}([0 -3; 44 -12])
|
|
|
|
|
@assert isone(a^10)
|
|
|
|
|
@assert isone(b^10)
|
|
|
|
|
|
|
|
|
|
a, b
|
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
@warn "no special set of generators for prime $p"
|
2020-06-09 10:52:55 +02:00
|
|
|
|
a, b = let
|
2020-05-26 00:10:24 +02:00
|
|
|
|
a = SL₂{p}(1, 0, 1, 1)
|
|
|
|
|
b = SL₂{p}(1, 1, 0, 1)
|
|
|
|
|
a, b
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2022-02-13 11:38:31 +01:00
|
|
|
|
return a, b
|
2020-05-26 00:10:24 +02:00
|
|
|
|
end
|
|
|
|
|
|
2022-02-13 11:38:31 +01:00
|
|
|
|
function adjacency(ϱ, a, b; prec = 256)
|
|
|
|
|
order_a = findfirst(i -> isone(a^i), 1:100)
|
|
|
|
|
order_b = findfirst(i -> isone(b^i), 1:100)
|
2020-11-14 20:38:04 +01:00
|
|
|
|
@assert !isnothing(order_a) && order_a > 1
|
|
|
|
|
@assert !isnothing(order_b) && order_b > 1
|
|
|
|
|
|
2022-02-13 11:38:31 +01:00
|
|
|
|
k = order_a - 1 + order_b - 1
|
2020-11-14 20:38:04 +01:00
|
|
|
|
|
2022-02-13 11:38:31 +01:00
|
|
|
|
A = AcbMatrix(ϱ(a), prec = prec)
|
|
|
|
|
B = AcbMatrix(ϱ(b), prec = prec)
|
2020-11-14 20:38:04 +01:00
|
|
|
|
res = sum(A^i for i = 1:order_a-1) + sum(B^i for i = 1:order_b-1)
|
2022-02-13 11:38:31 +01:00
|
|
|
|
#return Arblib.scalar_div!(res, res, k)
|
|
|
|
|
return res
|
2020-06-09 16:18:00 +02:00
|
|
|
|
end
|
2020-05-26 00:10:24 +02:00
|
|
|
|
|
2020-09-03 10:58:44 +02:00
|
|
|
|
function parse_our_args()
|
|
|
|
|
s = ArgParseSettings()
|
2020-09-03 12:36:58 +02:00
|
|
|
|
@add_arg_table! s begin
|
2020-09-03 10:58:44 +02:00
|
|
|
|
"-p"
|
2022-02-13 11:38:31 +01:00
|
|
|
|
help = "the prime p for which to use PSL(2,p)"
|
|
|
|
|
arg_type = Int
|
|
|
|
|
required = true
|
2020-09-03 10:58:44 +02:00
|
|
|
|
"-a"
|
2022-02-13 11:38:31 +01:00
|
|
|
|
help = "generator a (optional)"
|
2020-09-03 10:58:44 +02:00
|
|
|
|
"-b"
|
2022-02-13 11:38:31 +01:00
|
|
|
|
help = "generator b (optional)"
|
2020-09-03 11:35:33 +02:00
|
|
|
|
"--ab"
|
2022-02-13 11:38:31 +01:00
|
|
|
|
help = "array of generators a and b (optional)"
|
2020-11-14 20:38:34 +01:00
|
|
|
|
"--precision"
|
2022-02-13 11:38:31 +01:00
|
|
|
|
help = "set the precision of computations"
|
|
|
|
|
arg_type = Int
|
|
|
|
|
default = 128
|
2020-09-03 10:58:44 +02:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
result = parse_args(s)
|
2020-09-03 11:35:33 +02:00
|
|
|
|
for key in ["a", "b", "ab"]
|
2020-09-03 10:58:44 +02:00
|
|
|
|
val = get(result, key, "")
|
|
|
|
|
if val != nothing
|
|
|
|
|
result[key] = eval(Meta.parse(val))
|
|
|
|
|
else
|
|
|
|
|
delete!(result, key)
|
|
|
|
|
end
|
|
|
|
|
end
|
2020-09-03 11:35:33 +02:00
|
|
|
|
val = get(result, "ab", "")
|
|
|
|
|
if val != ""
|
|
|
|
|
result["a"] = val[1]
|
|
|
|
|
result["b"] = val[2]
|
|
|
|
|
end
|
2020-09-03 10:58:44 +02:00
|
|
|
|
result
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
parsed_args = parse_our_args()
|
|
|
|
|
|
2020-11-14 19:24:12 +01:00
|
|
|
|
const p = let p = parsed_args["p"]
|
2022-02-13 11:38:31 +01:00
|
|
|
|
isprime(p) ||
|
|
|
|
|
@error "You need to provide a prime, ex: `julia adj_psl2_eigvals.jl -p 31`"
|
2020-06-09 16:18:00 +02:00
|
|
|
|
p
|
|
|
|
|
end
|
2020-05-26 00:10:24 +02:00
|
|
|
|
|
2020-11-14 20:38:34 +01:00
|
|
|
|
const PRECISION = parsed_args["precision"]
|
|
|
|
|
const LOGFILE = joinpath("log", "SL(2,$p)_eigvals_$(now()).log")
|
2020-06-09 16:18:00 +02:00
|
|
|
|
|
2020-11-14 20:38:34 +01:00
|
|
|
|
open(LOGFILE, "w") do io
|
|
|
|
|
@info "Logging into $LOGFILE"
|
2020-06-09 16:18:00 +02:00
|
|
|
|
with_logger(SimpleLogger(io)) do
|
|
|
|
|
|
2022-02-13 11:38:31 +01:00
|
|
|
|
@info "Arguments:" args = parsed_args
|
2020-06-09 16:18:00 +02:00
|
|
|
|
|
2022-02-13 11:38:31 +01:00
|
|
|
|
a, b = SL2p_gens(p)
|
2020-09-03 10:58:44 +02:00
|
|
|
|
a = SL₂{p}(get(parsed_args, "a", a))
|
|
|
|
|
b = SL₂{p}(get(parsed_args, "b", b))
|
2020-09-21 20:59:20 +02:00
|
|
|
|
@info "Generators" a b
|
2020-06-09 16:18:00 +02:00
|
|
|
|
|
2022-02-13 11:38:31 +01:00
|
|
|
|
Borel_cosets = let p = p, (a, b) = (a, b)
|
2020-06-09 16:18:00 +02:00
|
|
|
|
SL2p, sizes =
|
|
|
|
|
RamanujanGraphs.generate_balls([a, b, inv(a), inv(b)], radius = 21)
|
|
|
|
|
@assert sizes[end] == RamanujanGraphs.order(SL₂{p})
|
|
|
|
|
RamanujanGraphs.CosetDecomposition(SL2p, Borel(SL₂{p}))
|
2020-05-26 00:10:24 +02:00
|
|
|
|
end
|
|
|
|
|
|
2020-11-14 20:38:04 +01:00
|
|
|
|
all_large_evs = Arb[]
|
2020-06-09 16:18:00 +02:00
|
|
|
|
let α = RamanujanGraphs.generator(RamanujanGraphs.GF{p}(0))
|
2020-06-08 16:18:02 +02:00
|
|
|
|
|
2020-06-09 16:18:00 +02:00
|
|
|
|
for j = 0:(p-1)÷4
|
|
|
|
|
h = PrincipalRepr(
|
2022-02-13 11:38:31 +01:00
|
|
|
|
α => unit_root((p - 1) ÷ 2, j, prec = PRECISION),
|
2020-06-09 16:18:00 +02:00
|
|
|
|
Borel_cosets,
|
|
|
|
|
)
|
|
|
|
|
|
2022-02-13 11:38:31 +01:00
|
|
|
|
@time adj = adjacency(h, a, b, prec = PRECISION)
|
2020-06-08 16:18:02 +02:00
|
|
|
|
|
2020-06-09 16:18:00 +02:00
|
|
|
|
try
|
2020-11-14 20:38:04 +01:00
|
|
|
|
@time evs = let evs = safe_eigvals(adj)
|
|
|
|
|
count_multiplicites(evs)
|
2020-06-09 16:18:00 +02:00
|
|
|
|
end
|
2020-11-14 20:38:04 +01:00
|
|
|
|
append!(all_large_evs, [real(first(x)) for x in evs[1:2]])
|
2020-06-09 16:18:00 +02:00
|
|
|
|
|
2020-11-14 20:38:04 +01:00
|
|
|
|
@info "Principal Series Representation $j" evs[1:2] evs[end]
|
2020-06-09 16:18:00 +02:00
|
|
|
|
catch ex
|
|
|
|
|
@error "Principal Series Representation $j failed" ex
|
|
|
|
|
ex isa InterruptException && rethrow(ex)
|
|
|
|
|
end
|
2020-05-26 00:10:24 +02:00
|
|
|
|
end
|
2020-06-09 16:18:00 +02:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
let α = RamanujanGraphs.generator(RamanujanGraphs.GF{p}(0)),
|
|
|
|
|
β = RamanujanGraphs.generator_min(QuadraticExt(α))
|
2020-05-26 00:10:24 +02:00
|
|
|
|
|
2020-06-09 16:18:00 +02:00
|
|
|
|
if p % 4 == 1
|
|
|
|
|
ub = (p - 1) ÷ 4
|
2022-02-13 11:38:31 +01:00
|
|
|
|
ζ = unit_root((p + 1) ÷ 2, 1, prec = PRECISION)
|
2020-06-09 16:18:00 +02:00
|
|
|
|
else # p % 4 == 3
|
|
|
|
|
ub = (p + 1) ÷ 4
|
2022-02-13 11:38:31 +01:00
|
|
|
|
ζ = unit_root((p + 1), 1, prec = PRECISION)
|
2020-05-26 00:10:24 +02:00
|
|
|
|
end
|
|
|
|
|
|
2020-06-09 16:18:00 +02:00
|
|
|
|
for k = 1:ub
|
|
|
|
|
|
|
|
|
|
h = DiscreteRepr(
|
2022-02-13 11:38:31 +01:00
|
|
|
|
RamanujanGraphs.GF{p}(1) => unit_root(p, prec = PRECISION),
|
2020-06-09 16:18:00 +02:00
|
|
|
|
β => ζ^k,
|
|
|
|
|
)
|
|
|
|
|
|
2022-02-13 11:38:31 +01:00
|
|
|
|
@time adj = adjacency(h, a, b, prec = PRECISION)
|
2020-06-09 16:18:00 +02:00
|
|
|
|
|
|
|
|
|
try
|
2020-11-14 20:38:04 +01:00
|
|
|
|
@time evs = let evs = safe_eigvals(adj)
|
|
|
|
|
count_multiplicites(evs)
|
2020-06-09 16:18:00 +02:00
|
|
|
|
end
|
2020-11-14 20:38:04 +01:00
|
|
|
|
append!(all_large_evs, [real(first(x)) for x in evs[1:2]])
|
2020-06-09 16:18:00 +02:00
|
|
|
|
|
2020-11-14 20:38:04 +01:00
|
|
|
|
@info "Discrete Series Representation $k" evs[1:2] evs[end]
|
2020-06-09 16:18:00 +02:00
|
|
|
|
catch ex
|
|
|
|
|
@error "Discrete Series Representation $k : failed" ex
|
|
|
|
|
ex isa InterruptException && rethrow(ex)
|
|
|
|
|
end
|
|
|
|
|
end
|
2020-05-26 00:10:24 +02:00
|
|
|
|
end
|
2022-02-13 11:38:31 +01:00
|
|
|
|
all_large_evs = sort(all_large_evs, rev = true)
|
2020-09-03 12:36:58 +02:00
|
|
|
|
λ = all_large_evs[2]
|
2022-02-13 11:38:31 +01:00
|
|
|
|
ε = (λ - 3) / 5
|
2020-09-03 12:36:58 +02:00
|
|
|
|
α = acos(ε)
|
2022-02-13 11:38:31 +01:00
|
|
|
|
α_deg = (α / pi) * 180
|
2020-11-14 20:40:33 +01:00
|
|
|
|
@info "Certified values:" λ ε α α_deg
|
2020-06-09 16:18:00 +02:00
|
|
|
|
end # with_logger
|
|
|
|
|
end # open(logfile)
|
2020-05-26 00:10:24 +02:00
|
|
|
|
|
2020-06-09 10:52:55 +02:00
|
|
|
|
#
|
2020-05-26 00:10:24 +02:00
|
|
|
|
# using RamanujanGraphs.LightGraphs
|
|
|
|
|
# using Arpack
|
|
|
|
|
#
|
2020-06-09 10:52:55 +02:00
|
|
|
|
# Γ, eigenvalues = let p = 109,
|
|
|
|
|
# a = PSL₂{p}([ 0 1; 108 11]),
|
|
|
|
|
# b = PSL₂{p}([ 57 2; 52 42])
|
2020-05-26 00:10:24 +02:00
|
|
|
|
#
|
|
|
|
|
# S = unique([[a^i for i in 1:4]; [b^i for i in 1:4]])
|
|
|
|
|
#
|
|
|
|
|
# @info "Generating set S of $(eltype(S))" S
|
2020-06-09 10:52:55 +02:00
|
|
|
|
# @time Γ, verts, vlabels, elabels =
|
|
|
|
|
# RamanujanGraphs.cayley_graph(RamanujanGraphs.order(PSL₂{p}), S)
|
|
|
|
|
#
|
|
|
|
|
# @assert all(LightGraphs.degree(Γ,i) == length(S) for i in vertices(Γ))
|
|
|
|
|
# @assert LightGraphs.nv(Γ) == RamanujanGraphs.order(PSL₂{p})
|
|
|
|
|
# A = adjacency_matrix(Γ)
|
|
|
|
|
# @time eigenvalues, _ = eigs(A, nev=5)
|
|
|
|
|
# @show Γ eigenvalues
|
|
|
|
|
# Γ, eigenvalues
|
|
|
|
|
# end
|
|
|
|
|
#
|
|
|
|
|
# let p = 131,
|
|
|
|
|
# a = PSL₂{p}([-58 -24; -58 46]),
|
|
|
|
|
# b = PSL₂{p}([0 -3; 44 -12])
|
|
|
|
|
#
|
|
|
|
|
# S = unique([[a^i for i in 1:4]; [b^i for i in 1:4]])
|
|
|
|
|
#
|
|
|
|
|
# @info "Generating set S of $(eltype(S))" S
|
|
|
|
|
# @time Γ, verts, vlabels, elabels =
|
|
|
|
|
# RamanujanGraphs.cayley_graph(RamanujanGraphs.order(PSL₂{p}), S)
|
|
|
|
|
#
|
2020-05-26 00:10:24 +02:00
|
|
|
|
# @assert all(LightGraphs.degree(Γ,i) == length(S) for i in vertices(Γ))
|
2020-06-09 10:52:55 +02:00
|
|
|
|
# @assert LightGraphs.nv(Γ) == RamanujanGraphs.order(PSL₂{p})
|
2020-05-26 00:10:24 +02:00
|
|
|
|
# A = adjacency_matrix(Γ)
|
|
|
|
|
# @time eigenvalues, _ = eigs(A, nev=5)
|
|
|
|
|
# @show Γ eigenvalues
|
|
|
|
|
# Γ, eigenvalues
|
|
|
|
|
# end
|