Hecke triangle group elements¶
AUTHORS:
Jonas Jermann (2014): initial version
- class sage.modular.modform_hecketriangle.hecke_triangle_group_element.HeckeTriangleGroupElement(parent, M, check=True, **kwargs)¶
Bases:
sage.groups.matrix_gps.group_element.MatrixGroupElement_genericElements of HeckeTriangleGroup.
- a()¶
Return the upper left entry of
self.EXAMPLES:
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup sage: U = HeckeTriangleGroup(n=7).U() sage: U.a() lam sage: U.a().parent() Maximal Order in Number Field in lam with defining polynomial x^3 - x^2 - 2*x + 1 with lam = 1.801937735804839?
- acton(tau)¶
Return the image of
tauunder the action ofselfby linear fractional transformations or by conjugation in casetauis an element of the parent ofself.It is possible to act on points of
HyperbolicPlane().Note
There is a 1-1 correspondence between hyperbolic fixed points and the corresponding primitive element in the stabilizer. The action in the two cases above is compatible with this correspondence.
INPUT:
tau– Either an element ofselfor anyelement to which a linear fractional transformation can be applied in the usual way.
In particular
infinityis a possible argument and a possible return value.As mentioned it is also possible to use points of
HyperbolicPlane().
EXAMPLES:
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup sage: G = HeckeTriangleGroup(5) sage: G.S().acton(SR(1 + i/2)) 2/5*I - 4/5 sage: G.S().acton(SR(1 + i/2)).parent() Symbolic Ring sage: G.S().acton(QQbar(1 + i/2)) 2/5*I - 4/5 sage: G.S().acton(QQbar(1 + i/2)).parent() Algebraic Field sage: G.S().acton(i + exp(-2)) -1/(e^(-2) + I) sage: G.S().acton(i + exp(-2)).parent() Symbolic Ring sage: G.T().acton(infinity) == infinity True sage: G.U().acton(infinity) lam sage: G.V(2).acton(-G.lam()) == infinity True sage: G.V(2).acton(G.U()) == G.V(2)*G.U()*G.V(2).inverse() True sage: G.V(2).inverse().acton(G.U()) [ 0 -1] [ 1 lam] sage: p = HyperbolicPlane().PD().get_point(-I/2+1/8) sage: G.V(2).acton(p) Point in PD -((-(47*I + 161)*sqrt(5) - 47*I - 161)/(145*sqrt(5) + 94*I + 177) + I)/(I*(-(47*I + 161)*sqrt(5) - 47*I - 161)/(145*sqrt(5) + 94*I + 177) + 1) sage: bool(G.V(2).acton(p).to_model('UHP').coordinates() == G.V(2).acton(p.to_model('UHP').coordinates())) True sage: p = HyperbolicPlane().PD().get_point(I) sage: G.U().acton(p) Boundary point in PD 1/2*(sqrt(5) - 2*I + 1)/(-1/2*I*sqrt(5) - 1/2*I + 1) sage: G.U().acton(p).to_model('UHP') == HyperbolicPlane().UHP().get_point(G.lam()) True sage: G.U().acton(p) == HyperbolicPlane().UHP().get_point(G.lam()).to_model('PD') True
- as_hyperbolic_plane_isometry(model='UHP')¶
Return
selfas an isometry ofHyperbolicPlane()(in the upper half plane model).EXAMPLES:
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup sage: el = HeckeTriangleGroup(7).V(4) sage: el.as_hyperbolic_plane_isometry() Isometry in UHP [lam^2 - 1 lam] [lam^2 - 1 lam^2 - 1] sage: el.as_hyperbolic_plane_isometry().parent() Set of Morphisms from Hyperbolic plane in the Upper Half Plane Model to Hyperbolic plane in the Upper Half Plane Model in Category of hyperbolic models of Hyperbolic plane sage: el.as_hyperbolic_plane_isometry("KM").parent() Set of Morphisms from Hyperbolic plane in the Klein Disk Model to Hyperbolic plane in the Klein Disk Model in Category of hyperbolic models of Hyperbolic plane
- b()¶
Return the upper right entry of
self.EXAMPLES:
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup sage: U = HeckeTriangleGroup(n=7).U() sage: U.b() -1 sage: U.b().parent() Maximal Order in Number Field in lam with defining polynomial x^3 - x^2 - 2*x + 1 with lam = 1.801937735804839?
- block_decomposition()¶
Return a tuple
(L, R, sgn)such thatself = sgn * R.acton(prod(L)) = sgn * R*prod(L)*R.inverse().In the parabolic and hyperbolic case the tuple entries in
Lare powers of basic block matrices:V(j) = U^(j-1)*T = self.parent().V(j)for1 <= j <= n-1. In the elliptic case the tuple entries are eitherSorU.This decomposition data is (also) described by
_block_decomposition_data().Warning: The case
n=infinityis not verified at all and probably wrong!EXAMPLES:
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup sage: G = HeckeTriangleGroup(n=7) sage: G.element_repr_method("basic") sage: G.T().block_decomposition() ((T,), T^(-1), 1) sage: G.V(2).acton(G.T(-3)).block_decomposition() ((-S*T^(-3)*S,), T, 1) sage: (-G.V(2)^2).block_decomposition() ((T*S*T^2*S*T,), T*S*T, -1) sage: el = (-G.V(2)*G.V(6)*G.V(3)*G.V(2)*G.V(6)*G.V(3)) sage: el.block_decomposition() ((-S*T^(-1)*S, T*S*T*S*T, T*S*T, -S*T^(-1)*S, T*S*T*S*T, T*S*T), T*S*T, -1) sage: (G.U()^4*G.S()*G.V(2)).acton(el).block_decomposition() ((T*S*T, -S*T^(-1)*S, T*S*T*S*T, T*S*T, -S*T^(-1)*S, T*S*T*S*T), T*S*T*S*T*S*T^2*S*T, -1) sage: (G.V(1)^5*G.V(2)*G.V(3)^3).block_decomposition() ((T*S*T*S*T^2*S*T*S*T^2*S*T*S*T, T^5, T*S*T), T^6*S*T, 1) sage: G.element_repr_method("default") sage: (-G.I()).block_decomposition() ( ([1 0] [1 0] [-1 0] [0 1],), [0 1], [ 0 -1] ) sage: G.U().block_decomposition() ( ([lam -1] [1 0] [1 0] [ 1 0],), [0 1], [0 1] ) sage: (-G.S()).block_decomposition() ( ([ 0 -1] [-1 0] [-1 0] [ 1 0],), [ 0 -1], [ 0 -1] ) sage: (G.V(2)*G.V(3)).acton(G.U()^6).block_decomposition() ( ([ 0 1] [-2*lam^2 - 2*lam + 2 -2*lam^2 - 2*lam + 1] [-1 0] [ -1 lam],), [ -2*lam^2 + 1 -2*lam^2 - lam + 2], [ 0 -1] ) sage: (G.U()^(-6)).block_decomposition() ( ([lam -1] [1 0] [-1 0] [ 1 0],), [0 1], [ 0 -1] ) sage: G = HeckeTriangleGroup(n=8) sage: (G.U()^4).block_decomposition() ( ([ lam^2 - 1 -lam^3 + 2*lam] [1 0] [1 0] [ lam^3 - 2*lam -lam^2 + 1],), [0 1], [0 1] ) sage: (G.U()^(-4)).block_decomposition() ( ([ lam^2 - 1 -lam^3 + 2*lam] [1 0] [-1 0] [ lam^3 - 2*lam -lam^2 + 1],), [0 1], [ 0 -1] )
- block_length(primitive=False)¶
Return the block length of
self. The block length is given by the number of factors used for the decomposition of the conjugacy representative ofselfdescribed inprimitive_representative(). In particular the block length is invariant under conjugation.The definition is mostly used for parabolic or hyperbolic elements: In particular it gives a lower bound for the (absolute value of) the trace and the discriminant for primitive hyperbolic elements. Namely
abs(trace) >= lambda * block_lengthanddiscriminant >= block_length^2 * lambda^2 - 4.Warning: The case
n=infinityis not verified at all and probably wrong!INPUT:
primitive– IfTruethen the conjugacyrepresentative of the primitive part is used instead, default:
False.
OUTPUT:
An integer. For hyperbolic elements a non-negative integer. For parabolic elements a negative sign corresponds to taking the inverse. For elliptic elements a (non-trivial) integer with minimal absolute value is choosen. For +- the identity element
0is returned.EXAMPLES:
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup sage: G = HeckeTriangleGroup(n=7) sage: G.T().block_length() 1 sage: G.V(2).acton(G.T(-3)).block_length() 3 sage: G.V(2).acton(G.T(-3)).block_length(primitive=True) 1 sage: (-G.V(2)).block_length() 1 sage: el = -G.V(2)^3*G.V(6)^2*G.V(3) sage: t = el.block_length() sage: D = el.discriminant() sage: trace = el.trace() sage: (trace, D, t) (-124*lam^2 - 103*lam + 68, 65417*lam^2 + 52456*lam - 36300, 6) sage: abs(AA(trace)) >= AA(G.lam()*t) True sage: AA(D) >= AA(t^2 * G.lam() - 4) True sage: (el^3).block_length(primitive=True) == t True sage: el = (G.U()^4*G.S()*G.V(2)).acton(-G.V(2)^3*G.V(6)^2*G.V(3)) sage: t = el.block_length() sage: D = el.discriminant() sage: trace = el.trace() sage: (trace, D, t) (-124*lam^2 - 103*lam + 68, 65417*lam^2 + 52456*lam - 36300, 6) sage: abs(AA(trace)) >= AA(G.lam()*t) True sage: AA(D) >= AA(t^2 * G.lam() - 4) True sage: (el^(-2)).block_length(primitive=True) == t True sage: el = G.V(1)^5*G.V(2)*G.V(3)^3 sage: t = el.block_length() sage: D = el.discriminant() sage: trace = el.trace() sage: (trace, D, t) (284*lam^2 + 224*lam - 156, 330768*lam^2 + 265232*lam - 183556, 9) sage: abs(AA(trace)) >= AA(G.lam()*t) True sage: AA(D) >= AA(t^2 * G.lam() - 4) True sage: (el^(-1)).block_length(primitive=True) == t True sage: (G.V(2)*G.V(3)).acton(G.U()^6).block_length() 1 sage: (G.V(2)*G.V(3)).acton(G.U()^6).block_length(primitive=True) 1 sage: (-G.I()).block_length() 0 sage: G.U().block_length() 1 sage: (-G.S()).block_length() 1
- c()¶
Return the lower left entry of
self.EXAMPLES:
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup sage: U = HeckeTriangleGroup(n=7).U() sage: U.c() 1
- conjugacy_type(ignore_sign=True, primitive=False)¶
Return a unique description of the conjugacy class of
self(by default only up to a sign).Warning: The case
n=infinityis not verified at all and probably wrong!INPUT:
ignore_sign– IfTrue(default) then the conjugacyclasses are only considered up to a sign.
primitive– IfTruethen the conjugacy class ofthe primitive part is considered instead and the sign is ignored, default:
False.
OUTPUT:
A unique representative for the given block data (without the conjugation matrix) among all cyclic permutations. If
ignore_sign=Truethen the sign is excluded as well.EXAMPLES:
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup sage: G = HeckeTriangleGroup(n=7) sage: (-G.I()).conjugacy_type() ((6, 0),) sage: G.U().acton(G.S()).conjugacy_type() (0, 1) sage: (G.U()^4).conjugacy_type() (1, -3) sage: ((G.V(2)*G.V(3)^2*G.V(2)*G.V(3))^2).conjugacy_type() ((3, 2), (2, 1), (3, 1), (2, 1), (3, 2), (2, 1), (3, 1), (2, 1)) sage: (-G.I()).conjugacy_type(ignore_sign=False) (((6, 0),), -1) sage: G.S().conjugacy_type(ignore_sign=False) ((0, 1), 1) sage: (G.U()^4).conjugacy_type(ignore_sign=False) ((1, -3), -1) sage: G.U().acton((G.V(2)*G.V(3)^2*G.V(2)*G.V(3))^2).conjugacy_type(ignore_sign=False) (((3, 2), (2, 1), (3, 1), (2, 1), (3, 2), (2, 1), (3, 1), (2, 1)), 1) sage: (-G.I()).conjugacy_type(primitive=True) ((6, 0),) sage: G.S().conjugacy_type(primitive=True) (0, 1) sage: G.V(2).acton(G.U()^4).conjugacy_type(primitive=True) (1, 1) sage: (G.V(3)^2).conjugacy_type(primitive=True) ((3, 1),) sage: G.S().acton((G.V(2)*G.V(3)^2*G.V(2)*G.V(3))^2).conjugacy_type(primitive=True) ((3, 2), (2, 1), (3, 1), (2, 1))
- continued_fraction()¶
For hyperbolic and parabolic elements: Return the (negative) lambda-continued fraction expansion (lambda-CF) of the (attracting) hyperbolic fixed point of
self.Let
r_j in Zforj >= 0. A finite lambda-CF is defined as:[r_0; r_1, ..., r_k] := (T^(r_0)*S* ... *T^(r_k)*S)(infinity), whereSandTare the generators ofself. An infinite lambda-CF is defined as a corresponding limit value (k->infinity) if it exists.In this case the lambda-CF of parabolic and hyperbolic fixed points are returned which have an eventually periodic lambda-CF. The parabolic elements are exactly those with a cyclic permutation of the period
[2, 1, ..., 1]withn-3ones.Warning: The case
n=infinityis not verified at all and probably wrong!OUTPUT:
A tuple
(preperiod, period)with the preperiod and period tuples of the lambda-CF.EXAMPLES:
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup sage: G = HeckeTriangleGroup(n=7) sage: G.T().continued_fraction() ((0, 1), (1, 1, 1, 1, 2)) sage: G.V(2).acton(G.T(-3)).continued_fraction() ((), (2, 1, 1, 1, 1)) sage: (-G.V(2)).continued_fraction() ((1,), (2,)) sage: (-G.V(2)^3*G.V(6)^2*G.V(3)).continued_fraction() ((1,), (2, 2, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 2)) sage: (G.U()^4*G.S()*G.V(2)).acton(-G.V(2)^3*G.V(6)^2*G.V(3)).continued_fraction() ((1, 1, 1, 2), (2, 2, 2, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1)) sage: (G.V(1)^5*G.V(2)*G.V(3)^3).continued_fraction() ((6,), (2, 1, 2, 1, 2, 1, 7)) sage: G = HeckeTriangleGroup(n=8) sage: G.T().continued_fraction() ((0, 1), (1, 1, 1, 1, 1, 2)) sage: G.V(2).acton(G.T(-3)).continued_fraction() ((), (2, 1, 1, 1, 1, 1)) sage: (-G.V(2)).continued_fraction() ((1,), (2,)) sage: (-G.V(2)^3*G.V(6)^2*G.V(3)).continued_fraction() ((1,), (2, 2, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 2)) sage: (G.U()^4*G.S()*G.V(2)).acton(-G.V(2)^3*G.V(6)^2*G.V(3)).continued_fraction() ((1, 1, 1, 2), (2, 2, 2, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1)) sage: (G.V(1)^5*G.V(2)*G.V(3)^3).continued_fraction() ((6,), (2, 1, 2, 1, 2, 1, 7)) sage: (G.V(2)^3*G.V(5)*G.V(1)*G.V(6)^2*G.V(4)).continued_fraction() ((1,), (2, 2, 2, 1, 1, 1, 3, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 2))
- d()¶
Return the lower right of
self.EXAMPLES:
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup sage: U = HeckeTriangleGroup(n=7).U() sage: U.d() 0
- discriminant()¶
Return the discriminant of
selfwhich corresponds to the discriminant of the corresponding quadratic form ofself.EXAMPLES:
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup sage: G = HeckeTriangleGroup(n=7) sage: G.V(3).discriminant() 4*lam^2 + 4*lam - 4 sage: AA(G.V(3).discriminant()) 16.19566935808922?
- fixed_points(embedded=False, order='default')¶
Return a pair of (mutually conjugate) fixed points of
selfin a possible quadratic extension of the base field.INPUT:
embedded– IfTruethe fixed points are embedded intoAlgebraicRealFieldresp.AlgebraicField. Default:False.
order– Iforder="none"the fixed points are choosenand ordered according to a fixed formula.
If
order="sign"the fixed points are always ordered according to the sign in front of the square root.If
order="default"(default) then in case the fixed points are hyperbolic they are ordered according to the sign of the trace ofselfinstead, such that the attracting fixed point comes first.If
order="trace"the fixed points are always ordered according to the sign of the trace ofself. If the trace is zero they are ordered by the sign in front of the square root. In particular the fixed_points in this case remain the same for-self.
OUTPUT:
If
embedded=Truean element of eitherAlgebraicRealFieldorAlgebraicFieldis returned. Otherwise an element of a relative field extension over the base field of (the parent of)selfis returned.Warning: Relative field extensions don’t support default embeddings. So the correct embedding (which is the positive resp. imaginary positive one) has to be choosen.
EXAMPLES:
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup sage: G = HeckeTriangleGroup(n=infinity) sage: (-G.T(-4)).fixed_points() (+Infinity, +Infinity) sage: (-G.S()).fixed_points() (1/2*e, -1/2*e) sage: p = (-G.S()).fixed_points(embedded=True)[0] sage: p I sage: (-G.S()).acton(p) == p True sage: (-G.V(2)).fixed_points() (1/2*e, -1/2*e) sage: (-G.V(2)).fixed_points() == G.V(2).fixed_points() True sage: p = (-G.V(2)).fixed_points(embedded=True)[1] sage: p -1.732050807568878? sage: (-G.V(2)).acton(p) == p True sage: G = HeckeTriangleGroup(n=7) sage: (-G.S()).fixed_points() (1/2*e, -1/2*e) sage: p = (-G.S()).fixed_points(embedded=True)[1] sage: p -I sage: (-G.S()).acton(p) == p True sage: (G.U()^4).fixed_points() ((1/2*lam^2 - 1/2*lam - 1/2)*e + 1/2*lam, (-1/2*lam^2 + 1/2*lam + 1/2)*e + 1/2*lam) sage: pts = (G.U()^4).fixed_points(order="trace") sage: (G.U()^4).fixed_points() == [pts[1], pts[0]] False sage: (G.U()^4).fixed_points(order="trace") == (-G.U()^4).fixed_points(order="trace") True sage: (G.U()^4).fixed_points() == (G.U()^4).fixed_points(order="none") True sage: (-G.U()^4).fixed_points() == (G.U()^4).fixed_points() True sage: (-G.U()^4).fixed_points(order="none") == pts True sage: p = (G.U()^4).fixed_points(embedded=True)[1] sage: p 0.9009688679024191? - 0.4338837391175581?*I sage: (G.U()^4).acton(p) == p True sage: (-G.V(5)).fixed_points() ((1/2*lam^2 - 1/2*lam - 1/2)*e, (-1/2*lam^2 + 1/2*lam + 1/2)*e) sage: (-G.V(5)).fixed_points() == G.V(5).fixed_points() True sage: p = (-G.V(5)).fixed_points(embedded=True)[0] sage: p 0.6671145837954892? sage: (-G.V(5)).acton(p) == p True
- is_elliptic()¶
Return whether
selfis an elliptic matrix.EXAMPLES:
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup sage: G = HeckeTriangleGroup(n=7) sage: [ G.V(k).is_elliptic() for k in range(1,8) ] [False, False, False, False, False, False, True] sage: G.U().is_elliptic() True
- is_hecke_symmetric()¶
Return whether the conjugacy class of the primitive part of
self, denoted by[gamma]is \(Hecke-symmetric\): I.e. if[gamma] == [gamma^(-1)].This is equivalent to
self.simple_fixed_point_set()being equal with it’s \(Hecke-conjugated\) set (where each fixed point is replaced by the other (\(Hecke-conjugated\)) fixed point.It is also equivalent to
[Q] == [-Q]for the corresponding hyperbolic binary quadratic formQ.The method assumes that
selfis hyperbolic.Warning
The case
n=infinityis not verified at all and probably wrong!EXAMPLES:
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup sage: G = HeckeTriangleGroup(n=5) sage: el = G.V(2) sage: el.is_hecke_symmetric() False sage: (el.simple_fixed_point_set(), el.inverse().simple_fixed_point_set()) ({1/2*e, (-1/2*lam + 1/2)*e}, {-1/2*e, (1/2*lam - 1/2)*e}) sage: el = G.V(3)*G.V(2)^(-1)*G.V(1)*G.V(6) sage: el.is_hecke_symmetric() False sage: el.simple_fixed_point_set() == el.inverse().simple_fixed_point_set() False sage: el = G.V(2)*G.V(3) sage: el.is_hecke_symmetric() True sage: sorted(el.simple_fixed_point_set(), key=str) [(-lam + 3/2)*e + 1/2*lam - 1, (-lam + 3/2)*e - 1/2*lam + 1, (lam - 3/2)*e + 1/2*lam - 1, (lam - 3/2)*e - 1/2*lam + 1] sage: el.simple_fixed_point_set() == el.inverse().simple_fixed_point_set() True
- is_hyperbolic()¶
Return whether
selfis a hyperbolic matrix.EXAMPLES:
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup sage: G = HeckeTriangleGroup(n=7) sage: [ G.V(k).is_hyperbolic() for k in range(1,8) ] [False, True, True, True, True, False, False] sage: G.U().is_hyperbolic() False
- is_identity()¶
Return whether
selfis the identity or minus the identity.EXAMPLES:
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup sage: G = HeckeTriangleGroup(n=7) sage: [ G.V(k).is_identity() for k in range(1,8) ] [False, False, False, False, False, False, False] sage: G.U().is_identity() False
- is_parabolic(exclude_one=False)¶
Return whether
selfis a parabolic matrix.If
exclude_oneis set, then +- the identity element is not considered parabolic.EXAMPLES:
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup sage: G = HeckeTriangleGroup(n=7) sage: [ G.V(k).is_parabolic() for k in range(1,8) ] [True, False, False, False, False, True, False] sage: G.U().is_parabolic() False sage: G.V(6).is_parabolic(exclude_one=True) True sage: G.V(7).is_parabolic(exclude_one=True) False
- is_primitive()¶
Returns whether
selfis primitive. We call an element primitive if (up to a sign and taking inverses) it generates the full stabilizer subgroup of the corresponding fixed point. In the non-elliptic case this means that primitive elements cannot be written as a \(non-trivial\) power of another element.The notion is mostly used for hyperbolic and parabolic elements.
Warning: The case
n=infinityis not verified at all and probably wrong!EXAMPLES:
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup sage: G = HeckeTriangleGroup(n=7) sage: G.V(2).acton(G.T(-1)).is_primitive() True sage: G.T(3).is_primitive() False sage: (-G.V(2)^2).is_primitive() False sage: (G.V(1)^5*G.V(2)*G.V(3)^3).is_primitive() True sage: (-G.I()).is_primitive() True sage: (-G.U()).is_primitive() True sage: (-G.S()).is_primitive() True sage: (G.U()^6).is_primitive() True sage: G = HeckeTriangleGroup(n=8) sage: (G.U()^2).is_primitive() False sage: (G.U()^(-4)).is_primitive() False sage: (G.U()^(-3)).is_primitive() True
- is_reduced(require_primitive=True, require_hyperbolic=True)¶
Returns whether
selfis reduced. We call an element reduced if the associated lambda-CF is purely periodic.I.e. (in the hyperbolic case) if the associated hyperbolic fixed point (resp. the associated hyperbolic binary quadratic form) is reduced.
Note that if
selfis reduced then the element corresponding to the cyclic permutation of the lambda-CF (which is conjugate to the original element) is again reduced. In particular the reduced elements in the conjugacy class ofselfform a finite cycle.Elliptic elements and +- identity are not considered reduced.
Warning: The case
n=infinityis not verified at all and probably wrong!INPUT:
require_primitive– IfTrue(default) then non-primitive elementsare not considered reduced.
require_hyperbolic– IfTrue(default) then non-hyperbolic elementsare not considered reduced.
EXAMPLES:
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup sage: G = HeckeTriangleGroup(n=7) sage: G.I().is_reduced(require_hyperbolic=False) False sage: G.U().reduce().is_reduced(require_hyperbolic=False) False sage: G.T().reduce().is_reduced() False sage: G.T().reduce().is_reduced(require_hyperbolic=False) True sage: (G.V(5)^2).reduce(primitive=False).is_reduced() False sage: (G.V(5)^2).reduce(primitive=False).is_reduced(require_primitive=False) True sage: G.V(5).reduce().is_reduced() True sage: (-G.V(2)).reduce().is_reduced() True sage: (-G.V(2)^3*G.V(6)^2*G.V(3)).reduce().is_reduced() True sage: (G.U()^4*G.S()*G.V(2)).acton(-G.V(2)^3*G.V(6)^2*G.V(3)).reduce().is_reduced() True
- is_reflection()¶
Return whether
selfis the usual reflection on the unit circle.EXAMPLES:
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup sage: (-HeckeTriangleGroup(n=7).S()).is_reflection() True sage: HeckeTriangleGroup(n=7).U().is_reflection() False
- is_simple()¶
Return whether
selfis simple. We call an element simple if it is hyperbolic, primitive, has positive sign and if the associated hyperbolic fixed points satisfy:alpha' < 0 < alphawherealphais the attracting fixed point for the element.I.e. if the associated hyperbolic fixed point (resp. the associated hyperbolic binary quadratic form) is simple.
There are only finitely many simple elements for a given discriminant. They can be used to provide explicit descriptions of rational period functions.
Warning: The case
n=infinityis not verified at all and probably wrong!EXAMPLES:
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup sage: G = HeckeTriangleGroup(n=5) sage: el = G.V(2) sage: el.is_simple() True sage: R = el.simple_elements() sage: [v.is_simple() for v in R] [True] sage: (fp1, fp2) = R[0].fixed_points(embedded=True) sage: (fp1, fp2) (1.272019649514069?, -1.272019649514069?) sage: fp2 < 0 < fp1 True sage: el = G.V(3)*G.V(2)^(-1)*G.V(1)*G.V(6) sage: el.is_simple() False sage: R = el.simple_elements() sage: [v.is_simple() for v in R] [True, True] sage: (fp1, fp2) = R[1].fixed_points(embedded=True) sage: fp2 < 0 < fp1 True sage: el = G.V(1)^2*G.V(2)*G.V(4) sage: el.is_simple() True sage: R = el.simple_elements() sage: el in R True sage: [v.is_simple() for v in R] [True, True, True, True] sage: (fp1, fp2) = R[2].fixed_points(embedded=True) sage: fp2 < 0 < fp1 True
- is_translation(exclude_one=False)¶
Return whether
selfis a translation. Ifexclude_one = True, then the identity map is not considered as a translation.EXAMPLES:
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup sage: (-HeckeTriangleGroup(n=7).T(-4)).is_translation() True sage: (-HeckeTriangleGroup(n=7).I()).is_translation() True sage: (-HeckeTriangleGroup(n=7).I()).is_translation(exclude_one=True) False
- linking_number()¶
Let
gdenote a holomorphic primitive ofE2in the sense:lambda/(2*pi*i) d/dz g = E2. Letgamma=selfand letM_gamma(z)beLog((c*z+d) * sgn(a+d))ifc, a+d > 0, resp.Log((c*z+d) / i*sgn(c))ifa+d = 0, c!=0, resp.0ifc=0. Letk=4 * n / (n-2), then:g(gamma.acton(z) - g(z) - k*M_gamma(z)is equal to2*pi*i / (n-2) * self.linking_number().In particular it is independent of
zand a conjugacy invariant.If
selfis hyperbolic then in the classical casen=3this is the linking number of the closed geodesic (corresponding toself) with the trefoil knot.EXAMPLES:
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup sage: from sage.modular.modform_hecketriangle.space import QuasiModularForms sage: def E2_primitive(z, n=3, prec=10, num_prec=53): ....: G = HeckeTriangleGroup(n=n) ....: MF = QuasiModularForms(group=G, k=2, ep=-1) ....: q = MF.get_q(prec=prec) ....: int_series = integrate((MF.E2().q_expansion(prec=prec) - 1) / q) ....: t_const = (2*pi*i/G.lam()).n(num_prec) ....: d = MF.get_d(fix_d=True, d_num_prec=num_prec) ....: q = exp(t_const * z) ....: return t_const*z + sum([(int_series.coefficients()[m]).subs(d=d) * q**int_series.exponents()[m] for m in range(len(int_series.coefficients()))]) sage: def M(gamma, z, num_prec=53): ....: a = ComplexField(num_prec)(gamma.a()) ....: b = ComplexField(num_prec)(gamma.b()) ....: c = ComplexField(num_prec)(gamma.c()) ....: d = ComplexField(num_prec)(gamma.d()) ....: if c == 0: ....: return 0 ....: elif a + d == 0: ....: return log(-i.n(num_prec)*(c*z + d)*sign(c)) ....: else: ....: return log((c*z+d)*sign(a+d)) sage: def num_linking_number(A, z, n=3, prec=10, num_prec=53): ....: z = z.n(num_prec) ....: k = 4 * n / (n - 2) ....: return (n-2) / (2*pi*i).n(num_prec) * (E2_primitive(A.acton(z), n=n, prec=prec, num_prec=num_prec) - E2_primitive(z, n=n, prec=prec, num_prec=num_prec) - k*M(A, z, num_prec=num_prec)) sage: G = HeckeTriangleGroup(8) sage: z = i sage: for A in [G.S(), G.T(), G.U(), G.U()^(G.n()//2), G.U()^(-3)]: ....: print("A={}: ".format(A.string_repr("conj"))) ....: num_linking_number(A, z, G.n()) ....: A.linking_number() A=[S]: 0.000000000000... 0 A=[V(1)]: 6.000000000000... 6 A=[U]: -2.00000000000... -2 A=[U^4]: 0.596987639289... + 0.926018962976...*I 0 A=[U^(-3)]: 5.40301236071... + 0.926018962976...*I 6 sage: z = ComplexField(1000)(- 2.3 + 3.1*i) sage: B = G.I() sage: for A in [G.S(), G.T(), G.U(), G.U()^(G.n()//2), G.U()^(-3)]: ....: print("A={}: ".format(A.string_repr("conj"))) ....: num_linking_number(B.acton(A), z, G.n(), prec=100, num_prec=1000).n(53) ....: B.acton(A).linking_number() A=[S]: 6.63923483989...e-31 + 2.45195568651...e-30*I 0 A=[V(1)]: 6.000000000000... 6 A=[U]: -2.00000000000... + 2.45195568651...e-30*I -2 A=[U^4]: 0.00772492873864... + 0.00668936643212...*I 0 A=[U^(-3)]: 5.99730551444... + 0.000847636355069...*I 6 sage: z = ComplexField(5000)(- 2.3 + 3.1*i) sage: B = G.U() sage: for A in [G.S(), G.T(), G.U(), G.U()^(G.n()//2), G.U()^(-3)]: # long time ....: print("A={}: ".format(A.string_repr("conj"))) ....: num_linking_number(B.acton(A), z, G.n(), prec=200, num_prec=5000).n(53) ....: B.acton(A).linking_number() A=[S]: -7.90944791339...e-34 - 9.38956758807...e-34*I 0 A=[V(1)]: 5.99999997397... - 5.96520311160...e-8*I 6 A=[U]: -2.00000000000... - 1.33113963568...e-61*I -2 A=[U^4]: -2.32704571946...e-6 + 5.91899385948...e-7*I 0 A=[U^(-3)]: 6.00000032148... - 1.82676936467...e-7*I 6 sage: A = G.V(2)*G.V(3) sage: B = G.I() sage: num_linking_number(B.acton(A), z, G.n(), prec=200, num_prec=5000).n(53) # long time 6.00498424588... - 0.00702329345176...*I sage: A.linking_number() 6 The numerical properties for anything larger are basically too bad to make nice further tests...
- primitive_part(method='cf')¶
Return the primitive part of
self. I.e. a group elementAwith non-negative trace such thatself = sign * A^power, wheresign = self.sign()is +- the identity (to correct the sign) andpower = self.primitive_power().The primitive part itself is choosen such that it cannot be written as a non-trivial power of another element. It is a generator of the stabilizer of the corresponding (attracting) fixed point.
If
selfis elliptic then the primitive part is chosen as a conjugate ofSorU.Warning: The case
n=infinityis not verified at all and probably wrong!INPUT:
method– The method used to determine the primitivepart (see
primitive_representative()), default: “cf”. The parameter is ignored for elliptic elements or +- the identity.The result should not depend on the method.
OUTPUT:
The primitive part as a group element of
self.EXAMPLES:
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup sage: G = HeckeTriangleGroup(n=7) sage: G.element_repr_method("block") sage: G.T().primitive_part() (T^(-1)*S) * (V(6)) * (T^(-1)*S)^(-1) sage: G.V(2).acton(G.T(-3)).primitive_part() (T) * (V(6)) * (T)^(-1) sage: (-G.V(2)).primitive_part() (T*S*T) * (V(2)) * (T*S*T)^(-1) sage: (-G.V(2)^3*G.V(6)^2*G.V(3)).primitive_part() V(2)^3*V(6)^2*V(3) sage: (G.U()^4*G.S()*G.V(2)).acton(-G.V(2)^3*G.V(6)^2*G.V(3)).primitive_part() (T*S*T*S*T*S*T^2*S*T) * (V(2)^3*V(6)^2*V(3)) * (T*S*T*S*T*S*T^2*S*T)^(-1) sage: (G.V(1)^5*G.V(2)*G.V(3)^3).primitive_part() (T^6*S*T) * (V(3)^3*V(1)^5*V(2)) * (T^6*S*T)^(-1) sage: (G.V(2)*G.V(3)).acton(G.U()^6).primitive_part() (-T*S*T^2*S*T*S*T) * (U) * (-T*S*T^2*S*T*S*T)^(-1) sage: (-G.I()).primitive_part() 1 sage: G.U().primitive_part() U sage: (-G.S()).primitive_part() S sage: el = (G.V(2)*G.V(3)).acton(G.U()^6) sage: el.primitive_part() (-T*S*T^2*S*T*S*T) * (U) * (-T*S*T^2*S*T*S*T)^(-1) sage: el.primitive_part() == el.primitive_part(method="block") True sage: G.T().primitive_part() (T^(-1)*S) * (V(6)) * (T^(-1)*S)^(-1) sage: G.T().primitive_part(method="block") (T^(-1)) * (V(1)) * (T^(-1))^(-1) sage: G.V(2).acton(G.T(-3)).primitive_part() == G.V(2).acton(G.T(-3)).primitive_part(method="block") True sage: (-G.V(2)).primitive_part() == (-G.V(2)).primitive_part(method="block") True sage: el = -G.V(2)^3*G.V(6)^2*G.V(3) sage: el.primitive_part() == el.primitive_part(method="block") True sage: el = (G.U()^4*G.S()*G.V(2)).acton(-G.V(2)^3*G.V(6)^2*G.V(3)) sage: el.primitive_part() == el.primitive_part(method="block") True sage: el=G.V(1)^5*G.V(2)*G.V(3)^3 sage: el.primitive_part() == el.primitive_part(method="block") True sage: G.element_repr_method("default")
- primitive_power(method='cf')¶
Return the primitive power of
self. I.e. an integerpowersuch thatself = sign * primitive_part^power, wheresign = self.sign()andprimitive_part = self.primitive_part(method).Warning: For the parabolic case the sign depends on the method: The “cf” method may return a negative power but the “block” method never will.
Warning: The case
n=infinityis not verified at all and probably wrong!INPUT:
method– The method used to determine the primitivepower (see
primitive_representative()), default: “cf”. The parameter is ignored for elliptic elements or +- the identity.
OUTPUT:
An integer. For +- the identity element
0is returned, for parabolic and hyperbolic elements a positive integer. And for elliptic elements a (non-zero) integer with minimal absolute value such thatprimitive_part^powerstill has a positive sign.EXAMPLES:
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup sage: G = HeckeTriangleGroup(n=7) sage: G.T().primitive_power() -1 sage: G.V(2).acton(G.T(-3)).primitive_power() 3 sage: (-G.V(2)^2).primitive_power() 2 sage: el = (-G.V(2)*G.V(6)*G.V(3)*G.V(2)*G.V(6)*G.V(3)) sage: el.primitive_power() 2 sage: (G.U()^4*G.S()*G.V(2)).acton(el).primitive_power() 2 sage: (G.V(2)*G.V(3)).acton(G.U()^6).primitive_power() -1 sage: G.V(2).acton(G.T(-3)).primitive_power() == G.V(2).acton(G.T(-3)).primitive_power(method="block") True sage: (-G.I()).primitive_power() 0 sage: G.U().primitive_power() 1 sage: (-G.S()).primitive_power() 1 sage: el = (G.V(2)*G.V(3)).acton(G.U()^6) sage: el.primitive_power() -1 sage: el.primitive_power() == (-el).primitive_power() True sage: (G.U()^(-6)).primitive_power() 1 sage: G = HeckeTriangleGroup(n=8) sage: (G.U()^4).primitive_power() 4 sage: (G.U()^(-4)).primitive_power() 4
- primitive_representative(method='block')¶
Return a tuple
(P, R)which gives the decomposition of the primitive part ofself, namelyR*P*R.inverse()into a specific representativePand the corresponding conjugation matrixR(the result depends on the method used).Together they describe the primitive part of self. I.e. an element which is equal to
selfup to a sign after taking the appropriate power.See
_primitive_block_decomposition_data()for a description about the representative in case the default methodblockis used. Also seeprimitive_part()to construct the primitive part ofself.Warning: The case
n=infinityis not verified at all and probably wrong!INPUT:
method–block(default) orcf. The methodused to determine
PandR. Ifselfis elliptic this parameter is ignored and ifselfis +- the identity then theblockmethod is used.With
blockthe decomposition described in_primitive_block_decomposition_data()is used.With
cfa reduced representative from the lambda-CF ofselfis used (seecontinued_fraction()). In that casePcorresponds to the period andRto the preperiod.
OUTPUT:
A tuple
(P, R)of group elements such thatR*P*R.inverse()is a/the primitive part ofselfEXAMPLES:
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup sage: G = HeckeTriangleGroup(n=7) sage: G.element_repr_method("basic") sage: el = G.T().primitive_representative(method="cf") sage: el (S*T^(-1)*S*T^(-1)*S*T*S, S*T*S) sage: (el[0]).is_primitive() True sage: el = G.V(2).acton(G.T(-3)).primitive_representative(method="cf") sage: el (-T*S*T^(-1)*S*T^(-1), 1) sage: (el[0]).is_primitive() True sage: el = (-G.V(2)).primitive_representative(method="cf") sage: el (T^2*S, T*S) sage: (el[0]).is_primitive() True sage: el = (-G.V(2)^3*G.V(6)^2*G.V(3)).primitive_representative(method="cf") sage: el (-T^2*S*T^2*S*T*S*T^(-2)*S*T*S*T*S*T^2*S, T*S) sage: (el[0]).is_primitive() True sage: el = (G.U()^4*G.S()*G.V(2)).acton(-G.V(2)^3*G.V(6)^2*G.V(3)).primitive_representative(method="cf") sage: el (-T^2*S*T^2*S*T^2*S*T*S*T^(-2)*S*T*S*T*S, T*S*T*S*T*S*T^2*S) sage: (el[0]).is_primitive() True sage: el = (G.V(1)^5*G.V(2)*G.V(3)^3).primitive_representative(method="cf") sage: el (T^2*S*T*S*T^2*S*T*S*T^2*S*T*S*T^7*S, T^6*S) sage: (el[0]).is_primitive() True sage: el = (G.V(2)*G.V(3)).acton(G.U()^6).primitive_representative(method="cf") sage: el (T*S, -T*S*T^2*S*T*S*T) sage: (el[0]).is_primitive() True sage: G.element_repr_method("block") sage: el = G.T().primitive_representative() sage: (el[0]).is_primitive() True sage: el = G.V(2).acton(G.T(-3)).primitive_representative() sage: el ((-S*T^(-1)*S) * (V(6)) * (-S*T^(-1)*S)^(-1), (T^(-1)) * (V(1)) * (T^(-1))^(-1)) sage: (el[0]).is_primitive() True sage: el = (-G.V(2)).primitive_representative() sage: el ((T*S*T) * (V(2)) * (T*S*T)^(-1), (T*S*T) * (V(2)) * (T*S*T)^(-1)) sage: (el[0]).is_primitive() True sage: el = (-G.V(2)^3*G.V(6)^2*G.V(3)).primitive_representative() sage: el (V(2)^3*V(6)^2*V(3), 1) sage: (el[0]).is_primitive() True sage: el = (G.U()^4*G.S()*G.V(2)).acton(-G.V(2)^3*G.V(6)^2*G.V(3)).primitive_representative() sage: el (V(2)^3*V(6)^2*V(3), (T*S*T*S*T*S*T) * (V(2)*V(4)) * (T*S*T*S*T*S*T)^(-1)) sage: (el[0]).is_primitive() True sage: el = (G.V(1)^5*G.V(2)*G.V(3)^3).primitive_representative() sage: el (V(3)^3*V(1)^5*V(2), (T^6*S*T) * (V(1)^5*V(2)) * (T^6*S*T)^(-1)) sage: (el[0]).is_primitive() True sage: G.element_repr_method("default") sage: el = G.I().primitive_representative() sage: el ( [1 0] [1 0] [0 1], [0 1] ) sage: (el[0]).is_primitive() True sage: el = G.U().primitive_representative() sage: el ( [lam -1] [1 0] [ 1 0], [0 1] ) sage: (el[0]).is_primitive() True sage: el = (-G.S()).primitive_representative() sage: el ( [ 0 -1] [-1 0] [ 1 0], [ 0 -1] ) sage: (el[0]).is_primitive() True sage: el = (G.V(2)*G.V(3)).acton(G.U()^6).primitive_representative() sage: el ( [lam -1] [-2*lam^2 - 2*lam + 2 -2*lam^2 - 2*lam + 1] [ 1 0], [ -2*lam^2 + 1 -2*lam^2 - lam + 2] ) sage: (el[0]).is_primitive() True
- rational_period_function(k)¶
The method assumes that
selfis hyperbolic.Return the rational period function of weight
kfor the primitive conjugacy class ofself.A \(rational period function\) of weight
kis a rational functionqwhich satisfies:q + q|S == 0andq + q|U + q|U^2 + ... + q|U^(n-1) == 0, whereS = self.parent().S(),U = self.parent().U()and|is the usual \(slash-operator\) of weight \(k\). Note that ifk < 0thenqis a polynomial.This method returns a very basic rational period function associated with the primitive conjugacy class of
self. The (strong) expectation is that all rational period functions are formed by linear combinations of such functions.There is also a close relation with modular integrals of weight
2-kand sometimes2-kis used for the weight instead ofk.Warning: The case
n=infinityis not verified at all and probably wrong!EXAMPLES:
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup sage: G = HeckeTriangleGroup(n=5) sage: S = G.S() sage: U = G.U() sage: def is_rpf(f, k=None): ....: if not f + S.slash(f, k=k) == 0: ....: return False ....: if not sum([(U^m).slash(f, k=k) for m in range(G.n())]) == 0: ....: return False ....: return True sage: z = PolynomialRing(G.base_ring(), 'z').gen() sage: [is_rpf(1 - z^(-k), k=k) for k in range(-6, 6, 2)] # long time [True, True, True, True, True, True] sage: [is_rpf(1/z, k=k) for k in range(-6, 6, 2)] [False, False, False, False, True, False] sage: el = G.V(2) sage: el.is_hecke_symmetric() False sage: rpf = el.rational_period_function(-4) sage: is_rpf(rpf) == is_rpf(rpf, k=-4) True sage: is_rpf(rpf) True sage: is_rpf(rpf, k=-6) False sage: is_rpf(rpf, k=2) False sage: rpf -lam*z^4 + lam sage: rpf = el.rational_period_function(-2) sage: is_rpf(rpf) True sage: rpf (lam + 1)*z^2 - lam - 1 sage: el.rational_period_function(0) == 0 True sage: rpf = el.rational_period_function(2) sage: is_rpf(rpf) True sage: rpf ((lam + 1)*z^2 - lam - 1)/(lam*z^4 + (-lam - 2)*z^2 + lam) sage: el = G.V(3)*G.V(2)^(-1)*G.V(1)*G.V(6) sage: el.is_hecke_symmetric() False sage: rpf = el.rational_period_function(-6) sage: is_rpf(rpf) True sage: rpf (68*lam + 44)*z^6 + (-24*lam - 12)*z^4 + (24*lam + 12)*z^2 - 68*lam - 44 sage: rpf = el.rational_period_function(-2) sage: is_rpf(rpf) True sage: rpf (4*lam + 4)*z^2 - 4*lam - 4 sage: el.rational_period_function(0) == 0 True sage: rpf = el.rational_period_function(2) sage: is_rpf(rpf) == is_rpf(rpf, k=2) True sage: is_rpf(rpf) True sage: rpf.denominator() (8*lam + 5)*z^8 + (-94*lam - 58)*z^6 + (199*lam + 124)*z^4 + (-94*lam - 58)*z^2 + 8*lam + 5 sage: el = G.V(2)*G.V(3) sage: el.is_hecke_symmetric() True sage: el.rational_period_function(-4) == 0 True sage: rpf = el.rational_period_function(-2) sage: is_rpf(rpf) True sage: rpf (8*lam + 4)*z^2 - 8*lam - 4 sage: el.rational_period_function(0) == 0 True sage: rpf = el.rational_period_function(2) sage: is_rpf(rpf) True sage: rpf.denominator() (144*lam + 89)*z^8 + (-618*lam - 382)*z^6 + (951*lam + 588)*z^4 + (-618*lam - 382)*z^2 + 144*lam + 89 sage: el.rational_period_function(4) == 0 True
- reduce(primitive=True)¶
Return a reduced version of
self(with the same the same fixed points). Also seeis_reduced().If
selfis elliptic (or +- the identity) the result is never reduced (by definition). Instead a more canonical conjugation representative ofself(resp. it’s primitive part) is choosen.Warning: The case
n=infinityis not verified at all and probably wrong!INPUT:
primitive– IfTrue(default) then a primitiverepresentative for
selfis returned.
EXAMPLES:
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup sage: G = HeckeTriangleGroup(n=7) sage: print(G.T().reduce().string_repr("basic")) S*T^(-1)*S*T^(-1)*S*T*S sage: G.T().reduce().is_reduced(require_hyperbolic=False) True sage: print(G.V(2).acton(-G.T(-3)).reduce().string_repr("basic")) -T*S*T^(-1)*S*T^(-1) sage: print(G.V(2).acton(-G.T(-3)).reduce(primitive=False).string_repr("basic")) T*S*T^(-3)*S*T^(-1) sage: print((-G.V(2)).reduce().string_repr("basic")) T^2*S sage: (-G.V(2)).reduce().is_reduced() True sage: print((-G.V(2)^3*G.V(6)^2*G.V(3)).reduce().string_repr("block")) (-S*T^(-1)) * (V(2)^3*V(6)^2*V(3)) * (-S*T^(-1))^(-1) sage: (-G.V(2)^3*G.V(6)^2*G.V(3)).reduce().is_reduced() True sage: print((-G.I()).reduce().string_repr("block")) 1 sage: print(G.U().reduce().string_repr("block")) U sage: print((-G.S()).reduce().string_repr("block")) S sage: print((G.V(2)*G.V(3)).acton(G.U()^6).reduce().string_repr("block")) U sage: print((G.V(2)*G.V(3)).acton(G.U()^6).reduce(primitive=False).string_repr("block")) -U^(-1)
- reduced_elements()¶
Return the cycle of reduced elements in the (primitive) conjugacy class of
self.I.e. the set (cycle) of all reduced elements which are conjugate to
self.primitive_part(). E.g.self.primitive_representative().reduce().Also see
is_reduced(). In particular the result of this method only depends on the (primitive) conjugacy class ofself.The method assumes that
selfis hyperbolic or parabolic.Warning: The case
n=infinityis not verified at all and probably wrong!EXAMPLES:
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup sage: G = HeckeTriangleGroup(n=5) sage: G.element_repr_method("basic") sage: el = G.V(1) sage: el.continued_fraction() ((0, 1), (1, 1, 2)) sage: R = el.reduced_elements() sage: R [T*S*T*S*T^2*S, T*S*T^2*S*T*S, -T*S*T^(-1)*S*T^(-1)] sage: [v.continued_fraction() for v in R] [((), (1, 1, 2)), ((), (1, 2, 1)), ((), (2, 1, 1))] sage: el = G.V(3)*G.V(2)^(-1)*G.V(1)*G.V(6) sage: el.continued_fraction() ((1,), (3,)) sage: R = el.reduced_elements() sage: [v.continued_fraction() for v in R] [((), (3,))] sage: G.element_repr_method("default")
- root_extension_embedding(K=None)¶
Return the correct embedding from the root extension field to
K.INPUT:
K– A field to which we want the (correct) embedding.If
K=None(default) thenAlgebraicField()is used for elliptic elements andAlgebraicRealField()otherwise.
EXAMPLES:
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup sage: G = HeckeTriangleGroup(n=infinity) sage: fp = (-G.S()).fixed_points()[0] sage: alg_fp = (-G.S()).root_extension_embedding()(fp) sage: alg_fp 1*I sage: alg_fp == (-G.S()).fixed_points(embedded=True)[0] True sage: fp = (-G.V(2)).fixed_points()[1] sage: alg_fp = (-G.V(2)).root_extension_embedding()(fp) sage: alg_fp -1.732050807568...? sage: alg_fp == (-G.V(2)).fixed_points(embedded=True)[1] True sage: fp = (-G.V(2)).fixed_points()[0] sage: alg_fp = (-G.V(2)).root_extension_embedding()(fp) sage: alg_fp 1.732050807568...? sage: alg_fp == (-G.V(2)).fixed_points(embedded=True)[0] True sage: G = HeckeTriangleGroup(n=7) sage: fp = (-G.S()).fixed_points()[1] sage: alg_fp = (-G.S()).root_extension_embedding()(fp) sage: alg_fp 0.?... - 1.000000000000...?*I sage: alg_fp == (-G.S()).fixed_points(embedded=True)[1] True sage: fp = (-G.U()^4).fixed_points()[0] sage: alg_fp = (-G.U()^4).root_extension_embedding()(fp) sage: alg_fp 0.9009688679024...? + 0.4338837391175...?*I sage: alg_fp == (-G.U()^4).fixed_points(embedded=True)[0] True sage: (-G.U()^4).root_extension_embedding(CC)(fp) 0.900968867902... + 0.433883739117...*I sage: (-G.U()^4).root_extension_embedding(CC)(fp).parent() Complex Field with 53 bits of precision sage: fp = (-G.V(5)).fixed_points()[1] sage: alg_fp = (-G.V(5)).root_extension_embedding()(fp) sage: alg_fp -0.6671145837954...? sage: alg_fp == (-G.V(5)).fixed_points(embedded=True)[1] True
- root_extension_field()¶
Return a field extension which contains the fixed points of
self. Namely the root extension field of the parent for the discriminant ofself. Also see the parent methodroot_extension_field(D)androot_extension_embedding()(which provides the correct embedding).EXAMPLES:
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup sage: G = HeckeTriangleGroup(n=infinity) sage: G.V(3).discriminant() 32 sage: G.V(3).root_extension_field() == G.root_extension_field(32) True sage: G.T().root_extension_field() == G.root_extension_field(G.T().discriminant()) == G.base_field() True sage: (G.S()).root_extension_field() == G.root_extension_field(G.S().discriminant()) True sage: G = HeckeTriangleGroup(n=7) sage: D = G.V(3).discriminant() sage: D 4*lam^2 + 4*lam - 4 sage: G.V(3).root_extension_field() == G.root_extension_field(D) True sage: G.U().root_extension_field() == G.root_extension_field(G.U().discriminant()) True sage: G.V(1).root_extension_field() == G.base_field() True
- sign()¶
Return the sign element/matrix (+- identity) of
self. The sign is given by the sign of the trace. if the trace is zero it is instead given by the sign of the lower left entry.EXAMPLES:
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup sage: G = HeckeTriangleGroup(n=7) sage: (-G.T(-1)).sign() [-1 0] [ 0 -1] sage: G.S().sign() [1 0] [0 1] sage: (-G.S()).sign() [-1 0] [ 0 -1] sage: (G.U()^6).sign() [-1 0] [ 0 -1] sage: G = HeckeTriangleGroup(n=8) sage: (G.U()^4).trace() 0 sage: (G.U()^4).sign() [1 0] [0 1] sage: (G.U()^(-4)).sign() [-1 0] [ 0 -1]
- simple_elements()¶
Return all simple elements in the primitive conjugacy class of
self.I.e. the set of all simple elements which are conjugate to
self.primitive_part().Also see
is_simple(). In particular the result of this method only depends on the (primitive) conjugacy class ofself.The method assumes that
selfis hyperbolic.Warning: The case
n=infinityis not verified at all and probably wrong!EXAMPLES:
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup sage: G = HeckeTriangleGroup(n=5) sage: el = G.V(2) sage: el.continued_fraction() ((1,), (2,)) sage: R = el.simple_elements() sage: R [ [lam lam] [ 1 lam] ] sage: R[0].is_simple() True sage: el = G.V(3)*G.V(2)^(-1)*G.V(1)*G.V(6) sage: el.continued_fraction() ((1,), (3,)) sage: R = el.simple_elements() sage: R [ [ 2*lam 2*lam + 1] [ lam 2*lam + 1] [ 1 lam], [ 1 2*lam] ] sage: [v.is_simple() for v in R] [True, True] sage: el = G.V(1)^2*G.V(2)*G.V(4) sage: el.discriminant() 135*lam + 86 sage: R = el.simple_elements() sage: R [ [ 3*lam 3*lam + 2] [8*lam + 3 3*lam + 2] [5*lam + 2 9*lam + 6] [3*lam + 4 6*lam + 3], [ lam + 2 lam], [ lam + 2 4*lam + 1], [2*lam + 1 7*lam + 4] [ lam + 2 7*lam + 2] ]
This agrees with the results (p.16) from Culp-Ressler on binary quadratic forms for Hecke triangle groups:
sage: [v.continued_fraction() for v in R] [((1,), (1, 1, 4, 2)), ((3,), (2, 1, 1, 4)), ((2,), (2, 1, 1, 4)), ((1,), (2, 1, 1, 4))]
- simple_fixed_point_set(extended=True)¶
Return a set of all attracting fixed points in the conjugacy class of the primitive part of
self.If
extended=True(default) then alsoS.acton(alpha)are added foralphain the set.This is a so called \(irreducible system of poles\) for rational period functions for the parent group. I.e. the fixed points occur as a irreducible part of the non-zero pole set of some rational period function and all pole sets are given as a union of such irreducible systems of poles.
The method assumes that
selfis hyperbolic.Warning: The case
n=infinityis not verified at all and probably wrong!EXAMPLES:
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup sage: G = HeckeTriangleGroup(n=5) sage: el = G.V(2) sage: el.simple_fixed_point_set() {1/2*e, (-1/2*lam + 1/2)*e} sage: el.simple_fixed_point_set(extended=False) {1/2*e} sage: el = G.V(3)*G.V(2)^(-1)*G.V(1)*G.V(6) sage: el.simple_fixed_point_set() {(-lam + 3/2)*e + 1/2*lam - 1, (-lam + 3/2)*e - 1/2*lam + 1, 1/2*e - 1/2*lam, 1/2*e + 1/2*lam} sage: el.simple_fixed_point_set(extended=False) {1/2*e - 1/2*lam, 1/2*e + 1/2*lam}
- slash(f, tau=None, k=None)¶
Return the \(slash-operator\) of weight
kto applied tof, evaluated attau. I.e.(f|_k[self])(tau).INPUT:
f– A function intau(or an object for whichevaluation at
self.acton(tau)makes sense.
tau– Where to evaluate the result.This should be a valid argument for
acton().If
tauis a point ofHyperbolicPlane()then its coordinates in the upper half plane model are used.Default:
Nonein which casefhas to be a rational function / polynomial in one variable and the generator of the polynomial ring is used fortau. That wayslashacts on rational functions / polynomials.
k– An even integer.Default:
Nonein which casefeither has to be a rational function / polynomial in one variable (then -degree is used). Orfneeds to have aweightattribute which is then used.
EXAMPLES:
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup sage: from sage.modular.modform_hecketriangle.space import ModularForms sage: G = HeckeTriangleGroup(n=5) sage: E4 = ModularForms(group=G, k=4, ep=1).E4() sage: z = CC(-1/(-1/(2*i+30)-1)) sage: (G.S()).slash(E4, z) 32288.0558881... - 118329.856601...*I sage: (G.V(2)*G.V(3)).slash(E4, z) 32288.0558892... - 118329.856603...*I sage: E4(z) 32288.0558881... - 118329.856601...*I sage: z = HyperbolicPlane().PD().get_point(CC(-I/2 + 1/8)) sage: (G.V(2)*G.V(3)).slash(E4, z) -(21624.437... - 12725.035...*I)/((0.610... + 0.324...*I)*sqrt(5) + 2.720... + 0.648...*I)^4 sage: z = PolynomialRing(G.base_ring(), 'z').gen() sage: rat = z^2 + 1/(z-G.lam()) sage: dr = rat.numerator().degree() - rat.denominator().degree() sage: G.S().slash(rat) == G.S().slash(rat, tau=None, k=-dr) True sage: G.S().slash(rat) (z^6 - lam*z^4 - z^3)/(-lam*z^4 - z^3) sage: G.S().slash(rat, k=0) (z^4 - lam*z^2 - z)/(-lam*z^4 - z^3) sage: G.S().slash(rat, k=-4) (z^8 - lam*z^6 - z^5)/(-lam*z^4 - z^3)
- string_repr(method='default')¶
Return a string representation of
selfusing the specifiedmethod. This method is used to representself. The default representation method can be set for the parent withself.parent().element_repr_method(method).INPUT:
method–default: Use the usual representation method for matrix group elements.basic: The representation is given as a word inSand powers ofT.Note: If
S, Tare defined accordingly the output can be used/evaluated directly to recoverself.conj: The conjugacy representative of the element is representedas a word in powers of the basic blocks, together with an unspecified conjugation matrix.
block: Same asconjbut the conjugation matrix is specified as well.Note: Assuming
S, T, U, Vare defined accordingly the output can directly be used/evaluated to recoverself.
Warning: For
n=infinitythe methodsconjandblockare not verified at all and are probably wrong!EXAMPLES:
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup sage: G = HeckeTriangleGroup(n=5) sage: el1 = -G.I() sage: el2 = G.S()*G.T(3)*G.S()*G.T(-2) sage: el3 = G.V(2)*G.V(3)^2*G.V(4)^3 sage: el4 = G.U()^4 sage: el5 = (G.V(2)*G.T()).acton(-G.S()) sage: el4.string_repr(method="basic") 'S*T^(-1)' sage: G.element_repr_method("default") sage: el1 [-1 0] [ 0 -1] sage: el2 [ -1 2*lam] [ 3*lam -6*lam - 7] sage: el3 [34*lam + 19 5*lam + 4] [27*lam + 18 5*lam + 2] sage: el4 [ 0 -1] [ 1 -lam] sage: el5 [-7*lam - 4 9*lam + 6] [-4*lam - 5 7*lam + 4] sage: G.element_repr_method("basic") sage: el1 -1 sage: el2 S*T^3*S*T^(-2) sage: el3 -T*S*T*S*T^(-1)*S*T^(-2)*S*T^(-4)*S sage: el4 S*T^(-1) sage: el5 T*S*T^2*S*T^(-2)*S*T^(-1) sage: G.element_repr_method("conj") sage: el1 [-1] sage: el2 [-V(4)^2*V(1)^3] sage: el3 [V(3)^2*V(4)^3*V(2)] sage: el4 [-U^(-1)] sage: el5 [-S] sage: G.element_repr_method("block") sage: el1 -1 sage: el2 -(S*T^3) * (V(4)^2*V(1)^3) * (S*T^3)^(-1) sage: el3 (T*S*T) * (V(3)^2*V(4)^3*V(2)) * (T*S*T)^(-1) sage: el4 -U^(-1) sage: el5 -(T*S*T^2) * (S) * (T*S*T^2)^(-1) sage: G.element_repr_method("default") sage: G = HeckeTriangleGroup(n=infinity) sage: el = G.S()*G.T(3)*G.S()*G.T(-2) sage: print(el.string_repr()) [ -1 4] [ 6 -25] sage: print(el.string_repr(method="basic")) S*T^3*S*T^(-2)
- trace()¶
Return the trace of
self, which is the sum of the diagonal entries.EXAMPLES:
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup sage: G = HeckeTriangleGroup(n=7) sage: G.U().trace() lam sage: G.S().trace() 0
- word_S_T()¶
Decompose
selfinto a product of the generatorsSandTof its parent, together with a sign correction matrix, namely:self = sgn * prod(L).Warning: If
selfis +- the identityprod(L)is an empty product which produces1instead of the identity matrix.OUTPUT:
The function returns a tuple
(L, sgn)where the entries ofLare either the generatorSor a non-trivial integer power of the generatorT.sgnis +- the identity.If this decomposition is not possible a
TypeErroris raised.EXAMPLES:
sage: from sage.modular.modform_hecketriangle.hecke_triangle_groups import HeckeTriangleGroup sage: G = HeckeTriangleGroup(n=17) sage: (-G.I()).word_S_T()[0] () sage: (-G.I()).word_S_T()[1] [-1 0] [ 0 -1] sage: (L, sgn) = (-G.V(2)).word_S_T() sage: L ( [ 1 lam] [ 0 -1] [ 1 lam] [ 0 1], [ 1 0], [ 0 1] ) sage: sgn == -G.I() True sage: -G.V(2) == sgn * prod(L) True sage: (L, sgn) = G.U().word_S_T() sage: L ( [ 1 lam] [ 0 -1] [ 0 1], [ 1 0] ) sage: sgn == G.I() True sage: G.U() == sgn * prod(L) True sage: G = HeckeTriangleGroup(n=infinity) sage: (L, sgn) = (-G.V(2)*G.V(3)).word_S_T() sage: L ( [1 2] [ 0 -1] [1 4] [ 0 -1] [1 2] [ 0 -1] [1 2] [0 1], [ 1 0], [0 1], [ 1 0], [0 1], [ 1 0], [0 1] ) sage: -G.V(2)*G.V(3) == sgn * prod(L) True
- sage.modular.modform_hecketriangle.hecke_triangle_group_element.coerce_AA(p)¶
Return the argument first coerced into
AAand then simplified.This leads to a major performance gain with some operations.
EXAMPLES:
sage: from sage.modular.modform_hecketriangle.hecke_triangle_group_element import coerce_AA sage: p = (791264*AA(2*cos(pi/8))^2 - 463492).sqrt() sage: AA(p)._exact_field() Number Field in a with defining polynomial y^8 ... with a in ... sage: coerce_AA(p)._exact_field() Number Field in a with defining polynomial y^4 - 1910*y^2 - 3924*y + 681058 with a in 39.710518724...?
- sage.modular.modform_hecketriangle.hecke_triangle_group_element.cyclic_representative(L)¶
Return a unique representative among all cyclic permutations of the given list/tuple.
INPUT:
L– A list or tuple.
OUTPUT:
The maximal element among all cyclic permutations with respect to lexicographical ordering.
EXAMPLES:
sage: from sage.modular.modform_hecketriangle.hecke_triangle_group_element import cyclic_representative sage: cyclic_representative((1,)) (1,) sage: cyclic_representative((2,2)) (2, 2) sage: cyclic_representative((1,2,1,2)) (2, 1, 2, 1) sage: cyclic_representative((1,2,3,2,3,1)) (3, 2, 3, 1, 1, 2)