diff --git a/SL.jl b/SL.jl index 62a908c..815005b 100644 --- a/SL.jl +++ b/SL.jl @@ -1,6 +1,11 @@ -import Primes: isprime +using ArgParse +using GroupAlgebras +using PropertyT using Mods +import Primes: isprime + +import SCS.SCSSolver function SL_generatingset(n::Int) @@ -72,14 +77,14 @@ function inv(M::Array{Mod,2}) end function SL_generatingset(n::Int, p::Int) - (p > 1 && n > 1) || throw(ArgumentError("Both n and p should be integers!")) + p == 0 && return SL_generatingset(n) + (p > 1 && n > 0) || throw(ArgumentError("Both n and p should be positive integers!")) isprime(p) || throw(ArgumentError("p should be a prime number!")) indexing = [(i,j) for i in 1:n for j in 1:n if i≠j] S = [E(i,j, N=n, mod=p) for (i,j) in indexing] S = vcat(S, [inv(s) for s in S]) S = vcat(S, [permutedims(x, [2,1]) for x in S]); - return unique(S) end @@ -108,6 +113,12 @@ function ΔandSDPconstraints{T<:Number}(identity::Array{T,2}, S::Vector{Array{T, return Δ, sdp_constraints end +ID(n::Int) = eye(Int, n) + +function ID(n::Int, p::Int) + p==0 && return ID(n) + return [Mod(x,p) for x in eye(Int,N)] +end #= @@ -118,24 +129,89 @@ function ΔandSDPconstraints(identity, S):: (Δ, sdp_constraints) =# -using GroupAlgebras -using PropertyT +function cpuinfo_physicalcores() + maxcore = -1 + for line in eachline("/proc/cpuinfo") + if startswith(line, "core id") + maxcore = max(maxcore, parse(Int, split(line, ':')[2])) + end + end + maxcore < 0 && error("failure to read core ids from /proc/cpuinfo") + return maxcore + 1 +end -const N = 3 +function parse_commandline() + s = ArgParseSettings() -# const name = "SL$(N)Z" -const name = "SL3Z-0.279" -const ID = eye(Int, N) -S() = SL_generatingset(N) -const upper_bound=0.27 + @add_arg_table s begin + "--tol" + help = "set numerical tolerance for the SDP solver" + arg_type = Float64 + default = 1e-9 + "--iterations" + help = "set maximal number of iterations for the SDP solver" + arg_type = Int + default = 100000 + "--upper-bound" + help = "Set an upper bound for the spectral gap" + arg_type = Float64 + default = Inf + "--cpus" + help = "Set number of cpus used by solver" + arg_type = Int + required = false + "-N" + help = "Consider matrices of size N" + arg_type = Int + default = 3 + "-p" + help = "Matrices over filed of p-elements (0 = over ZZ)" + arg_type = Int + default = 0 + end + return parse_args(s) +end -# const p = 7 -# const upper_bound=0.738 # (N,p) = (3,7) +function main() + parsed_args = parse_commandline() + println("Parsed args:") -# const name = "SL($N,$p)" -# const ID = [Mod(x,p) for x in eye(Int,N)] -# S() = SL_generatingset(N, p) + # SL(3,Z) + # upper_bound = 0.28-1e-5 + # tol = 1e-12 + # iterations = 500000 -BLAS.set_num_threads(4) -@time PropertyT.check_property_T(name, ID, S; verbose=true, tol=1e-8, upper_bound=upper_bound) + # SL(4,Z) + # upper_bound = 1.31 + # tol = 3e-11 + + # upper_bound=0.738 # (N,p) = (3,7) + + tol = parsed_args["tol"] + iterations = parsed_args["iterations"] + + # solver = MosekSolver(INTPNT_CO_TOL_REL_GAP=tol, QUIET=false) + solver = SCSSolver(eps=tol, max_iters=iterations, verbose=true) + + N = parsed_args["N"] + upper_bound = parsed_args["upper-bound"] + p = parsed_args["p"] + if p == 0 + name = "SL$(N)Z" + else + name = "SL$(N)_p" + end + + S() = SL_generatingset(N, p) + + if parsed_args["cpus"] ≠ nothing + if parsed_args["cpus"] > cpuinfo_physicalcores() + warn("Number of specified cores exceeds the physical core cound. Performance will suffer.") + end + Blas.set_num_threads(parsed_args["cpus"]) + end + @time PropertyT.check_property_T(name, ID(N,p), S, solver, upper_bound, tol) +end + +main()