Path: blob/master/src/sage/modular/arithgroup/tests.py
8820 views
r"""1Testing Arithmetic subgroup2"""3################################################################################4#5# Copyright (C) 2009, The Sage Group -- http://www.sagemath.org/6#7# Distributed under the terms of the GNU General Public License (GPL)8#9# The full text of the GPL is available at:10#11# http://www.gnu.org/licenses/12#13################################################################################1415from arithgroup_perm import ArithmeticSubgroup_Permutation, EvenArithmeticSubgroup_Permutation, OddArithmeticSubgroup_Permutation16from sage.modular.arithgroup.all import Gamma, Gamma0, Gamma1, GammaH17from sage.rings.finite_rings.integer_mod_ring import Zmod1819import sage.misc.prandom as prandom20from sage.misc.misc import cputime2122def random_even_arithgroup(index,nu2_max=None,nu3_max=None):23r"""24Return a random even arithmetic subgroup2526EXAMPLES::2728sage: import sage.modular.arithgroup.tests as tests29sage: G = tests.random_even_arithgroup(30); G # random30Arithmetic subgroup of index 3031sage: G.is_even()32True33"""34from sage.groups.perm_gps.permgroup import PermutationGroup3536test = False3738if nu2_max is None:39nu2_max = index//540elif nu2_max == 0:41assert index%2 == 042if nu3_max is None:43nu3_max = index//744elif nu3_max == 0:45assert index%3 == 04647while not test:48nu2 = prandom.randint(0,nu2_max)49nu2 = index%2 + nu2*250nu3 = prandom.randint(0,nu3_max)51nu3 = index%3 + nu3*35253l = range(1,index+1)54prandom.shuffle(l)55S2 = []56for i in xrange(nu2):57S2.append((l[i],))58for i in xrange(nu2,index,2):59S2.append((l[i],l[i+1]))60prandom.shuffle(l)61S3 = []62for i in xrange(nu3):63S3.append((l[i],))64for i in xrange(nu3,index,3):65S3.append((l[i],l[i+1],l[i+2]))66G = PermutationGroup([S2,S3])67test = G.is_transitive()6869return ArithmeticSubgroup_Permutation(S2=S2,S3=S3)7071def random_odd_arithgroup(index,nu3_max=None):72r"""73Return a random odd arithmetic subgroup7475EXAMPLES::7677sage: from sage.modular.arithgroup.tests import random_odd_arithgroup78sage: G = random_odd_arithgroup(20); G #random79Arithmetic subgroup of index 2080sage: G.is_odd()81True82"""83assert index%4 == 084G = random_even_arithgroup(index//2,nu2_max=0,nu3_max=nu3_max)85return G.one_odd_subgroup(random=True)8687class Test:88r"""89Testing class for arithmetic subgroup implemented via permutations.90"""91def __init__(self, index=20, index_max=50, odd_probability=0.5):92r"""93Create an arithmetic subgroup testing object.9495INPUT:9697- ``index`` - the index of random subgroup to test9899- ``index_max`` - the maximum index for congruence subgroup to test100101EXAMPLES::102103sage: from sage.modular.arithgroup.tests import Test104sage: Test()105Arithmetic subgroup testing class106"""107self.congroups = []108i = 1109self.odd_probability = odd_probability110if index%2:111self.odd_probability=0112while Gamma(i).index() < index_max:113self.congroups.append(Gamma(i))114i += 1115i = 1116while Gamma0(i).index() < index_max:117self.congroups.append(Gamma0(i))118i += 1119i = 2120while Gamma1(i).index() < index_max:121self.congroups.append(Gamma1(i))122M = Zmod(i)123U = filter(lambda x: x.is_unit(), M)124for j in xrange(1,len(U)-1):125self.congroups.append(GammaH(i,prandom.sample(U,j)))126i += 1127128self.index = index129130def __repr__(self):131r"""132Return the string representation of self133134EXAMPLES::135136sage: from sage.modular.arithgroup.tests import Test137sage: Test().__repr__()138'Arithmetic subgroup testing class'139"""140return "Arithmetic subgroup testing class"141142def _do(self, name):143"""144Perform the test 'test_name', where name is specified as an145argument. This function exists to avoid a call to eval.146147EXAMPLES::148149sage: from sage.modular.arithgroup.tests import Test150sage: Test()._do("random")151test_random152...153"""154155print "test_%s"%name156Test.__dict__["test_%s"%name](self)157158def random(self, seconds=0):159"""160Perform random tests for a given number of seconds, or161indefinitely if seconds is not specified.162163EXAMPLES::164165sage: from sage.modular.arithgroup.tests import Test166sage: Test().random(1)167test_random168...169"""170self.test("random", seconds)171172def test(self, name, seconds=0):173"""174Repeatedly run 'test_name', where name is passed as an175argument. If seconds is nonzero, run for that many seconds. If176seconds is 0, run indefinitely.177178EXAMPLES::179180sage: from sage.modular.arithgroup.tests import Test181sage: T = Test()182sage: T.test('relabel',seconds=1)183test_relabel184...185sage: T.test('congruence_groups',seconds=1)186test_congruence_groups187...188sage: T.test('contains',seconds=1)189test_contains190...191sage: T.test('todd_coxeter',seconds=1)192test_todd_coxeter193...194"""195seconds = float(seconds)196total = cputime()197n = 1198while seconds == 0 or cputime(total) < seconds:199s = "** test_dimension: number %s"%n200if seconds > 0:201s += " (will stop after about %s seconds)"%seconds202t = cputime()203self._do(name)204print "\ttime=%s\telapsed=%s"%(cputime(t),cputime(total))205n += 1206207def test_random(self):208"""209Do a random test from all the possible tests.210211EXAMPLES::212213sage: from sage.modular.arithgroup.tests import Test214sage: Test().test_random() #random215Doing random test216"""217tests = [a for a in Test.__dict__.keys() if a[:5] == "test_" and a != "test_random"]218name = prandom.choice(tests)219print "Doing random test %s"%name220Test.__dict__[name](self)221222def test_relabel(self):223r"""224Try the function canonic labels for a random even modular subgroup.225226EXAMPLES::227228sage: from sage.modular.arithgroup.tests import Test229sage: Test().test_relabel() # random230"""231if prandom.uniform(0,1) < self.odd_probability:232G = random_odd_arithgroup(self.index)233else:234G = random_even_arithgroup(self.index)235236G.relabel()237s2 = G._S2238s3 = G._S3239l = G._L240r = G._R241242# 0 should be stabilized by the mapping243# used for renumbering so we start at 1244p = range(1,self.index)245246for _ in xrange(10):247prandom.shuffle(p)248# we add 0 to the mapping249pp = [0] + p250ss2 = [None]*self.index251ss3 = [None]*self.index252ll = [None]*self.index253rr = [None]*self.index254for i in xrange(self.index):255ss2[pp[i]] = pp[s2[i]]256ss3[pp[i]] = pp[s3[i]]257ll[pp[i]] = pp[l[i]]258rr[pp[i]] = pp[r[i]]259if G.is_even():260GG = EvenArithmeticSubgroup_Permutation(ss2,ss3,ll,rr)261else:262GG = OddArithmeticSubgroup_Permutation(ss2,ss3,ll,rr)263GG.relabel()264265for elt in ['_S2','_S3','_L','_R']:266if getattr(G,elt) != getattr(GG,elt):267print "s2 = %s" %str(s2)268print "s3 = %s" %str(s3)269print "ss2 = %s" %str(ss2)270print "ss3 = %s" %str(ss3)271print "pp = %s" %str(pp)272raise AssertionError, "%s does not coincide" %elt273274def test_congruence_groups(self):275r"""276Check whether the different implementations of methods for congruence277groups and generic arithmetic group by permutations return the same278results.279280EXAMPLES::281282sage: from sage.modular.arithgroup.tests import Test283sage: Test().test_congruence_groups() #random284"""285G = prandom.choice(self.congroups)286GG = G.as_permutation_group()287288if not GG.is_congruence():289raise AssertionError, "Hsu congruence test failed"290291methods = [292'index',293'is_odd',294'is_even',295'is_normal',296'ncusps',297'nregcusps',298'nirregcusps',299'nu2',300'nu3',301'generalised_level']302303for f in methods:304if getattr(G,f)() != getattr(GG,f)():305raise AssertionError, "results of %s does not coincide for %s" %(f,G)306307if sorted((G.cusp_width(c) for c in G.cusps())) != GG.cusp_widths():308raise AssertionError, "Cusps widths are different for %s" %G309310for _ in xrange(20):311m = GG.random_element()312if m not in G:313raise AssertionError, "random element generated by perm. group not in %s" %(str(m),str(G))314315def test_contains(self):316r"""317Test whether the random generator for arithgroup perms gives matrices in318the group.319320EXAMPLES::321322sage: from sage.modular.arithgroup.tests import Test323sage: Test().test_contains() #random324"""325if prandom.uniform(0,1) < self.odd_probability:326G = random_odd_arithgroup(self.index)327else:328G = random_even_arithgroup(self.index)329330for _ in xrange(20):331g = G.random_element()332if G.random_element() not in G:333raise AssertionError, "%s not in %s" %(g,G)334335def test_spanning_trees(self):336r"""337Test coset representatives obtained from spanning trees for even338subgroup (Kulkarni's method with generators ``S2``, ``S3`` and Verrill's339method with generators ``L``, ``S2``).340341EXAMPLES::342343sage: from sage.modular.arithgroup.tests import Test344sage: Test().test_spanning_trees() #random345"""346from sage.all import prod347from all import SL2Z348from arithgroup_perm import S2m,S3m,Lm349350G = random_even_arithgroup(self.index)351352m = {'l':Lm, 's':S2m}353tree,reps,wreps,gens = G._spanning_tree_verrill()354assert reps[0] == SL2Z([1,0,0,1])355assert wreps[0] == ''356for i in xrange(1,self.index):357assert prod(m[letter] for letter in wreps[i]) == reps[i]358tree,reps,wreps,gens = G._spanning_tree_verrill(on_right=False)359assert reps[0] == SL2Z([1,0,0,1])360assert wreps[0] == ''361for i in xrange(1,self.index):362assert prod(m[letter] for letter in wreps[i]) == reps[i]363364m = {'s2':S2m, 's3':S3m}365tree,reps,wreps,gens = G._spanning_tree_kulkarni()366assert reps[0] == SL2Z([1,0,0,1])367assert wreps[0] == []368for i in xrange(1,self.index):369assert prod(m[letter] for letter in wreps[i]) == reps[i]370tree,reps,wreps,gens = G._spanning_tree_kulkarni(on_right=False)371assert reps[0] == SL2Z([1,0,0,1])372assert wreps[0] == []373for i in xrange(1,self.index):374assert prod(m[letter] for letter in wreps[i]) == reps[i]375376def test_todd_coxeter(self):377r"""378Test representatives of todd coxeter algorithm379380EXAMPLES::381382sage: from sage.modular.arithgroup.tests import Test383sage: Test().test_todd_coxeter() #random384"""385from all import SL2Z386from arithgroup_perm import S2m,S3m,Lm,Rm387388G = random_even_arithgroup(self.index)389390reps,gens,l,s2 = G.todd_coxeter_l_s2()391assert reps[0] == SL2Z([1,0,0,1])392assert len(reps) == G.index()393for i in xrange(1,len(reps)):394assert reps[i] not in G395assert reps[i]*S2m*~reps[s2[i]] in G396assert reps[i]*Lm*~reps[l[i]] in G397for j in xrange(i+1,len(reps)):398assert reps[i] * ~reps[j] not in G399assert reps[j] * ~reps[i] not in G400401reps,gens,s2,s3 = G.todd_coxeter_s2_s3()402assert reps[0] == SL2Z([1,0,0,1])403assert len(reps) == G.index()404for i in xrange(1,len(reps)):405assert reps[i] not in G406assert reps[i]*S2m*~reps[s2[i]] in G407assert reps[i]*S3m*~reps[s3[i]] in G408for j in xrange(i+1,len(reps)):409assert reps[i] * ~reps[j] not in G410assert reps[j] * ~reps[i] not in G411412413414