Sage Days 20.5 demonstration -- Misc talks, demos, tutorials, ... using Sage v4.3.4 system:sage

Sage Days 20.5 demonstration

{{{id=0| %hide pretty_print_default() /// }}}

A demonstration of Sage + GAP4 + GAP3 + Chevie + Semigroupe

Let us create the Coxeter group W:

{{{id=1| W = CoxeterGroup(["H",4]); W /// }}}

It is constructed as a group of permutations, from root data given by GAP3+Chevie (thanks to Franco’s interface):

sage: W._gap_group CoxeterGroup(“H”,4) sage: (W._gap_group).parent() Gap3

with operations on permutations implemented in Sage:

{{{id=2| W.an_element()^3 /// (1,5)(2,62)(3,7)(6,9)(8,12)(11,15)(13,17)(16,20)(18,22)(21,25)(26,29)(28,31)(30,33)(32,35)(34,37)(36,39)(38,41)(42,45)(46,48)(47,49)(50,52)(55,56)(57,58)(61,65)(63,67)(66,69)(68,72)(71,75)(73,77)(76,80)(78,82)(81,85)(86,89)(88,91)(90,93)(92,95)(94,97)(96,99)(98,101)(102,105)(106,108)(107,109)(110,112)(115,116)(117,118) }}}

and group operations implemented in GAP:

{{{id=3| len(W.conjugacy_classes_representatives()) /// 34 }}} {{{id=4| W.cardinality() /// 14400 }}}

Now, assume we want to do intensive computations on this group, requiring heavy access to the left and right Cayley graphs (e.g. Bruhat interval calculations, representation theory, ...). Then we can use Jean-Eric Pin’s Semigroupe, a software written in C:

{{{id=5| S = semigroupe.AutomaticSemigroup(W.semigroup_generators(), W.one(), category = FiniteCoxeterGroups()) /// }}}

The following triggers the full expansion of the group and its Cayley graph in memory:

{{{id=6| S.cardinality() /// 14400 }}}

And we can now iterate through the elements, in length-lexicographic order w.r.t. their reduced word:

{{{id=7| sum( x^p.length() for p in S) /// x^60 + 4*x^59 + 9*x^58 + 16*x^57 + 25*x^56 + 36*x^55 + 49*x^54 + 64*x^53 + 81*x^52 + 100*x^51 + 121*x^50 + 144*x^49 + 168*x^48 + 192*x^47 + 216*x^46 + 240*x^45 + 264*x^44 + 288*x^43 + 312*x^42 + 336*x^41 + 359*x^40 + 380*x^39 + 399*x^38 + 416*x^37 + 431*x^36 + 444*x^35 + 455*x^34 + 464*x^33 + 471*x^32 + 476*x^31 + 478*x^30 + 476*x^29 + 471*x^28 + 464*x^27 + 455*x^26 + 444*x^25 + 431*x^24 + 416*x^23 + 399*x^22 + 380*x^21 + 359*x^20 + 336*x^19 + 312*x^18 + 288*x^17 + 264*x^16 + 240*x^15 + 216*x^14 + 192*x^13 + 168*x^12 + 144*x^11 + 121*x^10 + 100*x^9 + 81*x^8 + 64*x^7 + 49*x^6 + 36*x^5 + 25*x^4 + 16*x^3 + 9*x^2 + 4*x + 1 }}} {{{id=8| S[0:10] /// [[], [0], [1], [2], [3], [0, 1], [0, 2], [0, 3], [1, 0], [1, 2]] }}} {{{id=9| S[-1] /// [0, 1, 0, 1, 0, 2, 0, 1, 0, 1, 2, 0, 1, 0, 2, 3, 2, 0, 1, 0, 1, 2, 0, 1, 0, 2, 3, 2, 0, 1, 0, 1, 2, 0, 1, 0, 2, 3, 2, 0, 1, 0, 1, 2, 0, 1, 0, 2, 3, 2, 0, 1, 0, 1, 2, 0, 1, 0, 2, 3] }}}

The elements of S are handles to C objects from Semigroupe:

{{{id=10| x = S.an_element() x /// [0, 1, 2, 3] }}}

Products are calculated by Semigroupe:

{{{id=11| x * x /// [0, 1, 0, 2, 0, 1, 3, 2] }}}

Powering operations are handled by Sage:

{{{id=12| x^3 /// [0, 1, 0, 2, 0, 1, 0, 2, 3, 2, 0, 1] }}} {{{id=13| x^(10^10000) /// }}}

Altogether, S is a full fledged Sage Coxeter group, which passes all the generic tests:

{{{id=14| TestSuite(S).run(verbose = True, skip = "_test_associativity") /// }}}

And of course it works for general semigroups too, and can further compute much more information about those, like the (Knuth-Bendix completion of the) relations between the generators:

{{{id=15| S.print_relations() /// aa = 1 bb = 1 cb = bc cc = 1 da = ad db = bd dd = 1 cac = aca dcd = cdc dcababcabacdcababcabacdcababcabacdcababcabacdc = cdcababcabacdcababcabacdcababcabacdcababcabacd }}}

which contains the usual commutation + braid relations.

Let’s try now the 0-Hecke monoid:

{{{id=16| from sage.combinat.j_trivial_monoids import * S = semigroupe.AutomaticSemigroup(W.simple_projections(), W.one(), by_action = True) S.cardinality() /// 48 }}} {{{id=17| S.print_relations() /// aa = a bb = b ca = ac cc = c da = ad db = bd dd = d cbc = bcb dcd = cdc ababacbabacbabcdcbabacbabcdcbabacbabcdcbabacbabcdcbabacbabcd = 0 }}}

Let us throw in more mathematical information:

{{{id=18| W = CoxeterGroup(["A",3]) S = semigroupe.AutomaticSemigroup(W.simple_projections(), W.one(), by_action = True, category = FiniteJTrivialMonoids()) /// }}} {{{id=19| S.cardinality() /// }}} {{{id=20| H = S.algebra(QQ) H.orthogonal_idempotents() /// }}}

More about Jtrivial monoids:

{{{id=21| from sage.combinat.j_trivial_monoids import * def pij(j): return lambda i: i if i != j+1 else j pi2 = pij(2) /// }}}
{{{id=22| pi2(1), pi2(2), pi2(3), pi2(4) /// (1, 2, 2, 4) }}}
{{{id=23| class NDPFMonoid(AutomaticMonoid): def __init__(self, n): ambient_monoid = DiscreteFunctions(range(1,n+1), action="right") pi = Family(range(1, n), lambda j: ambient_monoid(pij(j))) AutomaticMonoid.__init__(self, pi, one = ambient_monoid.one(), category = (SubFiniteMonoidsOfFunctions(), FiniteJTrivialMonoids())) Mon = NDPFMonoid(3) Mon.cardinality() /// 5 }}}
{{{id=24| Mon.list() /// [[], [1], [2], [1, 2], [2, 1]] }}}
{{{id=25| [ NDPFMonoid(n).cardinality() for n in range(6)] /// [1, 1, 2, 5, 14, 42] }}}
{{{id=26| MuMon = mupad(Mon); MuMon /// / +- -+ \ | | 0, 1, 2, 3, 4 | | | | | | | | 1, 1, 4, 4, 4 | | | | | | Dom::MMonoid| | 2, 3, 2, 3, 4 | | | | | | | | 3, 3, 4, 4, 4 | | | | | | | | 4, 4, 4, 4, 4 | | \ +- -+ / }}} {{{id=27| MuMon.count() /// 5 }}} {{{id=28| MuAlg = mupad.Dom.MonoidAlgebra(MuMon); MuAlg /// }}} {{{id=29| MuCMat = MuAlg.cartanInvariantsMatrix(); MuCMat /// +- -+ | 1, 0, 0, 0 | | | | 0, 1, 1, 0 | | | | 0, 0, 1, 0 | | | | 0, 0, 0, 1 | +- -+ }}} {{{id=30| MuCMat.sage() /// [1 0 0 0] [0 1 1 0] [0 0 1 0] [0 0 0 1] }}}
{{{id=31| M4 = NDPFMonoid(4) var('q') /// q }}} {{{id=32| cartconj = M4.cartan_matrix(q); cartconj /// [ 1 0 0 0 0 0 0 0] [ 0 1 q q^2 0 0 0 0] [ 0 0 1 q 0 0 0 0] [ 0 0 0 1 0 0 0 0] [ 0 0 0 0 1 0 q 0] [ 0 0 0 0 q 1 q^2 0] [ 0 0 0 0 0 0 1 0] [ 0 0 0 0 0 0 0 1] }}} {{{id=33| cart = M4.cartan_matrix_mupad(q); cart /// [ 1 0 0 0 0 0 0 0] [ 0 1 0 0 q 0 0 0] [ 0 q 1 0 q^2 0 0 0] [ 0 0 0 1 0 q^2 q 0] [ 0 0 0 0 1 0 0 0] [ 0 0 0 0 0 1 0 0] [ 0 0 0 0 0 q 1 0] [ 0 0 0 0 0 0 0 1] }}} {{{id=34| def is_isomorphic_matrices(m1, m2): coeffs1 = set([ c for row in m1 for c in row ]) coeffs2 = set([ c for row in m2 for c in row ]) if coeffs1 != coeffs2: return False f = sage.combinat.ranker.rank_from_list(sorted(coeffs1)) def graph(m): m = matrix([[f(m[i,j]) for j in range(m.ncols()) ] for i in range(m.nrows())]) return DiGraph(m, multiple_edges = True) return graph(m1).is_isomorphic(graph(m2)) /// }}} {{{id=35| is_isomorphic_matrices(cart, cartconj) /// True }}} {{{id=36| P4 = Posets(4); P4 /// Posets containing 4 vertices }}} {{{id=37| P4.cardinality() /// 16 }}} {{{id=38| Pos = P4[9]; Pos.cover_relations() /// [[0, 2], [1, 2], [2, 3]] }}} {{{id=39| #Pos.plot() /// }}} {{{id=40| MP = NDPFMonoidPoset(Pos); MP /// NDPF monoid of Poset ([[0, 2], [1, 2], [2, 3]]) }}} {{{id=41| is_isomorphic_matrices(MP.cartan_matrix(q), MP.cartan_matrix_mupad(q)) /// True }}} {{{id=42| @parallel() def check_conj_parallel(Pos): MP = NDPFMonoidPoset(Pos) return is_isomorphic_matrices(MP.cartan_matrix(q), MP.cartan_matrix_mupad(q)) /// }}} {{{id=43| for (((poset,), _), res) in check_conj_parallel(Posets(3).list()): print poset.cover_relations(), res /// }}} {{{id=44| all(x[1] for x in check_conj_parallel(Posets(4).list())) /// True }}}

We finish with some character ring calculations:

{{{id=45| attach /home/nthiery/work/frg/Articles/Hivert_Schilling_Thiery_HeckeMonoid/main.sage M = BiHeckeMonoid(["A",3]) G = M.character_ring() E = G.E(); T = G.T(); P = G.P() /// }}} {{{id=46| M0 = M.fix_w0_monoid() G0 = M0.character_ring() S0 = G0.S(); P0 = G0.P() /// }}} {{{id=47| for e in P0.basis(): print "Ind(",e, ")=", P(G.induce_from_M0(S0(e))) # indirect doctest /// Ind( P[1234] )= P[1234] Ind( P[2134] )= P[2134] + P[2314] + P[2341] + P[2413] + P[4213] Ind( P[2314] )= P[2314] + P[2341] Ind( P[3214] )= P[3214] + P[3241] + P[3421] Ind( P[2341] )= P[2341] Ind( P[3241] )= P[3241] + P[3421] Ind( P[3421] )= P[3421] Ind( P[4321] )= P[4321] Ind( P[2431] )= P[2431] + P[4231] Ind( P[4231] )= P[4231] Ind( P[1324] )= P[1324] + P[1342] + P[3124] + P[3142] + P[3241] + P[3412] + P[4132] Ind( P[3124] )= P[3124] + P[3142] + P[3241] + P[3412] Ind( P[1342] )= P[1342] + P[3142] + P[3412] + P[4132] Ind( P[3142] )= P[3142] + P[3412] Ind( P[3412] )= P[3412] Ind( P[4312] )= P[4312] Ind( P[1432] )= P[1432] + P[4132] + P[4312] Ind( P[4132] )= P[4132] + P[4312] Ind( P[1243] )= P[1243] + P[1423] + P[2413] + P[2431] + P[4123] Ind( P[2143] )= P[2143] + P[2413] + P[2431] + P[4213] + P[4231] Ind( P[2413] )= P[2413] + P[2431] + P[4213] + P[4231] Ind( P[4213] )= P[4213] + P[4231] Ind( P[1423] )= P[1423] + P[4123] Ind( P[4123] )= P[4123] }}}

Behind the scene, it uses the cutting poset (to convert between translation modules to simple modules), the character formula for projective modules of J-Trivial monoids, the property that simple modules for M0 are induced to translation modules for M, etc. Plus inversion by matrix of linear morphism between finite dimensional vector spaces. It also uses the expansion of the character of a projective module for the BiHecke monoid in term of simple module, but this one is hard-coded for type A3 (currently too expensive to recalculate it). The framework supports q-characters; but few of the rules above are implemented for them, since we do not know them yet

Table Of Contents

Previous topic

SLC 64 demonstration

Next topic

Objects and Classes in Python and Sage

This Page