aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastiano Tronto <sebastiano.tronto@gmail.com>2019-09-19 11:48:05 +0200
committerSebastiano Tronto <sebastiano.tronto@gmail.com>2019-09-19 11:48:05 +0200
commitec512abcc914e42a0a8fabb51b4106aec90773c5 (patch)
tree256891e201bf7291a399a30e8be68232d98241fb
parent6b80453f9f7cd302899ee62eb068d1bfe0bc9ba5 (diff)
downloadkummer-degrees-ec512abcc914e42a0a8fabb51b4106aec90773c5.tar.gz
kummer-degrees-ec512abcc914e42a0a8fabb51b4106aec90773c5.zip
Added caching for failure table
Diffstat (limited to '')
-rw-r--r--kummer_degree.sage53
-rw-r--r--todo-list7
2 files changed, 36 insertions, 24 deletions
diff --git a/kummer_degree.sage b/kummer_degree.sage
index 2b03716..59c0929 100644
--- a/kummer_degree.sage
+++ b/kummer_degree.sage
@@ -9,6 +9,8 @@
9# set of generators is sufficient. # 9# set of generators is sufficient. #
10############################################################################# 10#############################################################################
11 11
12from sage.misc.cachefunc import CachedFunction
13
12# Computes the "adelic Kummer failure", i.e. the degrees of the intersection 14# Computes the "adelic Kummer failure", i.e. the degrees of the intersection
13# of the the Kummer extension Q(\sqrt{2^n}{G}) with the M-th cyclotomic field 15# of the the Kummer extension Q(\sqrt{2^n}{G}) with the M-th cyclotomic field
14# over Q_{2^n}. 16# over Q_{2^n}.
@@ -218,11 +220,11 @@ def bad_primes( B ):
218 return 220 return
219 221
220 # Compute which primes l divide all minors of the exponent matrix 222 # Compute which primes l divide all minors of the exponent matrix
221 bad_primes = list( prime_factors( gcd( M.minors(a) ) ) ) 223 bad_p = list( prime_factors( gcd( M.minors(a) ) ) )
222 if 2 not in bad_primes: 224 if 2 not in bad_p:
223 bad_primes += [2] # 2 is always bad 225 bad_p += [2] # 2 is always bad
224 226
225 return sorted(bad_primes) # Ensures 2 is always first 227 return sorted(bad_p) # Ensures 2 is always first
226 228
227# Computes the l-adic failure for a specific l. Returns a "table" as 229# Computes the l-adic failure for a specific l. Returns a "table" as
228# described above "total_l_adic_failure". 230# described above "total_l_adic_failure".
@@ -345,11 +347,12 @@ def compute_vl( p, n, m, r ):
345 347
346 return M - m + r*n - sum( ni ) 348 return M - m + r*n - sum( ni )
347 349
348# Computes a basis for G from a set of generators. 350# Computes a basis for G from a frozen_set of generators.
349# Returns a pair (B,torsion) where B is a list of rational numbers and 351# Returns a pair (B,torsion) where B is a list of rational numbers and
350# torsion is true if -1 is in G and false otherwise. 352# torsion is true if -1 is in G and false otherwise.
353@CachedFunction
351def generators_to_basis( G ): 354def generators_to_basis( G ):
352 (BM,BM_primes) = exponent_matrix_with_sign_and_primes( G ) 355 (BM,BM_primes) = exponent_matrix_with_sign_and_primes( list(G) )
353 BM = BM.echelon_form() 356 BM = BM.echelon_form()
354 BM_primes.append(-1) 357 BM_primes.append(-1)
355 358
@@ -416,6 +419,7 @@ def adjust_sign( B ):
416# Given the exponent matrix M of a list of rational numbers B, returns the 419# Given the exponent matrix M of a list of rational numbers B, returns the
417# coefficients of a linear combination that is weakly l-divisible, or [] if 420# coefficients of a linear combination that is weakly l-divisible, or [] if
418# the B[i] are strongly l-independent. 421# the B[i] are strongly l-independent.
422@CachedFunction
419def find_combination( M, l ): 423def find_combination( M, l ):
420 M = M.change_ring( GF( l ) ) 424 M = M.change_ring( GF( l ) )
421 if M.rank() != min( M.dimensions() ): 425 if M.rank() != min( M.dimensions() ):
@@ -469,10 +473,11 @@ def exponent_matrix_with_sign_and_primes( B ):
469 rows.append( rowg ) 473 rows.append( rowg )
470 return ( matrix( rows ), prime_list ) 474 return ( matrix( rows ), prime_list )
471 475
472# This is a wrapper function for total_kummer_failure( G, True ), see below. 476# The function TotalKummerFailure (with its many wrapper functions) computes
473def TotalKummerFailure( G ): 477# the total table of Kummer Failures for the given group G. Moreover, the
474 total_kummer_failure( G, True ) 478# result is cached for speeding up following computations on the same group,
475 479# even if the same group is given with a different set of generators.
480#
476# Input: any set of generators for a subgroup G of Q*. 481# Input: any set of generators for a subgroup G of Q*.
477# If output=False, returns a 4-uple (t,MM,NN,D): 482# If output=False, returns a 4-uple (t,MM,NN,D):
478# - t is a pair, where t[0] is the rank of G and t[1] is either True (if G 483# - t is a pair, where t[0] is the rank of G and t[1] is either True (if G
@@ -485,9 +490,18 @@ def TotalKummerFailure( G ):
485# computed for a torsion-free part of G. 490# computed for a torsion-free part of G.
486# If output is True, outputs this data in a human-readable way and does not 491# If output is True, outputs this data in a human-readable way and does not
487# return any value. 492# return any value.
488def total_kummer_failure( G, output ):
489 493
494def TotalKummerFailure( G ):
495 total_kummer_failure( G, True )
496
497@CachedFunction
498def total_kummer_failure_cachable( G ):
490 B, torsion = generators_to_basis( G ) 499 B, torsion = generators_to_basis( G )
500 return total_kummer_failure_cachable_basis( tuple(B), torsion )
501
502@CachedFunction
503def total_kummer_failure_cachable_basis( B, torsion ):
504 B = list(B)
491 r = len(B) # Rank of G 505 r = len(B) # Rank of G
492 506
493 if r == 0: 507 if r == 0:
@@ -495,15 +509,15 @@ def total_kummer_failure( G, output ):
495 return False 509 return False
496 510
497 # Compute l-adic data (straightforward) 511 # Compute l-adic data (straightforward)
498 ( bad_primes, l_adic_failure_table ) = total_l_adic_failure( B ) 512 ( bad_p, l_adic_failure_table ) = total_l_adic_failure( B )
499 513
500 # Compute adelic data. 514 # Compute adelic data.
501 (GB,d) = adjust_sign( make_good_basis( B, 2 ) ) 515 (GB,d) = adjust_sign( make_good_basis( B, 2 ) )
502 adelic_failure_table = adelic_failure_gb( GB, d ) 516 adelic_failure_table = adelic_failure_gb( GB, d )
503 517
504 # Computing the bounds M0 and N0 518 # Computing the bounds M0 and N0
505 N0 = prod( [ bad_primes[i] ^ len( l_adic_failure_table[i][-1][0] ) \ 519 N0 = prod( [ bad_p[i] ^ len( l_adic_failure_table[i][-1][0] ) \
506 for i in range(len(bad_primes)) ] ) 520 for i in range(len(bad_p)) ] )
507 # Extra factors of 2 may come from the adelic failure 521 # Extra factors of 2 may come from the adelic failure
508 N0 = lcm( N0, 2^len( adelic_failure_table ) ) 522 N0 = lcm( N0, 2^len( adelic_failure_table ) )
509 divs_N0 = divisors(N0) 523 divs_N0 = divisors(N0)
@@ -530,16 +544,20 @@ def total_kummer_failure( G, output ):
530 FT[j][l] = lcm( FT[j][l], pp[1] ) 544 FT[j][l] = lcm( FT[j][l], pp[1] )
531 545
532 # Adding l-adic failure to the table 546 # Adding l-adic failure to the table
533 for i in range( len( bad_primes ) ): 547 for i in range( len( bad_p ) ):
534 l = bad_primes[i] 548 l = bad_p[i]
535 for j in range(len(divs_N0)): 549 for j in range(len(divs_N0)):
536 dN = divs_N0[j] 550 dN = divs_N0[j]
537 fl = l_adic_failure_from_data(B,l,l_adic_failure_table[i],dN,dN) 551 fl = l_adic_failure_from_data(B,l,l_adic_failure_table[i],dN,dN)
538 for h in range(len(divs_M0)): 552 for h in range(len(divs_M0)):
539 FT[j][h] *= fl 553 FT[j][h] *= fl
540 554
541 ret = ( ( r, torsion ), ( M0, divs_M0 ), ( N0, divs_N0 ), FT ) 555 return ( ( r, torsion ), ( M0, divs_M0 ), ( N0, divs_N0 ), FT )
542 556
557def total_kummer_failure( G, output ):
558
559 ret = total_kummer_failure_cachable( frozenset(G) )
560
543 if output: 561 if output:
544 print_total_table( ret ) 562 print_total_table( ret )
545 # Uncomment following line for case list description. 563 # Uncomment following line for case list description.
@@ -728,3 +746,4 @@ def KummerDegree( G, M, N ):
728 failure = FT 746 failure = FT
729 747
730 return e_deg/failure[divs_N0.index(gcd(N,N0))][divs_M0.index(gcd(M,M0))] 748 return e_deg/failure[divs_N0.index(gcd(N,N0))][divs_M0.index(gcd(M,M0))]
749
diff --git a/todo-list b/todo-list
deleted file mode 100644
index eb52de1..0000000
--- a/todo-list
+++ /dev/null
@@ -1,7 +0,0 @@
1- Decent output format. What information might the user want?
2 - maybe not so bad right now
3- Caching for efficient subsequent computations on the same group
4 - What is Sage standard for this kind of stuff?
5- Standardize to Sage coding style
6- Should the given degree be over Q or over the cyclotomic field?
7 - I don't even remember what I am doing now on top of my mind...

Generated with cgit - Back to sebastiano.tronto.net