From cdc086e5e9c8da9494504a1e16558e8f898b7213 Mon Sep 17 00:00:00 2001 From: Hossein Hadipour Date: Tue, 4 Jul 2023 12:09:12 +0200 Subject: [PATCH 001/231] add the warp's sbox --- src/sage/crypto/sboxes.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/sage/crypto/sboxes.py b/src/sage/crypto/sboxes.py index 056ce082b50..c0c79849b41 100644 --- a/src/sage/crypto/sboxes.py +++ b/src/sage/crypto/sboxes.py @@ -92,7 +92,7 @@ - SERPENT_S0, ..., SERPENT_S7 ([BAK1998]_) - KLEIN ([GNL2011]_) - MIBS ([ISSK2009)] - - Midori_Sb0 (MANTIS, CRAFT), Midori_Sb1 ([BBISHAR2015]_) + - Midori_Sb0 (MANTIS, CRAFT, WARP), Midori_Sb1 ([BBISHAR2015]_) - Noekeon ([DPVAR2000]_) - Piccolo ([SIHMAS2011]_) - Panda ([YWHWXSW2014]_) @@ -1572,6 +1572,7 @@ def monomial_function(n, e): MIBS = SBox([4,15,3,8,13,10,12,0,11,5,7,14,2,6,1,9]) Midori_Sb0 = SBox([0xc,0xa,0xd,0x3,0xe,0xb,0xf,0x7,0x8,0x9,0x1,0x5,0x0,0x2,0x4,0x6]) MANTIS = Midori_Sb0 +WARP = Midori_Sb0 CRAFT = Midori_Sb0 Midori_Sb1 = SBox([0x1,0x0,0x5,0x3,0xe,0x2,0xf,0x7,0xd,0xa,0x9,0xb,0xc,0x8,0x4,0x6]) Noekeon = SBox([0x7,0xA,0x2,0xC,0x4,0x8,0xF,0x0,0x5,0x9,0x1,0xE,0x3,0xD,0xB,0x6]) From 3fb33c32de148f4c458818ad3ba342a60c77089e Mon Sep 17 00:00:00 2001 From: hadipourh Date: Tue, 4 Jul 2023 13:17:49 +0200 Subject: [PATCH 002/231] debugged 'component_function' in the sbox module --- src/sage/crypto/sbox.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/crypto/sbox.pyx b/src/sage/crypto/sbox.pyx index 8f830240844..6dccf702aa5 100644 --- a/src/sage/crypto/sbox.pyx +++ b/src/sage/crypto/sbox.pyx @@ -1286,7 +1286,7 @@ cdef class SBox(SageObject): b = list(b) if len(b) > n: raise ValueError("input (%s) is too long and would be truncated" % (b,)) - b = self.from_bits(b) + b = self.from_bits(b, n) except TypeError: try: b = ZZ(b) From 004fc70f7701d7d30d0e2522055eb421ee2a8e4c Mon Sep 17 00:00:00 2001 From: Gareth Ma Date: Thu, 15 Feb 2024 16:26:12 +0000 Subject: [PATCH 003/231] fix #37356 --- src/sage/rings/polynomial/polynomial_element.pyx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sage/rings/polynomial/polynomial_element.pyx b/src/sage/rings/polynomial/polynomial_element.pyx index 94d5854976a..68db550b585 100644 --- a/src/sage/rings/polynomial/polynomial_element.pyx +++ b/src/sage/rings/polynomial/polynomial_element.pyx @@ -5211,13 +5211,13 @@ cdef class Polynomial(CommutativePolynomial): sage: # needs sage.rings.finite_rings sage: P. = PolynomialRing(GF(401^13, 'a')) sage: t = 2*x^14 - 5 + 6*x - sage: t.splitting_field('b') + sage: t.splitting_field('b') # long time -- 16s Finite Field in b of size 401^104 sage: t = 24*x^13 + 2*x^12 + 14 - sage: t.splitting_field('b') + sage: t.splitting_field('b') # long time -- 39s Finite Field in b of size 401^156 sage: t = x^56 - 14*x^3 - sage: t.splitting_field('b') + sage: t.splitting_field('b') # long time -- 2s Finite Field in b of size 401^52 sage: R. = QQ[] From e4f6be3ddb3eb083f863c44f3dee970acd107779 Mon Sep 17 00:00:00 2001 From: Gareth Ma Date: Thu, 15 Feb 2024 17:39:48 +0000 Subject: [PATCH 004/231] mark slow files as slow --- src/sage/rings/number_field/number_field_rel.py | 2 +- .../rings/polynomial/polynomial_quotient_ring_element.py | 1 + src/sage/rings/tate_algebra_ideal.pyx | 2 +- src/sage/schemes/elliptic_curves/ell_field.py | 6 +++--- src/sage/schemes/elliptic_curves/ell_number_field.py | 2 +- src/sage/schemes/elliptic_curves/isogeny_class.py | 6 +++--- 6 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/sage/rings/number_field/number_field_rel.py b/src/sage/rings/number_field/number_field_rel.py index 2bbb0cce121..32bd5ab72e0 100644 --- a/src/sage/rings/number_field/number_field_rel.py +++ b/src/sage/rings/number_field/number_field_rel.py @@ -2467,7 +2467,7 @@ def order(self, *gens, **kwds): EXAMPLES:: sage: P. = QQ[2^(1/2), 2^(1/3), 3^(1/2)] # needs sage.symbolic - sage: R = P.order([a,b,c]); R # needs sage.symbolic + sage: R = P.order([a,b,c]); R # long time (83s), needs sage.symbolic Relative Order generated by [((-36372*sqrt3 + 371270)*a^2 + (-89082*sqrt3 + 384161)*a - 422504*sqrt3 - 46595)*sqrt2 + (303148*sqrt3 - 89080)*a^2 + (313664*sqrt3 - 218211)*a - 38053*sqrt3 - 1034933, ((-65954*sqrt3 + 323491)*a^2 + (-110591*sqrt3 + 350011)*a - 351557*sqrt3 + 77507)*sqrt2 + (264138*sqrt3 - 161552)*a^2 + (285784*sqrt3 - 270906)*a + 63287*sqrt3 - 861151, diff --git a/src/sage/rings/polynomial/polynomial_quotient_ring_element.py b/src/sage/rings/polynomial/polynomial_quotient_ring_element.py index 0754ed31e7c..849262af7d9 100644 --- a/src/sage/rings/polynomial/polynomial_quotient_ring_element.py +++ b/src/sage/rings/polynomial/polynomial_quotient_ring_element.py @@ -721,6 +721,7 @@ def minpoly(self): We make sure that the previous example works on random examples:: + sage: # long time sage: # needs sage.rings.finite_rings sage: p = random_prime(50) sage: K. = GF((p, randrange(1,20))) diff --git a/src/sage/rings/tate_algebra_ideal.pyx b/src/sage/rings/tate_algebra_ideal.pyx index 982d9581635..c3b1c7ea0c0 100644 --- a/src/sage/rings/tate_algebra_ideal.pyx +++ b/src/sage/rings/tate_algebra_ideal.pyx @@ -623,7 +623,7 @@ cdef TateAlgebraElement regular_reduce(sgb, TateAlgebraTerm s, TateAlgebraElemen TESTS:: - sage: cython( # needs sage.misc.cython + sage: cython( # long time 6.5s, needs sage.misc.cython ....: ''' ....: from sage.rings.tate_algebra_ideal cimport regular_reduce ....: def python_regular_reduce(gb, s, v, stopval): diff --git a/src/sage/schemes/elliptic_curves/ell_field.py b/src/sage/schemes/elliptic_curves/ell_field.py index 0c944f0f938..485e3e0b7c3 100644 --- a/src/sage/schemes/elliptic_curves/ell_field.py +++ b/src/sage/schemes/elliptic_curves/ell_field.py @@ -1419,10 +1419,10 @@ def kernel_polynomial_from_point(self, P, *, algorithm=None): sage: from sage.schemes.elliptic_curves.ell_field import EllipticCurve_field, point_of_order sage: p = 2^127 - 1 sage: E = EllipticCurve(GF(p), [1,0]) - sage: P = point_of_order(E, 31) - sage: %timeit E.kernel_polynomial_from_point(P, algorithm='basic') # not tested + sage: P = point_of_order(E, 31) # long time -- 8.5s + sage: %timeit E.kernel_polynomial_from_point(P, algorithm='basic') # not tested 4.38 ms ± 13.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each) - sage: %timeit E.kernel_polynomial_from_point(P, algorithm='minpoly') # not tested + sage: %timeit E.kernel_polynomial_from_point(P, algorithm='minpoly') # not tested 854 µs ± 1.56 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each) Example of finding all the rational isogenies using this method:: diff --git a/src/sage/schemes/elliptic_curves/ell_number_field.py b/src/sage/schemes/elliptic_curves/ell_number_field.py index a2c3687a4bf..b11ccac74fb 100644 --- a/src/sage/schemes/elliptic_curves/ell_number_field.py +++ b/src/sage/schemes/elliptic_curves/ell_number_field.py @@ -805,7 +805,7 @@ def _scale_by_units(self): sage: K. = QuadraticField(4569) sage: j = 46969655/32768 sage: E = EllipticCurve(j=K(j)) - sage: C = E.isogeny_class() + sage: C = E.isogeny_class() # long time -- 9.5s """ K = self.base_field() r1, r2 = K.signature() diff --git a/src/sage/schemes/elliptic_curves/isogeny_class.py b/src/sage/schemes/elliptic_curves/isogeny_class.py index 1109fd9b93b..717d2f83d9e 100644 --- a/src/sage/schemes/elliptic_curves/isogeny_class.py +++ b/src/sage/schemes/elliptic_curves/isogeny_class.py @@ -1399,7 +1399,7 @@ def possible_isogeny_degrees(E, algorithm='Billerey', max_l=None, Over an extension field:: sage: E3 = E.change_ring(CyclotomicField(3)) - sage: possible_isogeny_degrees(E3) + sage: possible_isogeny_degrees(E3) # long time -- 5s [5] sage: [phi.degree() for phi in E3.isogenies_prime_degree()] [5, 5] @@ -1421,7 +1421,7 @@ def possible_isogeny_degrees(E, algorithm='Billerey', max_l=None, sage: K. = NumberField(x^4 - 5*x^2 + 3) sage: E = EllipticCurve(K, [a^2 - 2, -a^2 + 3, a^2 - 2, -50*a^2 + 35, 95*a^2 - 67]) - sage: possible_isogeny_degrees(E, exact=False, algorithm='Billerey') + sage: possible_isogeny_degrees(E, exact=False, algorithm='Billerey') # long time -- 6.5s [2, 5] sage: possible_isogeny_degrees(E, exact=False, algorithm='Larson') [2, 5] @@ -1432,7 +1432,7 @@ def possible_isogeny_degrees(E, algorithm='Billerey', max_l=None, This function only returns the primes which are isogeny degrees:: - sage: Set(E.isogeny_class().matrix().list()) + sage: Set(E.isogeny_class().matrix().list()) # long time -- 7s {1, 2, 4, 5, 20, 10} For curves with CM by a quadratic order of class number greater From 13e33e4d0708d281d06051875cd6ad35a948c013 Mon Sep 17 00:00:00 2001 From: Gareth Ma Date: Mon, 19 Feb 2024 12:17:56 +0000 Subject: [PATCH 005/231] mark as long time + timing --- src/sage/rings/number_field/number_field_rel.py | 4 ++-- src/sage/rings/polynomial/polynomial_element.pyx | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/sage/rings/number_field/number_field_rel.py b/src/sage/rings/number_field/number_field_rel.py index 32bd5ab72e0..0c678662595 100644 --- a/src/sage/rings/number_field/number_field_rel.py +++ b/src/sage/rings/number_field/number_field_rel.py @@ -2478,13 +2478,13 @@ def order(self, *gens, **kwds): The base ring of an order in a relative extension is still `\ZZ`.:: - sage: R.base_ring() # needs sage.symbolic + sage: R.base_ring() # long time, needs sage.symbolic Integer Ring One must give enough generators to generate a ring of finite index in the maximal order:: - sage: P.order([a, b]) # needs sage.symbolic + sage: P.order([a, b]) # long time, needs sage.symbolic Traceback (most recent call last): ... ValueError: the rank of the span of gens is wrong diff --git a/src/sage/rings/polynomial/polynomial_element.pyx b/src/sage/rings/polynomial/polynomial_element.pyx index 68db550b585..5ae7a80bbdd 100644 --- a/src/sage/rings/polynomial/polynomial_element.pyx +++ b/src/sage/rings/polynomial/polynomial_element.pyx @@ -5211,13 +5211,13 @@ cdef class Polynomial(CommutativePolynomial): sage: # needs sage.rings.finite_rings sage: P. = PolynomialRing(GF(401^13, 'a')) sage: t = 2*x^14 - 5 + 6*x - sage: t.splitting_field('b') # long time -- 16s + sage: t.splitting_field('b') # long time (16s) Finite Field in b of size 401^104 sage: t = 24*x^13 + 2*x^12 + 14 - sage: t.splitting_field('b') # long time -- 39s + sage: t.splitting_field('b') # long time (39s) Finite Field in b of size 401^156 sage: t = x^56 - 14*x^3 - sage: t.splitting_field('b') # long time -- 2s + sage: t.splitting_field('b') # long time (2s) Finite Field in b of size 401^52 sage: R. = QQ[] From 0315907af84016cd02071ee381aa6d8ff75d1a30 Mon Sep 17 00:00:00 2001 From: Gareth Ma Date: Wed, 21 Feb 2024 12:41:02 +0000 Subject: [PATCH 006/231] formatting long time comments --- src/sage/algebras/fusion_rings/f_matrix.py | 2 +- src/sage/combinat/designs/orthogonal_arrays.py | 2 +- .../root_system/root_lattice_realization_algebras.py | 8 ++++---- src/sage/geometry/polyhedron/library.py | 10 +++++----- src/sage/modular/multiple_zeta.py | 2 +- src/sage/rings/number_field/number_field_rel.py | 2 +- src/sage/rings/qqbar.py | 2 +- src/sage/rings/tate_algebra_ideal.pyx | 2 +- src/sage/schemes/elliptic_curves/ell_field.py | 2 +- src/sage/schemes/elliptic_curves/ell_number_field.py | 2 +- src/sage/schemes/elliptic_curves/isogeny_class.py | 6 +++--- 11 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/sage/algebras/fusion_rings/f_matrix.py b/src/sage/algebras/fusion_rings/f_matrix.py index 47f5976cf03..7e4d8776c87 100644 --- a/src/sage/algebras/fusion_rings/f_matrix.py +++ b/src/sage/algebras/fusion_rings/f_matrix.py @@ -2429,7 +2429,7 @@ def certify_pentagons(self, use_mp=True, verbose=False): Partitioned 6 equations into 6 components of size: [1, 1, 1, 1, 1, 1] Computing appropriate NumberField... - sage: f.certify_pentagons() is None # not tested (long time ~1.5s, cypari issue in doctesting framework) + sage: f.certify_pentagons() is None # not tested, long time (~1.5s), cypari issue in doctesting framework True """ fvars_copy = deepcopy(self._fvars) diff --git a/src/sage/combinat/designs/orthogonal_arrays.py b/src/sage/combinat/designs/orthogonal_arrays.py index b4a14b0e7b6..9d6a2380afa 100644 --- a/src/sage/combinat/designs/orthogonal_arrays.py +++ b/src/sage/combinat/designs/orthogonal_arrays.py @@ -242,7 +242,7 @@ def transversal_design(k, n, resolvable=False, check=True, existence=False): For small values of the parameter ``n`` we check the coherence of the function :func:`transversal_design`:: - sage: for n in range(2,25): # long time -- 15 secs + sage: for n in range(2,25): # long time (15s) ....: i = 2 ....: while designs.transversal_design(i, n, existence=True) is True: ....: i += 1 diff --git a/src/sage/combinat/root_system/root_lattice_realization_algebras.py b/src/sage/combinat/root_system/root_lattice_realization_algebras.py index 30251e983a7..20a0748272c 100644 --- a/src/sage/combinat/root_system/root_lattice_realization_algebras.py +++ b/src/sage/combinat/root_system/root_lattice_realization_algebras.py @@ -566,13 +566,13 @@ def demazure_lusztig_operators(self, q1, q2, convention="antidominant"): sage: K = QQ['q1,q2'] sage: q1, q2 = K.gens() - sage: for cartan_type in CartanType.samples(crystallographic=True): # long time 12s + sage: for cartan_type in CartanType.samples(crystallographic=True): # long time (12s) ....: L = RootSystem(cartan_type).root_lattice() ....: KL = L.algebra(K) ....: T = KL.demazure_lusztig_operators(q1,q2) ....: T._test_relations() - sage: for cartan_type in CartanType.samples(crystallographic=True): # long time 12s + sage: for cartan_type in CartanType.samples(crystallographic=True): # long time (12s) ....: L = RootSystem(cartan_type).weight_lattice() ....: KL = L.algebra(K) ....: T = KL.demazure_lusztig_operators(q1,q2) @@ -584,7 +584,7 @@ def demazure_lusztig_operators(self, q1, q2, convention="antidominant"): to specify explicitly the elements on which to run the tests:: - sage: for cartan_type in CartanType.samples(crystallographic=True): # long time 12s + sage: for cartan_type in CartanType.samples(crystallographic=True): # long time (12s) ....: L = RootSystem(cartan_type).ambient_space() ....: KL = L.algebra(K) ....: weight_lattice = RootSystem(cartan_type).weight_lattice(extended=L.is_extended()) @@ -1103,7 +1103,7 @@ def twisted_demazure_lusztig_operators(self, q1, q2, convention="antidominant"): sage: K = QQ['q1,q2'].fraction_field() sage: q1, q2 = K.gens() - sage: for cartan_type in CartanType.samples(affine=True, crystallographic=True): # long time 12s + sage: for cartan_type in CartanType.samples(affine=True, crystallographic=True): # long time (12s) ....: if cartan_type.rank() > 4: continue ....: if cartan_type.type() == 'BC': continue ....: KL = RootSystem(cartan_type).weight_lattice().algebra(K) diff --git a/src/sage/geometry/polyhedron/library.py b/src/sage/geometry/polyhedron/library.py index efd79abb318..ce599e61363 100644 --- a/src/sage/geometry/polyhedron/library.py +++ b/src/sage/geometry/polyhedron/library.py @@ -1542,7 +1542,7 @@ def icosidodecahedron_V2(self, exact=True, base_ring=None, backend=None): EXAMPLES:: - sage: id = polytopes.icosidodecahedron_V2() # long time - 6secs + sage: id = polytopes.icosidodecahedron_V2() # long time (6s) sage: id.f_vector() # long time (1, 30, 60, 32, 1) sage: id.base_ring() # long time @@ -1705,7 +1705,7 @@ def pentakis_dodecahedron(self, exact=True, base_ring=None, backend=None): EXAMPLES:: - sage: pd = polytopes.pentakis_dodecahedron() # long time - ~10 sec + sage: pd = polytopes.pentakis_dodecahedron() # long time (10s) sage: pd.n_vertices() # long time 32 sage: pd.n_inequalities() # long time @@ -2201,7 +2201,7 @@ def truncated_six_hundred_cell(self, exact=False, backend=None): It is possible to use the backend ``'normaliz'`` to get an exact representation:: - sage: polytopes.truncated_six_hundred_cell(exact=True,backend='normaliz') # not tested - long time ~16sec + sage: polytopes.truncated_six_hundred_cell(exact=True,backend='normaliz') # not tested - long time (16s) A 4-dimensional polyhedron in AA^4 defined as the convex hull of 1440 vertices """ return self.generalized_permutahedron(['H', 4], point=[1, 1, 0, 0], exact=exact, backend=backend, regular=True) @@ -2229,7 +2229,7 @@ def rectified_six_hundred_cell(self, exact=True, backend=None): EXAMPLES:: - sage: polytopes.rectified_six_hundred_cell(backend='normaliz') # not tested - long time ~14sec + sage: polytopes.rectified_six_hundred_cell(backend='normaliz') # not tested, long time (14s) A 4-dimensional polyhedron in AA^4 defined as the convex hull of 720 vertices """ return self.generalized_permutahedron(['H', 4], point=[0, 1, 0, 0], exact=exact, backend=backend, regular=True) @@ -3091,7 +3091,7 @@ def one_hundred_twenty_cell(self, exact=True, backend=None, construction='coxete The classical construction given by Coxeter in [Cox1969]_ is given by:: - sage: polytopes.one_hundred_twenty_cell() # not tested - long time ~15 sec. + sage: polytopes.one_hundred_twenty_cell() # not tested, long time (~15s) A 4-dimensional polyhedron in (Number Field in sqrt5 with defining polynomial x^2 - 5 with sqrt5 = 2.236067977499790?)^4 defined as the convex hull of 600 vertices diff --git a/src/sage/modular/multiple_zeta.py b/src/sage/modular/multiple_zeta.py index cefcb3b3c65..1047bc881cb 100644 --- a/src/sage/modular/multiple_zeta.py +++ b/src/sage/modular/multiple_zeta.py @@ -2034,7 +2034,7 @@ def _richcmp_(self, other, op) -> bool: sage: M = Multizetas(QQ) sage: a = 28*M((3,9))+150*M((5,7))+168*M((7,5)) sage: b = 5197/691*M((12,)) - sage: a.iterated() == b.iterated() # not tested, long time 20s + sage: a.iterated() == b.iterated() # not tested, long time (20s) True """ if op not in [op_EQ, op_NE]: diff --git a/src/sage/rings/number_field/number_field_rel.py b/src/sage/rings/number_field/number_field_rel.py index 0c678662595..3b489cdd04f 100644 --- a/src/sage/rings/number_field/number_field_rel.py +++ b/src/sage/rings/number_field/number_field_rel.py @@ -2467,7 +2467,7 @@ def order(self, *gens, **kwds): EXAMPLES:: sage: P. = QQ[2^(1/2), 2^(1/3), 3^(1/2)] # needs sage.symbolic - sage: R = P.order([a,b,c]); R # long time (83s), needs sage.symbolic + sage: R = P.order([a,b,c]); R # not tested (83s, 2GB memory), needs sage.symbolic Relative Order generated by [((-36372*sqrt3 + 371270)*a^2 + (-89082*sqrt3 + 384161)*a - 422504*sqrt3 - 46595)*sqrt2 + (303148*sqrt3 - 89080)*a^2 + (313664*sqrt3 - 218211)*a - 38053*sqrt3 - 1034933, ((-65954*sqrt3 + 323491)*a^2 + (-110591*sqrt3 + 350011)*a - 351557*sqrt3 + 77507)*sqrt2 + (264138*sqrt3 - 161552)*a^2 + (285784*sqrt3 - 270906)*a + 63287*sqrt3 - 861151, diff --git a/src/sage/rings/qqbar.py b/src/sage/rings/qqbar.py index 4d92d64d80f..ba7df02b996 100644 --- a/src/sage/rings/qqbar.py +++ b/src/sage/rings/qqbar.py @@ -4929,7 +4929,7 @@ def _richcmp_(self, other, op): slower because the algorithm needs to check the equality of the real parts:: - sage: sorted(p2.roots(QQbar,False)) # long time - 3 secs + sage: sorted(p2.roots(QQbar,False)) # long time (3s) [1.000000000000000? - 4.016778562562223?*I, 1.000000000000000? - 3.850538755978243?*I, 1.000000000000000? - 3.390564396412898?*I, diff --git a/src/sage/rings/tate_algebra_ideal.pyx b/src/sage/rings/tate_algebra_ideal.pyx index c3b1c7ea0c0..87158478c41 100644 --- a/src/sage/rings/tate_algebra_ideal.pyx +++ b/src/sage/rings/tate_algebra_ideal.pyx @@ -623,7 +623,7 @@ cdef TateAlgebraElement regular_reduce(sgb, TateAlgebraTerm s, TateAlgebraElemen TESTS:: - sage: cython( # long time 6.5s, needs sage.misc.cython + sage: cython( # long time (6.5s), needs sage.misc.cython ....: ''' ....: from sage.rings.tate_algebra_ideal cimport regular_reduce ....: def python_regular_reduce(gb, s, v, stopval): diff --git a/src/sage/schemes/elliptic_curves/ell_field.py b/src/sage/schemes/elliptic_curves/ell_field.py index 485e3e0b7c3..8812434657f 100644 --- a/src/sage/schemes/elliptic_curves/ell_field.py +++ b/src/sage/schemes/elliptic_curves/ell_field.py @@ -1419,7 +1419,7 @@ def kernel_polynomial_from_point(self, P, *, algorithm=None): sage: from sage.schemes.elliptic_curves.ell_field import EllipticCurve_field, point_of_order sage: p = 2^127 - 1 sage: E = EllipticCurve(GF(p), [1,0]) - sage: P = point_of_order(E, 31) # long time -- 8.5s + sage: P = point_of_order(E, 31) # long time (8.5s) sage: %timeit E.kernel_polynomial_from_point(P, algorithm='basic') # not tested 4.38 ms ± 13.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each) sage: %timeit E.kernel_polynomial_from_point(P, algorithm='minpoly') # not tested diff --git a/src/sage/schemes/elliptic_curves/ell_number_field.py b/src/sage/schemes/elliptic_curves/ell_number_field.py index b11ccac74fb..537985494cb 100644 --- a/src/sage/schemes/elliptic_curves/ell_number_field.py +++ b/src/sage/schemes/elliptic_curves/ell_number_field.py @@ -805,7 +805,7 @@ def _scale_by_units(self): sage: K. = QuadraticField(4569) sage: j = 46969655/32768 sage: E = EllipticCurve(j=K(j)) - sage: C = E.isogeny_class() # long time -- 9.5s + sage: C = E.isogeny_class() # long time (9.5s) """ K = self.base_field() r1, r2 = K.signature() diff --git a/src/sage/schemes/elliptic_curves/isogeny_class.py b/src/sage/schemes/elliptic_curves/isogeny_class.py index 717d2f83d9e..cc3efd11dc8 100644 --- a/src/sage/schemes/elliptic_curves/isogeny_class.py +++ b/src/sage/schemes/elliptic_curves/isogeny_class.py @@ -1399,7 +1399,7 @@ def possible_isogeny_degrees(E, algorithm='Billerey', max_l=None, Over an extension field:: sage: E3 = E.change_ring(CyclotomicField(3)) - sage: possible_isogeny_degrees(E3) # long time -- 5s + sage: possible_isogeny_degrees(E3) # long time (5s) [5] sage: [phi.degree() for phi in E3.isogenies_prime_degree()] [5, 5] @@ -1421,7 +1421,7 @@ def possible_isogeny_degrees(E, algorithm='Billerey', max_l=None, sage: K. = NumberField(x^4 - 5*x^2 + 3) sage: E = EllipticCurve(K, [a^2 - 2, -a^2 + 3, a^2 - 2, -50*a^2 + 35, 95*a^2 - 67]) - sage: possible_isogeny_degrees(E, exact=False, algorithm='Billerey') # long time -- 6.5s + sage: possible_isogeny_degrees(E, exact=False, algorithm='Billerey') # long time (6.5s) [2, 5] sage: possible_isogeny_degrees(E, exact=False, algorithm='Larson') [2, 5] @@ -1432,7 +1432,7 @@ def possible_isogeny_degrees(E, algorithm='Billerey', max_l=None, This function only returns the primes which are isogeny degrees:: - sage: Set(E.isogeny_class().matrix().list()) # long time -- 7s + sage: Set(E.isogeny_class().matrix().list()) # long time (7s) {1, 2, 4, 5, 20, 10} For curves with CM by a quadratic order of class number greater From b264a86e85f7c82d7d8d4eca6e92c937b3d43f06 Mon Sep 17 00:00:00 2001 From: grhkm21 <83517584+grhkm21@users.noreply.github.com> Date: Sun, 25 Feb 2024 21:12:02 +0000 Subject: [PATCH 007/231] remove extra spaces MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Matthias Köppe --- src/sage/geometry/polyhedron/library.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/geometry/polyhedron/library.py b/src/sage/geometry/polyhedron/library.py index ce599e61363..d9226c20da7 100644 --- a/src/sage/geometry/polyhedron/library.py +++ b/src/sage/geometry/polyhedron/library.py @@ -2201,7 +2201,7 @@ def truncated_six_hundred_cell(self, exact=False, backend=None): It is possible to use the backend ``'normaliz'`` to get an exact representation:: - sage: polytopes.truncated_six_hundred_cell(exact=True,backend='normaliz') # not tested - long time (16s) + sage: polytopes.truncated_six_hundred_cell(exact=True,backend='normaliz') # not tested, long time (16s) A 4-dimensional polyhedron in AA^4 defined as the convex hull of 1440 vertices """ return self.generalized_permutahedron(['H', 4], point=[1, 1, 0, 0], exact=exact, backend=backend, regular=True) From 0b9bfd9c88241391cbae4b6633b790ef8e793b0a Mon Sep 17 00:00:00 2001 From: Kiran Kedlaya Date: Mon, 4 Mar 2024 07:55:42 -0800 Subject: [PATCH 008/231] Enable coercion to ZZ for GAP modular integers --- src/sage/groups/matrix_gps/group_element_gap.pyx | 2 +- src/sage/libs/gap/element.pyx | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/sage/groups/matrix_gps/group_element_gap.pyx b/src/sage/groups/matrix_gps/group_element_gap.pyx index 7c581377f6f..62b5f3bc5c3 100644 --- a/src/sage/groups/matrix_gps/group_element_gap.pyx +++ b/src/sage/groups/matrix_gps/group_element_gap.pyx @@ -210,7 +210,7 @@ cdef class MatrixGroupElement_gap(ElementLibGAP): entries = self.gap().Flat() MS = self.parent().matrix_space() ring = MS.base_ring() - m = MS([x.sage(ring=ring) for x in entries]) + m = MS([ring(x) for x in entries]) m.set_immutable() return m diff --git a/src/sage/libs/gap/element.pyx b/src/sage/libs/gap/element.pyx index ab9a2860cb4..e7eef0c6552 100644 --- a/src/sage/libs/gap/element.pyx +++ b/src/sage/libs/gap/element.pyx @@ -1704,6 +1704,15 @@ cdef class GapElement_IntegerMod(GapElement): ring = ZZ.quotient_ring(characteristic) return self.lift().sage(ring=ring) + def _integer_(self, R): + r""" + TESTS:: + + sage: n = libgap.eval('One(ZmodnZ(123)) * 13') + sage: ZZ(n) + 13 + """ + return self.lift()._integer_(R) ############################################################################ ### GapElement_FiniteField ##################################################### @@ -2942,7 +2951,7 @@ cdef class GapElement_List(GapElement): if ring is None: ring = entries.DefaultRing().sage() MS = MatrixSpace(ring, n, m) - return MS([x.sage(ring=ring) for x in entries]) + return MS([ring(x) for x in entries]) _matrix_ = matrix From 9b8ab086a7d239b614d5062b2f5b58f8066df504 Mon Sep 17 00:00:00 2001 From: Kiran Kedlaya Date: Sun, 10 Mar 2024 07:56:07 -0700 Subject: [PATCH 009/231] Convert libGAP integers without string representation --- src/sage/libs/gap/element.pyx | 21 ++++++++++++++------- src/sage/libs/gap/gap_includes.pxd | 2 ++ src/sage/libs/gmp/mpz.pxd | 1 + 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/sage/libs/gap/element.pyx b/src/sage/libs/gap/element.pyx index e7eef0c6552..f1c0d364408 100644 --- a/src/sage/libs/gap/element.pyx +++ b/src/sage/libs/gap/element.pyx @@ -22,6 +22,8 @@ from sage.libs.gap.gap_includes cimport * from sage.libs.gap.libgap import libgap from sage.libs.gap.util cimport * from sage.libs.gap.util import GAPError +from sage.libs.gmp.mpz cimport * +from sage.libs.gmp.pylong cimport mpz_get_pylong from sage.cpython.string cimport str_to_bytes, char_to_str from sage.rings.integer_ring import ZZ from sage.rings.rational_field import QQ @@ -1478,7 +1480,7 @@ cdef class GapElement_Integer(GapElement): Return the Sage equivalent of the :class:`GapElement_Integer` - ``ring`` -- Integer ring or ``None`` (default). If not - specified, a the default Sage integer ring is used. + specified, the default Sage integer ring is used. OUTPUT: @@ -1508,17 +1510,22 @@ cdef class GapElement_Integer(GapElement): sage: huge.sage().ndigits() 10000 """ + cdef UInt* x + cdef Int size + cdef int c_sign + cdef int c_size + cdef mpz_t output if ring is None: ring = ZZ if self.is_C_int(): return ring(GAP_ValueInt(self.value)) else: - # TODO: waste of time! - # gap integers are stored as a mp_limb_t and we have a much more direct - # conversion implemented in mpz_get_pylong(mpz_srcptr z) - # (see sage.libs.gmp.pylong) - string = self.String().sage() - return ring(string) + # gap integers are stored as a mp_limb_t + size = GAP_SizeInt(self.value) # count limbs and extract sign + c_sign = 1 if size > 0 else -1 + x = GAP_AddrInt(self.value) # pointer to limbs + mpz_roinit_n(output, x, abs(c_size)) + return ring(c_sign*mpz_get_pylong(output)) _integer_ = sage diff --git a/src/sage/libs/gap/gap_includes.pxd b/src/sage/libs/gap/gap_includes.pxd index 1ed4378a6c7..35107d3d4a0 100644 --- a/src/sage/libs/gap/gap_includes.pxd +++ b/src/sage/libs/gap/gap_includes.pxd @@ -74,6 +74,8 @@ cdef extern from "gap/libgap-api.h" nogil: bint GAP_IsSmallInt(Obj) Obj GAP_NewObjIntFromInt(Int val) Int GAP_ValueInt(Obj) + Int GAP_SizeInt(Obj) + UInt* GAP_AddrInt(Obj) bint GAP_IsList(Obj lst) UInt GAP_LenList(Obj lst) diff --git a/src/sage/libs/gmp/mpz.pxd b/src/sage/libs/gmp/mpz.pxd index 71d1e5e3069..48cb7888c1b 100644 --- a/src/sage/libs/gmp/mpz.pxd +++ b/src/sage/libs/gmp/mpz.pxd @@ -198,3 +198,4 @@ cdef extern from "gmp.h": void * _mpz_realloc (mpz_t integer, mp_size_t new_alloc) mp_limb_t mpz_getlimbn (mpz_t op, mp_size_t n) size_t mpz_size (mpz_t op) + mpz_srcptr mpz_roinit_n (mpz_t x, const mp_limb_t *xp, mp_size_t xs) From 5cf5989bacedd975c42bae4155ac0603f389c658 Mon Sep 17 00:00:00 2001 From: Kiran Kedlaya Date: Sat, 16 Mar 2024 14:18:00 -0700 Subject: [PATCH 010/231] Add missing assignment to c_size; add fallback --- src/sage/libs/gap/element.pyx | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/sage/libs/gap/element.pyx b/src/sage/libs/gap/element.pyx index ae94cb57ffe..664d724dcb2 100644 --- a/src/sage/libs/gap/element.pyx +++ b/src/sage/libs/gap/element.pyx @@ -1522,9 +1522,16 @@ cdef class GapElement_Integer(GapElement): else: # gap integers are stored as a mp_limb_t size = GAP_SizeInt(self.value) # count limbs and extract sign - c_sign = 1 if size > 0 else -1 + if size > 0: + c_sign = 1 + c_size = size + elif size < 0: + c_sign = -1 + c_size = -size + else: # Something is wrong, fall back to string representation + return ring(self.String().sage()) x = GAP_AddrInt(self.value) # pointer to limbs - mpz_roinit_n(output, x, abs(c_size)) + mpz_roinit_n(output, x, c_size) return ring(c_sign*mpz_get_pylong(output)) _integer_ = sage From 54a9e106f260fd3febe3347d16965d7da196bbda Mon Sep 17 00:00:00 2001 From: Kiran Kedlaya Date: Sat, 16 Mar 2024 16:23:42 -0700 Subject: [PATCH 011/231] Use ring(x) instead of x.sage(ring=ring) --- src/sage/libs/gap/element.pyx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/libs/gap/element.pyx b/src/sage/libs/gap/element.pyx index 664d724dcb2..620af227506 100644 --- a/src/sage/libs/gap/element.pyx +++ b/src/sage/libs/gap/element.pyx @@ -1697,7 +1697,7 @@ cdef class GapElement_IntegerMod(GapElement): INPUT: - ``ring`` -- Sage integer mod ring or ``None`` (default). If - not specified, a suitable integer mod ringa is used + not specified, a suitable integer mod ring is used automatically. OUTPUT: @@ -1716,7 +1716,7 @@ cdef class GapElement_IntegerMod(GapElement): # ring = self.DefaultRing().sage() characteristic = self.Characteristic().sage() ring = ZZ.quotient_ring(characteristic) - return self.lift().sage(ring=ring) + return ring(self.lift()) def _integer_(self, R): r""" From 1321494e7509bcead7ad2bf240a4f75361cb00fc Mon Sep 17 00:00:00 2001 From: Kiran Kedlaya Date: Mon, 18 Mar 2024 06:05:46 -0700 Subject: [PATCH 012/231] Add doctests to GapElement_IntegerMod._integer_ --- src/sage/libs/gap/element.pyx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/sage/libs/gap/element.pyx b/src/sage/libs/gap/element.pyx index 620af227506..fee027f7c59 100644 --- a/src/sage/libs/gap/element.pyx +++ b/src/sage/libs/gap/element.pyx @@ -1725,6 +1725,10 @@ cdef class GapElement_IntegerMod(GapElement): sage: n = libgap.eval('One(ZmodnZ(123)) * 13') sage: ZZ(n) 13 + sage: ZZ(-n) + 110 + sage: ZZ(0*n) + 0 """ return self.lift()._integer_(R) From ff86e0d83462340c12e48897076a195931ae0710 Mon Sep 17 00:00:00 2001 From: Kiran Kedlaya Date: Mon, 18 Mar 2024 06:45:06 -0700 Subject: [PATCH 013/231] Remove fallback GAP integer conversion --- src/sage/libs/gap/element.pyx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/sage/libs/gap/element.pyx b/src/sage/libs/gap/element.pyx index fee027f7c59..3065aac5407 100644 --- a/src/sage/libs/gap/element.pyx +++ b/src/sage/libs/gap/element.pyx @@ -1500,6 +1500,8 @@ cdef class GapElement_Integer(GapElement): TESTS:: + sage: libgap(0).sage() + 0 sage: large = libgap.eval('2^130'); large 1361129467683753853853498429727072845824 sage: large.sage() @@ -1525,11 +1527,9 @@ cdef class GapElement_Integer(GapElement): if size > 0: c_sign = 1 c_size = size - elif size < 0: + else: # Must have size < 0, or else self.value == 0 and self.is_C_int() == True c_sign = -1 c_size = -size - else: # Something is wrong, fall back to string representation - return ring(self.String().sage()) x = GAP_AddrInt(self.value) # pointer to limbs mpz_roinit_n(output, x, c_size) return ring(c_sign*mpz_get_pylong(output)) @@ -1722,7 +1722,7 @@ cdef class GapElement_IntegerMod(GapElement): r""" TESTS:: - sage: n = libgap.eval('One(ZmodnZ(123)) * 13') + sage: n = libgap.ZmodnZObj(13, 123) sage: ZZ(n) 13 sage: ZZ(-n) @@ -1853,6 +1853,8 @@ cdef class GapElement_FiniteField(GapElement): a^2 + a + 1 sage: n.sage(ring=GF(2^8, 'a')) a^7 + a^6 + a^4 + a^2 + a + 1 + sage: (n^3).sage() + 1 Check that :issue:`23153` is fixed:: From 0c3d2a60636ef534630510ec8aaf48dd52d21b10 Mon Sep 17 00:00:00 2001 From: Hartmut Monien Date: Tue, 2 Apr 2024 13:54:54 +0200 Subject: [PATCH 014/231] FareySymbol: set aspect_ratio to one in graph of fundamental domain. --- src/sage/modular/arithgroup/farey_symbol.pyx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sage/modular/arithgroup/farey_symbol.pyx b/src/sage/modular/arithgroup/farey_symbol.pyx index 4cfb4b12363..f6e03c1223b 100644 --- a/src/sage/modular/arithgroup/farey_symbol.pyx +++ b/src/sage/modular/arithgroup/farey_symbol.pyx @@ -1031,6 +1031,7 @@ cdef class Farey: thickness=options['thickness']) d = g.get_minmax_data() g.set_axes_range(d['xmin'], d['xmax'], 0, options['ymax']) + g.set_aspect_ratio(1) return g From 58f586b61a659c5d6f65d1cbde74dc92aa7bc225 Mon Sep 17 00:00:00 2001 From: hadipourh Date: Sat, 6 Apr 2024 12:41:21 +0200 Subject: [PATCH 015/231] add a test for component_function --- src/sage/crypto/sbox.pyx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/sage/crypto/sbox.pyx b/src/sage/crypto/sbox.pyx index bfe08d54296..37b694e7207 100644 --- a/src/sage/crypto/sbox.pyx +++ b/src/sage/crypto/sbox.pyx @@ -1326,6 +1326,12 @@ cdef class SBox(SageObject): sage: f5 = S.component_function([1, 0, 1]) sage: f5.algebraic_normal_form() # needs sage.rings.polynomial.pbori x0*x2 + x0 + x1*x2 + + TESTS:: + sage: from sage.crypto.sboxes import SBox + sage: sb = SBox(7, 6, 0, 4, 2, 5, 1, 3) + sage: sb.component_function([1, 0, 0]) + Boolean function with 3 variables """ cdef Py_ssize_t m = self.m cdef Py_ssize_t n = self.n From 82469daa899a8af534ae01b4b8c8affca09881d9 Mon Sep 17 00:00:00 2001 From: hadipourh Date: Sat, 6 Apr 2024 12:49:59 +0200 Subject: [PATCH 016/231] add a test for component_function --- src/sage/crypto/sbox.pyx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sage/crypto/sbox.pyx b/src/sage/crypto/sbox.pyx index 37b694e7207..ebd243bff08 100644 --- a/src/sage/crypto/sbox.pyx +++ b/src/sage/crypto/sbox.pyx @@ -1328,6 +1328,7 @@ cdef class SBox(SageObject): x0*x2 + x0 + x1*x2 TESTS:: + sage: from sage.crypto.sboxes import SBox sage: sb = SBox(7, 6, 0, 4, 2, 5, 1, 3) sage: sb.component_function([1, 0, 0]) From 68210f4acddd7292b84e35bb0758c6dea78f04e8 Mon Sep 17 00:00:00 2001 From: hadipourh Date: Sat, 6 Apr 2024 12:53:03 +0200 Subject: [PATCH 017/231] add a test for component_function --- src/sage/crypto/sbox.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/crypto/sbox.pyx b/src/sage/crypto/sbox.pyx index ebd243bff08..d22f91347a5 100644 --- a/src/sage/crypto/sbox.pyx +++ b/src/sage/crypto/sbox.pyx @@ -1328,7 +1328,7 @@ cdef class SBox(SageObject): x0*x2 + x0 + x1*x2 TESTS:: - + sage: from sage.crypto.sboxes import SBox sage: sb = SBox(7, 6, 0, 4, 2, 5, 1, 3) sage: sb.component_function([1, 0, 0]) From 302274dc54410cceec2124d13005b3ba44cbd1ea Mon Sep 17 00:00:00 2001 From: hadipourh Date: Sat, 6 Apr 2024 13:01:44 +0200 Subject: [PATCH 018/231] add a test for component_function --- src/sage/crypto/sbox.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/crypto/sbox.pyx b/src/sage/crypto/sbox.pyx index d22f91347a5..a818ae5271b 100644 --- a/src/sage/crypto/sbox.pyx +++ b/src/sage/crypto/sbox.pyx @@ -1326,7 +1326,7 @@ cdef class SBox(SageObject): sage: f5 = S.component_function([1, 0, 1]) sage: f5.algebraic_normal_form() # needs sage.rings.polynomial.pbori x0*x2 + x0 + x1*x2 - + TESTS:: sage: from sage.crypto.sboxes import SBox From c545fb3762d5eac370333b0b83a3347b6ef914f1 Mon Sep 17 00:00:00 2001 From: hadipourh Date: Tue, 28 May 2024 18:38:01 +0200 Subject: [PATCH 019/231] debug component_function in sbox module --- src/sage/crypto/sbox.pyx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sage/crypto/sbox.pyx b/src/sage/crypto/sbox.pyx index ab02e82cb1e..6074bc3921c 100644 --- a/src/sage/crypto/sbox.pyx +++ b/src/sage/crypto/sbox.pyx @@ -1330,9 +1330,9 @@ cdef class SBox(SageObject): TESTS:: sage: from sage.crypto.sboxes import SBox - sage: sb = SBox(7, 6, 0, 4, 2, 5, 1, 3) - sage: sb.component_function([1, 0, 0]) - Boolean function with 3 variables + sage: sb = SBox([0, 1, 2, 3, 0, 1, 2, 3]) + sage: sb.component_function([1, 0]) + Boolean function with 3 variabl """ cdef Py_ssize_t m = self.m cdef Py_ssize_t n = self.n From 34a5f92d06679ece241b83f4a9e3293765065c7c Mon Sep 17 00:00:00 2001 From: vboxuser Date: Tue, 4 Jun 2024 11:23:23 -0500 Subject: [PATCH 020/231] Fixing issue 38012 --- .../dynamics/arithmetic_dynamics/projective_ds.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py index 4b42ad87b1f..49507781286 100644 --- a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py +++ b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py @@ -8440,6 +8440,14 @@ def normal_form(self, return_conjugation=False): To: Finite Field in z2 of size 3^2 Defn: 1 |--> 1 + :: + + sage: R. = PolynomialRing(QQ) + sage: f = DynamicalSystem_affine(z^2+z+1).homogenize(1) + sage: f.normal_form() + Dynamical System of Projective Space of dimension 1 over Rational Field + Defn: Defined on coordinates by sending (x0 : x1) to + (x0^2 + 5/4*x1^2 : x1^2) """ # defines the field of fixed points if self.codomain().dimension_relative() != 1: @@ -8468,7 +8476,8 @@ def normal_form(self, return_conjugation=False): #we find one and not go all the way to the splitting field i = 0 if G.degree() != 0: - G = G.polynomial(G.variable(0)) + if is_MPolynomialRing(G.parent()): + G = G.polynomial(G.variable(0)) else: #no other fixed points raise NotImplementedError("map is not a polynomial") From 9d5a23af29af6889a79d26566c02a278d8425f91 Mon Sep 17 00:00:00 2001 From: vboxuser Date: Tue, 4 Jun 2024 13:09:15 -0500 Subject: [PATCH 021/231] Added comment saying purpose of change and reformated polynomial --- src/sage/dynamics/arithmetic_dynamics/projective_ds.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py index 49507781286..d44535ecdb4 100644 --- a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py +++ b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py @@ -8440,10 +8440,10 @@ def normal_form(self, return_conjugation=False): To: Finite Field in z2 of size 3^2 Defn: 1 |--> 1 - :: + Fixes issue 38012 by not forcing univariate polynomial to be univariate:: sage: R. = PolynomialRing(QQ) - sage: f = DynamicalSystem_affine(z^2+z+1).homogenize(1) + sage: f = DynamicalSystem_affine(z^2 + z + 1).homogenize(1) sage: f.normal_form() Dynamical System of Projective Space of dimension 1 over Rational Field Defn: Defined on coordinates by sending (x0 : x1) to From 7f64cf8efb5cfe2eee78d42ef19dc7d07bef8f69 Mon Sep 17 00:00:00 2001 From: Nathabolin <162615271+Nathabolin@users.noreply.github.com> Date: Wed, 5 Jun 2024 19:02:29 -0500 Subject: [PATCH 022/231] Update src/sage/dynamics/arithmetic_dynamics/projective_ds.py Co-authored-by: Sebastian A. Spindler <153911337+S17A05@users.noreply.github.com> --- src/sage/dynamics/arithmetic_dynamics/projective_ds.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py index d44535ecdb4..b910efd6e2d 100644 --- a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py +++ b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py @@ -8477,7 +8477,7 @@ def normal_form(self, return_conjugation=False): i = 0 if G.degree() != 0: if is_MPolynomialRing(G.parent()): - G = G.polynomial(G.variable(0)) + G = G.polynomial(G.variable(0)) else: #no other fixed points raise NotImplementedError("map is not a polynomial") From 8c97c9988fe9cf325abd99b3f6fade3a2438b5ee Mon Sep 17 00:00:00 2001 From: Nathabolin <162615271+Nathabolin@users.noreply.github.com> Date: Wed, 5 Jun 2024 19:02:41 -0500 Subject: [PATCH 023/231] Update src/sage/dynamics/arithmetic_dynamics/projective_ds.py Co-authored-by: Sebastian A. Spindler <153911337+S17A05@users.noreply.github.com> --- src/sage/dynamics/arithmetic_dynamics/projective_ds.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py index b910efd6e2d..4f1dd9b8630 100644 --- a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py +++ b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py @@ -8440,7 +8440,7 @@ def normal_form(self, return_conjugation=False): To: Finite Field in z2 of size 3^2 Defn: 1 |--> 1 - Fixes issue 38012 by not forcing univariate polynomial to be univariate:: + Fixes :issue:`38012` by not forcing univariate polynomial to be univariate:: sage: R. = PolynomialRing(QQ) sage: f = DynamicalSystem_affine(z^2 + z + 1).homogenize(1) From 872627faf0eb51204f5564988a7c24dff669e4ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Fri, 7 Jun 2024 14:56:51 +0200 Subject: [PATCH 024/231] implement morphisms from free algebras --- src/sage/algebras/free_algebra.py | 23 +++++++++++++++ src/sage/algebras/free_algebra_element.py | 24 +++++++++++++++ src/sage/monoids/free_monoid_element.py | 36 ++++++++++------------- 3 files changed, 63 insertions(+), 20 deletions(-) diff --git a/src/sage/algebras/free_algebra.py b/src/sage/algebras/free_algebra.py index 00b0dfdafa7..b4a6d4acd47 100644 --- a/src/sage/algebras/free_algebra.py +++ b/src/sage/algebras/free_algebra.py @@ -751,6 +751,29 @@ def _coerce_map_from_(self, R): return self.base_ring().has_coerce_map_from(R) + def _is_valid_homomorphism_(self, other, im_gens, base_map=None): + """ + Check that the number of given images is correct. + + EXAMPLES:: + + sage: ring = algebras.Free(QQ, ['a', 'b']) + sage: a, b = ring.gens() + sage: A = matrix(QQ, 2, 2, [1, 5, 1, 5]) + sage: B = matrix(QQ, 2, 2, [1, 4, 9, 2]) + sage: C = matrix(QQ, 2, 2, [1, 7, 8, 9]) + sage: f = ring.hom([A, B]) + sage: f(a*b+1) + [47 14] + [46 15] + + sage: ring.hom([A, B, C]) + Traceback (most recent call last): + ... + ValueError: number of images must equal number of generators + """ + return len(im_gens) == self.__ngens + def gen(self, i): """ The ``i``-th generator of the algebra. diff --git a/src/sage/algebras/free_algebra_element.py b/src/sage/algebras/free_algebra_element.py index 9fe2dcfb554..f2c644f3fe3 100644 --- a/src/sage/algebras/free_algebra_element.py +++ b/src/sage/algebras/free_algebra_element.py @@ -280,6 +280,30 @@ def _acted_upon_(self, scalar, self_on_left=False): # _lmul_ = _acted_upon_ # _rmul_ = _acted_upon_ + def _im_gens_(self, codomain, im_gens, base_map): + """ + Apply a morphism defined by its values on the generators. + + EXAMPLES:: + + sage: ring = algebras.Free(QQ, ['a', 'b']) + sage: a, b = ring.gens() + sage: A = matrix(QQ, 2, 2, [2, 3, 4, 1]) + sage: B = matrix(QQ, 2, 2, [1, 7, 7, 1]) + sage: f = ring.hom([A, B]) + sage: f(a*b+1) + [24 17] + [11 30] + """ + n = self.parent().ngens() + if n == 0: + return codomain.coerce(self) + + if base_map is None: + base_map = codomain + + return codomain.sum(base_map(c) * m(*im_gens) for m, c in list(self)) + def variables(self): """ Return the variables used in ``self``. diff --git a/src/sage/monoids/free_monoid_element.py b/src/sage/monoids/free_monoid_element.py index e540f408f1d..f1fb2424105 100644 --- a/src/sage/monoids/free_monoid_element.py +++ b/src/sage/monoids/free_monoid_element.py @@ -27,6 +27,7 @@ from sage.rings.integer import Integer from sage.structure.element import MonoidElement from sage.structure.richcmp import richcmp, richcmp_not_equal +from sage.rings.semirings.non_negative_integer_semiring import NN def is_FreeMonoidElement(x): @@ -176,8 +177,8 @@ def __call__(self, *x, **kwds): 2 sage: (x*y).subs({x:z,y:z}) z^2 - sage: M1=MatrixSpace(ZZ,1,2) - sage: M2=MatrixSpace(ZZ,2,1) + sage: M1 = MatrixSpace(ZZ,1,2) + sage: M2 = MatrixSpace(ZZ,2,1) sage: (x*y).subs({x:M1([1,2]),y:M2([3,4])}) [11] @@ -189,6 +190,14 @@ def __call__(self, *x, **kwds): sage: a.substitute(a=5) 5 + TESTS:: + + sage: M. = FreeMonoid(2) + sage: (x*y)(QQ(4),QQ(5)).parent() + Rational Field + sage: M.one()(QQ(4),QQ(5)).parent() + Integer Ring + AUTHORS: - Joel B. Mohler (2007-10-27) @@ -211,28 +220,15 @@ def __call__(self, *x, **kwds): if len(x) != self.parent().ngens(): raise ValueError("must specify as many values as generators in parent") - # I don't start with 0, because I don't want to preclude evaluation with - # arbitrary objects (e.g. matrices) because of funny coercion. - one = P.one() - result = None + # careful handling of anything that can be multiplied + # without being in one common parent + result = NN.one() for var_index, exponent in self._element_list: - # Take further pains to ensure that non-square matrices are not exponentiated. replacement = x[var_index] if exponent > 1: - c = replacement ** exponent + result *= replacement ** exponent elif exponent == 1: - c = replacement - else: - c = one - - if result is None: - result = c - else: - result *= c - - if result is None: - return one - + result *= replacement return result def _mul_(self, y): From 5f966bb8a049ffa03c55a00612f803a2fdacbd44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antoine=20Leudi=C3=A8re?= Date: Tue, 11 Jun 2024 17:57:21 +0200 Subject: [PATCH 025/231] Delete _check_rank_two method --- .../drinfeld_modules/drinfeld_module.py | 21 ------------------- 1 file changed, 21 deletions(-) diff --git a/src/sage/rings/function_field/drinfeld_modules/drinfeld_module.py b/src/sage/rings/function_field/drinfeld_modules/drinfeld_module.py index 958347113c0..08fb31ae941 100644 --- a/src/sage/rings/function_field/drinfeld_modules/drinfeld_module.py +++ b/src/sage/rings/function_field/drinfeld_modules/drinfeld_module.py @@ -759,27 +759,6 @@ def _Hom_(self, other, category): from sage.rings.function_field.drinfeld_modules.homset import DrinfeldModuleHomset return DrinfeldModuleHomset(self, other, category) - def _check_rank_two(self): - r""" - Raise ``NotImplementedError`` if the rank is not two. - - TESTS:: - - sage: Fq = GF(25) - sage: A. = Fq[] - sage: K. = Fq.extension(6) - sage: p_root = 2*z12^11 + 2*z12^10 + z12^9 + 3*z12^8 + z12^7 + 2*z12^5 + 2*z12^4 + 3*z12^3 + z12^2 + 2*z12 - sage: phi = DrinfeldModule(A, [p_root, z12^3, z12^5]) - sage: phi._check_rank_two() - sage: phi = DrinfeldModule(A, [p_root, 1]) - sage: phi._check_rank_two() - Traceback (most recent call last): - ... - NotImplementedError: rank must be 2 - """ - if self.rank() != 2: - raise NotImplementedError('rank must be 2') - def _latex_(self): r""" Return a LaTeX representation of the Drinfeld module. From 06cb9797d46ff3f046b3532fbb127de727227894 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antoine=20Leudi=C3=A8re?= Date: Thu, 13 Jun 2024 11:26:55 +0200 Subject: [PATCH 026/231] Re-add and deprecate _check_rank_two --- .../drinfeld_modules/drinfeld_module.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/sage/rings/function_field/drinfeld_modules/drinfeld_module.py b/src/sage/rings/function_field/drinfeld_modules/drinfeld_module.py index 08fb31ae941..6e5f7df858a 100644 --- a/src/sage/rings/function_field/drinfeld_modules/drinfeld_module.py +++ b/src/sage/rings/function_field/drinfeld_modules/drinfeld_module.py @@ -759,6 +759,18 @@ def _Hom_(self, other, category): from sage.rings.function_field.drinfeld_modules.homset import DrinfeldModuleHomset return DrinfeldModuleHomset(self, other, category) + def _check_rank_two(self): + r""" + Raise ``NotImplementedError`` if the rank is not two. + + Do not use this method, it will be removed. + """ + from sage.misc.superseded import deprecation + deprecation(38199, "This semi-private method should not be used. " \ + "It will be removed.") + if self.rank() != 2: + raise NotImplementedError('rank must be 2') + def _latex_(self): r""" Return a LaTeX representation of the Drinfeld module. From a2c07984534054ba55e54fa19cdbaa57ee4f60a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antoine=20Leudi=C3=A8re?= Date: Thu, 13 Jun 2024 11:42:55 +0200 Subject: [PATCH 027/231] Remove useless backslash --- .../rings/function_field/drinfeld_modules/drinfeld_module.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/rings/function_field/drinfeld_modules/drinfeld_module.py b/src/sage/rings/function_field/drinfeld_modules/drinfeld_module.py index 6e5f7df858a..52ab9bf2626 100644 --- a/src/sage/rings/function_field/drinfeld_modules/drinfeld_module.py +++ b/src/sage/rings/function_field/drinfeld_modules/drinfeld_module.py @@ -766,7 +766,7 @@ def _check_rank_two(self): Do not use this method, it will be removed. """ from sage.misc.superseded import deprecation - deprecation(38199, "This semi-private method should not be used. " \ + deprecation(38199, "This semi-private method should not be used. " "It will be removed.") if self.rank() != 2: raise NotImplementedError('rank must be 2') From 411308e02dd008b14f3345fb24b7c45bc0cbd4ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Fri, 14 Jun 2024 13:58:51 +0200 Subject: [PATCH 028/231] better handling of parents --- src/sage/algebras/free_algebra_element.py | 6 ++- src/sage/monoids/free_monoid_element.py | 46 ++++++++++++++++------- 2 files changed, 37 insertions(+), 15 deletions(-) diff --git a/src/sage/algebras/free_algebra_element.py b/src/sage/algebras/free_algebra_element.py index f2c644f3fe3..815be8858b5 100644 --- a/src/sage/algebras/free_algebra_element.py +++ b/src/sage/algebras/free_algebra_element.py @@ -297,12 +297,14 @@ def _im_gens_(self, codomain, im_gens, base_map): """ n = self.parent().ngens() if n == 0: - return codomain.coerce(self) + cf = next(iter(self._monomial_coefficients.values())) + return codomain.coerce(cf) if base_map is None: base_map = codomain - return codomain.sum(base_map(c) * m(*im_gens) for m, c in list(self)) + return codomain.sum(base_map(c) * m(*im_gens) + for m, c in self._monomial_coefficients.items()) def variables(self): """ diff --git a/src/sage/monoids/free_monoid_element.py b/src/sage/monoids/free_monoid_element.py index 9bc144d84bc..8dde7541ed2 100644 --- a/src/sage/monoids/free_monoid_element.py +++ b/src/sage/monoids/free_monoid_element.py @@ -173,31 +173,44 @@ def __call__(self, *x, **kwds): """ EXAMPLES:: + sage: M. = FreeMonoid(2) + sage: (x*y).substitute(x=1) + y + + sage: M. = FreeMonoid(1) + sage: a.substitute(a=5) + 5 + sage: M. = FreeMonoid(3) sage: (x*y).subs(x=1,y=2,z=14) 2 sage: (x*y).subs({x:z,y:z}) z^2 + + It is still possible to substitute elements + that have no common parent:: + sage: M1 = MatrixSpace(ZZ,1,2) # needs sage.modules sage: M2 = MatrixSpace(ZZ,2,1) # needs sage.modules sage: (x*y).subs({x: M1([1,2]), y: M2([3,4])}) # needs sage.modules [11] - sage: M. = FreeMonoid(2) - sage: (x*y).substitute(x=1) - y - - sage: M. = FreeMonoid(1) - sage: a.substitute(a=5) - 5 - TESTS:: sage: M. = FreeMonoid(2) sage: (x*y)(QQ(4),QQ(5)).parent() Rational Field + + The codomain is by default the first parent:: + sage: M.one()(QQ(4),QQ(5)).parent() - Integer Ring + Rational Field + + unless there is no variable and no substitution:: + + sage: M = FreeMonoid(0, []) + sage: M.one()().parent() + Free monoid on 0 generators () AUTHORS: @@ -215,15 +228,22 @@ def __call__(self, *x, **kwds): if key in gens_dict: x[gens_dict[key]] = value - if isinstance(x[0], tuple): + if x and isinstance(x[0], tuple): x = x[0] if len(x) != self.parent().ngens(): raise ValueError("must specify as many values as generators in parent") - # careful handling of anything that can be multiplied - # without being in one common parent - result = NN.one() + # if no substitution, do nothing + if not x: + return self + + try: + # This will land in the parent of the first element + result = x[0].parent().one() + except (AttributeError, TypeError): + # unless the parent has no unit + result = NN.one() for var_index, exponent in self._element_list: replacement = x[var_index] if exponent > 1: From 5faf5a34f44555b2c3e2396799b310c2e7269214 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Fri, 14 Jun 2024 20:47:23 +0200 Subject: [PATCH 029/231] fix doctest --- src/sage/structure/factorization.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/structure/factorization.py b/src/sage/structure/factorization.py index 61a544e1352..8d65ccb1197 100644 --- a/src/sage/structure/factorization.py +++ b/src/sage/structure/factorization.py @@ -1206,7 +1206,7 @@ def __call__(self, *args, **kwds): sage: R. = FreeAlgebra(QQ, 2) sage: F = Factorization([(x,3), (y, 2), (x,1)]) sage: F(x=4) - (1) * 4^3 * y^2 * 4 + 4^3 * y^2 * 4 sage: F.subs({y:2}) x^3 * 2^2 * x From f65d2112433ab60919611060b18f64c39eb78f37 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 15 Jun 2024 17:44:31 -0700 Subject: [PATCH 030/231] build/pkgs/fpylll: Update to 0.6.1 --- build/pkgs/fpylll/checksums.ini | 4 ++-- build/pkgs/fpylll/package-version.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build/pkgs/fpylll/checksums.ini b/build/pkgs/fpylll/checksums.ini index 5cbc7e3bc08..5f258e7518e 100644 --- a/build/pkgs/fpylll/checksums.ini +++ b/build/pkgs/fpylll/checksums.ini @@ -1,4 +1,4 @@ tarball=fpylll-VERSION.tar.gz -sha1=f23835208fc048028c849bb5b566f2fe631df7f4 -sha256=623b4619b6da9fed9ba26b1ac7e8d8e620a06d2a5f7095ee67985c7160d3c3a4 +sha1=c0bcf8c5583ebf614da9b26710a2c835d498bf34 +sha256=dfd9529a26c50993a2a716177debd7994312219070574cad31b35b4f0c040a19 upstream_url=https://pypi.io/packages/source/f/fpylll/fpylll-VERSION.tar.gz diff --git a/build/pkgs/fpylll/package-version.txt b/build/pkgs/fpylll/package-version.txt index a918a2aa18d..ee6cdce3c29 100644 --- a/build/pkgs/fpylll/package-version.txt +++ b/build/pkgs/fpylll/package-version.txt @@ -1 +1 @@ -0.6.0 +0.6.1 From 81f03b4a748d09b924f2fe78b0f24458c5309375 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 16 Jun 2024 17:26:18 -0700 Subject: [PATCH 031/231] tox.ini, .ci/write-dockerfile.sh: Pass GITHUB_ACTIONS through --- .ci/write-dockerfile.sh | 6 ++++++ tox.ini | 1 + 2 files changed, 7 insertions(+) diff --git a/.ci/write-dockerfile.sh b/.ci/write-dockerfile.sh index 3a4ae5b152d..3ff020b22d9 100755 --- a/.ci/write-dockerfile.sh +++ b/.ci/write-dockerfile.sh @@ -260,6 +260,12 @@ case ${DOCKER_BUILDKIT-0} in CHECK_STATUS_THEN='STATUS=$(cat STATUS 2>/dev/null); case "$STATUS" in ""|0) ;; *) exit $STATUS;; esac; ' esac +if [ -n "$GITHUB_ACTIONS" ]; then + cat < Date: Sun, 16 Jun 2024 17:27:47 -0700 Subject: [PATCH 032/231] build/bin/sage-logger [GITHUB_ACTIONS]: Do not truncate log, use ::error: annotation and ::group: --- build/bin/sage-logger | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/build/bin/sage-logger b/build/bin/sage-logger index 419a2231478..9615f56b817 100755 --- a/build/bin/sage-logger +++ b/build/bin/sage-logger @@ -118,9 +118,16 @@ if [ -n "$SAGE_SILENT_BUILD" -a ${use_prefix} = true ]; then ( exec>> $logfile 2>&1; time_cmd "$cmd"; status=$?; report_time; exit $status ) status=$? if [[ $status != 0 ]]; then - echo " [$logname] error installing, exit status $status. End of log file:" - tail -n 120 "$logfile" | sed "/Please email sage-devel/,$ d;s;^; [$logname] ;" >&2 - echo " [$logname] Full log file: $logfile" + if [ -n "$GITHUB_ACTIONS" ]; then + echo :":"error file=$logfile:":" ==== ERROR IN LOG FILE $logfile ==== + echo "::group::${logname}" + sed "s;^; [$logname] ;" "$logfile" >&2 + echo "::endgroup::" + else + echo " [$logname] error installing, exit status $status. End of log file:" + tail -n 120 "$logfile" | sed "/Please email sage-devel/,$ d;s;^; [$logname] ;" >&2 + echo " [$logname] Full log file: $logfile" + fi else time=$(report_time) if [ -n "$time" ]; then From bd9d1a3f680975de06cfd99bec96f880913bb657 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 16 Jun 2024 22:02:43 -0700 Subject: [PATCH 033/231] build/bin/sage-logger [GITHUB_ACTIONS]: Do not try to use ::error: annotation and ::group: --- build/bin/sage-logger | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/build/bin/sage-logger b/build/bin/sage-logger index 9615f56b817..42218fbbb3e 100755 --- a/build/bin/sage-logger +++ b/build/bin/sage-logger @@ -119,10 +119,8 @@ if [ -n "$SAGE_SILENT_BUILD" -a ${use_prefix} = true ]; then status=$? if [[ $status != 0 ]]; then if [ -n "$GITHUB_ACTIONS" ]; then - echo :":"error file=$logfile:":" ==== ERROR IN LOG FILE $logfile ==== - echo "::group::${logname}" + echo " [$logname] error installing, exit status $status. Log file:" sed "s;^; [$logname] ;" "$logfile" >&2 - echo "::endgroup::" else echo " [$logname] error installing, exit status $status. End of log file:" tail -n 120 "$logfile" | sed "/Please email sage-devel/,$ d;s;^; [$logname] ;" >&2 From 227a2ac9080fe4a8a8c8f4546acf980838864acb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Mon, 17 Jun 2024 16:20:46 +0200 Subject: [PATCH 034/231] cleanup for binary recurrence sequences --- .../combinat/binary_recurrence_sequences.py | 378 +++++++++--------- 1 file changed, 181 insertions(+), 197 deletions(-) diff --git a/src/sage/combinat/binary_recurrence_sequences.py b/src/sage/combinat/binary_recurrence_sequences.py index f9c9cdbf2a0..ebe6570cc8b 100644 --- a/src/sage/combinat/binary_recurrence_sequences.py +++ b/src/sage/combinat/binary_recurrence_sequences.py @@ -123,7 +123,6 @@ def __init__(self, b, c, u0=0, u1=1): sage: R = BinaryRecurrenceSequence(1,1) sage: loads(R.dumps()) == R True - """ self.b = b self.c = c @@ -133,7 +132,7 @@ def __init__(self, b, c, u0=0, u1=1): self._PGoodness = {} # dictionary to cache primes that are "good" by some prime power self._ell = 1 # variable that keeps track of the last prime power to be used as a goodness - def __repr__(self): + def __repr__(self) -> str: """ Give string representation of the class. @@ -143,11 +142,10 @@ def __repr__(self): sage: R Binary recurrence sequence defined by: u_n = 3 * u_{n-1} + 3 * u_{n-2}; With initial conditions: u_0 = 2, and u_1 = 1 - """ return 'Binary recurrence sequence defined by: u_n = ' + str(self.b) + ' * u_{n-1} + ' + str(self.c) + ' * u_{n-2};\nWith initial conditions: u_0 = ' + str(self.u0) + ', and u_1 = ' + str(self.u1) - def __eq__(self, other): + def __eq__(self, other) -> bool: """ Compare two binary recurrence sequences. @@ -196,7 +194,7 @@ def __call__(self, n, modulus=0): v = vector(R, [self.u0, self.u1]) return list(F**n * v)[0] - def is_degenerate(self): + def is_degenerate(self) -> bool: """ Decide whether the binary recurrence sequence is degenerate. @@ -243,13 +241,12 @@ def is_degenerate(self): if D.is_square(): A = sqrt(D) else: - K = QuadraticField(D, 'x') - A = K.gen() + A = QuadraticField(D, 'x').gen() - aa = (self.u1 - self.u0*(self.b + A)/2)/(A) #called `a` in Docstring - bb = (self.u1 - self.u0*(self.b - A)/2)/(A) #called `b` in Docstring + aa = (self.u1 - self.u0 * (self.b + A)/2)/(A) # called `a` in Docstring + bb = (self.u1 - self.u0 * (self.b - A)/2)/(A) # called `b` in Docstring - #(b+A)/2 is called alpha in Docstring, (b-A)/2 is called beta in Docstring + # (b+A)/2 is called alpha in Docstring, (b-A)/2 is called beta in Docstring if self.b != A: if ((self.b+A)/(self.b-A))**6 == 1: @@ -261,7 +258,7 @@ def is_degenerate(self): return True - def is_geometric(self): + def is_geometric(self) -> bool: """ Decide whether the binary recurrence sequence is geometric - ie a geometric sequence. @@ -279,14 +276,14 @@ def is_geometric(self): sage: S.is_geometric() True """ - #If [u_0, u_1]^T is an eigenvector for the incrementation matrix F = [[0,1],[c,b]], then the sequence - #is geometric, ie we can write u_n = a*r^n for some a and r. + # If [u_0, u_1]^T is an eigenvector for the incrementation matrix F = [[0,1],[c,b]], then the sequence + # is geometric, ie we can write u_n = a*r^n for some a and r. - #We decide if u0, u1, u2 = b*u1+c*u0 are in geometric progression by whether u1^2 = (b*u1+c*u0)*u0 + # We decide if u0, u1, u2 = b*u1+c*u0 are in geometric progression by whether u1^2 = (b*u1+c*u0)*u0 return (self.u1)**2 == (self.b*self.u1 + self.c*self.u0)*self.u0 - def is_quasigeometric(self): + def is_quasigeometric(self) -> bool: """ Decide whether the binary recurrence sequence is degenerate and similar to a geometric sequence, i.e. the union of multiple geometric sequences, or geometric after term ``u0``. @@ -323,14 +320,13 @@ def is_quasigeometric(self): if D.is_square(): A = sqrt(D) else: - K = QuadraticField(D, 'x') - A = K.gen() + A = QuadraticField(D, 'x').gen() if ((self.b+A)/(self.b-A))**6 == 1: return True return False - def is_arithmetic(self): + def is_arithmetic(self) -> bool: """ Decide whether the sequence is degenerate and an arithmetic sequence. @@ -347,7 +343,7 @@ def is_arithmetic(self): sage: S.is_arithmetic() True """ - return (self(1) - self(0) == self(2) - self(1) == self(3) - self(2)) + return self(1) - self(0) == self(2) - self(1) == self(3) - self(2) def period(self, m): """ @@ -398,7 +394,7 @@ def period(self, m): .. NOTE:: The answer is cached. """ - #If we have already computed the period mod m, then we return the stored value. + # If we have already computed the period mod m, then we return the stored value. if m in self._period_dict: return self._period_dict[m] @@ -410,17 +406,17 @@ def period(self, m): Fac = list(m.factor()) Periods = {} - #To compute the period mod m, we compute the least integer n such that A^n*w == w. This necessarily - #divides the order of A as a matrix in GL_2(Z/mZ). + # To compute the period mod m, we compute the least integer n such that A^n*w == w. This necessarily + # divides the order of A as a matrix in GL_2(Z/mZ). - #We compute the period modulo all distinct prime powers dividing m, and combine via the lcm. - #To compute the period mod p^e, we first compute the order mod p. Then the period mod p^e - #must divide p^{4e-4}*period(p), as the subgroup of matrices mod p^e, which reduce to - #the identity mod p is of order (p^{e-1})^4. So we compute the period mod p^e by successively - #multiplying the period mod p by powers of p. + # We compute the period modulo all distinct prime powers dividing m, and combine via the lcm. + # To compute the period mod p^e, we first compute the order mod p. Then the period mod p^e + # must divide p^{4e-4}*period(p), as the subgroup of matrices mod p^e, which reduce to + # the identity mod p is of order (p^{e-1})^4. So we compute the period mod p^e by successively + # multiplying the period mod p by powers of p. for p, e in Fac: - #first compute the period mod p + # first compute the period mod p if p in self._period_dict: perp = self._period_dict[p] else: @@ -429,29 +425,29 @@ def period(self, m): FF = F**(p-1) p1fac = list((p-1).factor()) - #The order of any matrix in GL_2(F_p) either divides p(p-1) or (p-1)(p+1). - #The order divides p-1 if it is diagonalizable. In any case, det(F^(p-1))=1, - #so if tr(F^(p-1)) = 2, then it must be triangular of the form [[1,a],[0,1]]. - #The order of the subgroup of matrices of this form is p, so the order must divide - #p(p-1) -- in fact it must be a multiple of p. If this is not the case, then the - #order divides (p-1)(p+1). As the period divides the order of the matrix in GL_2(F_p), - #these conditions hold for the period as well. + # The order of any matrix in GL_2(F_p) either divides p(p-1) or (p-1)(p+1). + # The order divides p-1 if it is diagonalizable. In any case, det(F^(p-1))=1, + # so if tr(F^(p-1)) = 2, then it must be triangular of the form [[1,a],[0,1]]. + # The order of the subgroup of matrices of this form is p, so the order must divide + # p(p-1) -- in fact it must be a multiple of p. If this is not the case, then the + # order divides (p-1)(p+1). As the period divides the order of the matrix in GL_2(F_p), + # these conditions hold for the period as well. - #check if the order divides (p-1) + # check if the order divides (p-1) if FF*v == v: M = p-1 Mfac = p1fac - #check if the trace is 2, then the order is a multiple of p dividing p*(p-1) + # check if the trace is 2, then the order is a multiple of p dividing p*(p-1) elif FF.trace() == 2: M = p-1 Mfac = p1fac - F = F**p #replace F by F^p as now we only need to determine the factor dividing (p-1) + F = F**p # replace F by F^p as now we only need to determine the factor dividing (p-1) - #otherwise it will divide (p+1)(p-1) + # otherwise it will divide (p+1)(p-1) else: M = (p+1)*(p-1) - p2fac = list((p+1).factor()) #factor the (p+1) and (p-1) terms separately and then combine for speed + p2fac = list((p+1).factor()) # factor the (p+1) and (p-1) terms separately and then combine for speed Mfac_dic = {} for i0, i1 in list(p1fac + p2fac): if i0 not in Mfac_dic: @@ -460,19 +456,15 @@ def period(self, m): Mfac_dic[i0] += i1 Mfac = list(Mfac_dic.items()) - #Now use a fast order algorithm to compute the period. We know that the period divides - #M = i_1*i_2*...*i_l where the i_j denote not necessarily distinct prime factors. As - #F^M*v == v, for each i_j, if F^(M/i_j)*v == v, then the period divides (M/i_j). After - #all factors have been iterated over, the result is the period mod p. + # Now use a fast order algorithm to compute the period. We know that the period divides + # M = i_1*i_2*...*i_l where the i_j denote not necessarily distinct prime factors. As + # F^M*v == v, for each i_j, if F^(M/i_j)*v == v, then the period divides (M/i_j). After + # all factors have been iterated over, the result is the period mod p. Mfac = list(Mfac) - C = [] - - #expand the list of prime factors so every factor is with multiplicity 1 - for i0, i1 in Mfac: - for _ in range(i1): - C.append(i0) + # expand the list of prime factors so every factor is with multiplicity 1 + C = [i0 for i0, i1 in Mfac for _ in range(i1)] Mfac = C n = M @@ -482,7 +474,7 @@ def period(self, m): n = b perp = n - #Now compute the period mod p^e by stepping up by multiples of p + # Now compute the period mod p^e by stepping up by multiples of p F = A.change_ring(Integers(p**e)) v = w.change_ring(Integers(p**e)) FF = F**perp @@ -498,12 +490,10 @@ def period(self, m): break Periods[p] = perpe - #take the lcm of the periods mod all distinct primes dividing m - period = 1 - for p in Periods: - period = lcm(Periods[p], period) + # take the lcm of the periods mod all distinct primes dividing m + period = lcm(Periods.values()) - self._period_dict[m] = period #cache the period mod m + self._period_dict[m] = period # cache the period mod m return period def pthpowers(self, p, Bound): @@ -569,17 +559,17 @@ def pthpowers(self, p, Bound): This function is primarily optimized in the range where ``Bound`` is much larger than ``p``. """ - #Thanks to Jesse Silliman for helpful conversations! + # Thanks to Jesse Silliman for helpful conversations! - #Reset the dictionary of good primes, as this depends on p + # Reset the dictionary of good primes, as this depends on p self._PGoodness = {} - #Starting lower bound on good primes + # Starting lower bound on good primes self._ell = 1 - #If the sequence is geometric, then the `n`th term is `a*r^n`. Thus the - #property of being a ``p`` th power is periodic mod ``p``. So there are either - #no ``p`` th powers if there are none in the first ``p`` terms, or many if there - #is at least one in the first ``p`` terms. + # If the sequence is geometric, then the `n`th term is `a*r^n`. Thus the + # property of being a ``p`` th power is periodic mod ``p``. So there are either + # no ``p`` th powers if there are none in the first ``p`` terms, or many if there + # is at least one in the first ``p`` terms. if self.is_geometric() or self.is_quasigeometric(): no_powers = True @@ -594,50 +584,50 @@ def pthpowers(self, p, Bound): else: raise ValueError("the degenerate binary recurrence sequence is geometric or quasigeometric and has many pth powers") - #If the sequence is degenerate without being geometric or quasigeometric, there - #may be many ``p`` th powers or no ``p`` th powers. + # If the sequence is degenerate without being geometric or quasigeometric, there + # may be many ``p`` th powers or no ``p`` th powers. elif (self.b**2+4*self.c) == 0: - #This is the case if the matrix F is not diagonalizable, ie b^2 +4c = 0, and alpha/beta = 1. + # This is the case if the matrix F is not diagonalizable, ie b^2 +4c = 0, and alpha/beta = 1. alpha = self.b/2 - #In this case, u_n = u_0*alpha^n + (u_1 - u_0*alpha)*n*alpha^(n-1) = alpha^(n-1)*(u_0 +n*(u_1 - u_0*alpha)), - #that is, it is a geometric term (alpha^(n-1)) times an arithmetic term (u_0 + n*(u_1-u_0*alpha)). + # In this case, u_n = u_0*alpha^n + (u_1 - u_0*alpha)*n*alpha^(n-1) = alpha^(n-1)*(u_0 +n*(u_1 - u_0*alpha)), + # that is, it is a geometric term (alpha^(n-1)) times an arithmetic term (u_0 + n*(u_1-u_0*alpha)). - #Look at classes n = k mod p, for k = 1,...,p. + # Look at classes n = k mod p, for k = 1,...,p. for k in range(1, p + 1): - #The linear equation alpha^(k-1)*u_0 + (k+pm)*(alpha^(k-1)*u1 - u0*alpha^k) - #must thus be a pth power. This is a linear equation in m, namely, A + B*m, where + # The linear equation alpha^(k-1)*u_0 + (k+pm)*(alpha^(k-1)*u1 - u0*alpha^k) + # must thus be a pth power. This is a linear equation in m, namely, A + B*m, where A = (alpha**(k-1)*self.u0 + k*(alpha**(k-1)*self.u1 - self.u0*alpha**k)) B = p*(alpha**(k-1)*self.u1 - self.u0*alpha**k) - #This linear equation represents a pth power iff A is a pth power mod B. + # This linear equation represents a pth power iff A is a pth power mod B. if _is_p_power_mod(A, p, B): raise ValueError("the degenerate binary recurrence sequence has many pth powers") return [] - #We find ``p`` th powers using an elementary sieve. Term `u_n` is a ``p`` th - #power if and only if it is a ``p`` th power modulo every prime `\\ell`. This condition - #gives nontrivial information if ``p`` divides the order of the multiplicative group of - #`\\Bold(F)_{\\ell}`, i.e. if `\\ell` is ` 1 \mod{p}`, as then only `1/p` terms are ``p`` th - #powers modulo `\\ell``. + # We find ``p`` th powers using an elementary sieve. Term `u_n` is a ``p`` th + # power if and only if it is a ``p`` th power modulo every prime `\\ell`. This condition + # gives nontrivial information if ``p`` divides the order of the multiplicative group of + # `\\Bold(F)_{\\ell}`, i.e. if `\\ell` is ` 1 \mod{p}`, as then only `1/p` terms are ``p`` th + # powers modulo `\\ell``. - #Thus, given such an `\\ell`, we get a set of necessary congruences for the index modulo the - #the period of the sequence mod `\\ell`. Then we intersect these congruences for many primes - #to get a tight list modulo a growing modulus. In order to keep this step manageable, we - #only use primes `\\ell` that have particularly smooth periods. + # Thus, given such an `\\ell`, we get a set of necessary congruences for the index modulo the + # the period of the sequence mod `\\ell`. Then we intersect these congruences for many primes + # to get a tight list modulo a growing modulus. In order to keep this step manageable, we + # only use primes `\\ell` that have particularly smooth periods. - #Some congruences in the list will remain as the modulus grows. If a congruence remains through - #7 rounds of increasing the modulus, then we check if this corresponds to a perfect power (if - #it does, we add it to our list of indices corresponding to ``p`` th powers). The rest of the congruences - #are transient and grow with the modulus. Once the smallest of these is greater than the bound, - #the list of known indices corresponding to ``p`` th powers is complete. + # Some congruences in the list will remain as the modulus grows. If a congruence remains through + # 7 rounds of increasing the modulus, then we check if this corresponds to a perfect power (if + # it does, we add it to our list of indices corresponding to ``p`` th powers). The rest of the congruences + # are transient and grow with the modulus. Once the smallest of these is greater than the bound, + # the list of known indices corresponding to ``p`` th powers is complete. else: @@ -656,50 +646,50 @@ def pthpowers(self, p, Bound): for n in range(Bound): # n is the index of the a0 - #Check whether a0 is a perfect power mod ell + # Check whether a0 is a perfect power mod ell if _is_p_power_mod(a0, p, ell): - #if a0 is a perfect power mod ell, check if nth term is ppower + # if a0 is a perfect power mod ell, check if nth term is ppower if _is_p_power(self(n), p): powers.append(n) - a0, a1 = a1, bf*a1 + cf*a0 #step up the variables + a0, a1 = a1, bf*a1 + cf*a0 # step up the variables else: - powers = [] #documents the indices of the sequence that provably correspond to pth powers - cong = [0] #list of necessary congruences on the index for it to correspond to pth powers - Possible_count = {} #keeps track of the number of rounds a congruence lasts in cong + powers = [] # documents the indices of the sequence that provably correspond to pth powers + cong = [0] # list of necessary congruences on the index for it to correspond to pth powers + Possible_count = {} # keeps track of the number of rounds a congruence lasts in cong - #These parameters are involved in how we choose primes to increase the modulus - qqold = 1 #we believe that we know complete information coming from primes good by qqold - M1 = 1 #we have congruences modulo M1, this may not be the tightest list - M2 = p #we want to move to have congruences mod M2 - qq = 1 #the largest prime power divisor of M1 is qq + # These parameters are involved in how we choose primes to increase the modulus + qqold = 1 # we believe that we know complete information coming from primes good by qqold + M1 = 1 # we have congruences modulo M1, this may not be the tightest list + M2 = p # we want to move to have congruences mod M2 + qq = 1 # the largest prime power divisor of M1 is qq - #This loop ups the modulus. + # This loop ups the modulus. while True: - #Try to get good data mod M2 + # Try to get good data mod M2 - #patience of how long we should search for a "good prime" - patience = 0.01 * _estimated_time(lcm(M2, p*next_prime_power(qq)), M1, len(cong), p) + # patience of how long we should search for a "good prime" + patience = 0.01 * _estimated_time(lcm(M2, p * next_prime_power(qq)), + M1, len(cong), p) tries = 0 - #This loop uses primes to get a small set of congruences mod M2. + # This loop uses primes to get a small set of congruences mod M2. while True: - #only proceed if took less than patience time to find the next good prime + # only proceed if took less than patience time to find the next good prime ell = _next_good_prime(p, self, qq, patience, qqold) if ell: - #gather congruence data for the sequence mod ell, which will be mod period(ell) = modu + # gather congruence data for the sequence mod ell, which will be mod period(ell) = modu cong1, modu = _find_cong1(p, self, ell) - CongNew = [] # makes a new list from cong that is now mod M = lcm(M1, modu) instead of M1 + # makes a new list from cong that is now mod M = lcm(M1, modu) instead of M1 M = lcm(M1, modu) - for k in range(M // M1): - for i in cong: - CongNew.append(k * M1 + i) + CongNew = [k * M1 + i for k in range(M // M1) + for i in cong] cong = set(CongNew) M1 = M @@ -728,15 +718,15 @@ def pthpowers(self, p, Bound): cong = list(cong) break - #Document how long each element of cong has been there + # Document how long each element of cong has been there for i in cong: if i in Possible_count: Possible_count[i] += 1 else: Possible_count[i] = 1 - #Check how long each element has persisted, if it is for at least 7 cycles, - #then we check to see if it is actually a perfect power + # Check how long each element has persisted, if it is for at least 7 cycles, + # then we check to see if it is actually a perfect power for i in Possible_count: if Possible_count[i] == 7: n = Integer(i) @@ -744,7 +734,7 @@ def pthpowers(self, p, Bound): if _is_p_power(self(n), p): powers.append(n) - #check for a contradiction + # check for a contradiction if len(cong) > len(powers): if cong[len(powers)] > Bound: break @@ -869,60 +859,56 @@ def _next_good_prime(p, R, qq, patience, qqold): False """ + # We are looking for pth powers in R. + # Our primes must be good by qq, but not qqold. + # We only allow patience number of iterations to find a good prime. - #We are looking for pth powers in R. - #Our primes must be good by qq, but not qqold. - #We only allow patience number of iterations to find a good prime. + # The variable _ell for R keeps track of the last "good" prime returned + # that was not found from the dictionary _PGoodness - #The variable _ell for R keeps track of the last "good" prime returned - #that was not found from the dictionary _PGoodness + # First, we check to see if we have already computed the goodness of a prime that fits + # our requirement of being good by qq but not by qqold. This is stored in the _PGoodness + # dictionary. - #First, we check to see if we have already computed the goodness of a prime that fits - #our requirement of being good by qq but not by qqold. This is stored in the _PGoodness - #dictionary. + # Then if we have, we return the smallest such prime and delete it from the list. If not, we + # search through patience number of primes R._ell to find one good by qq but not qqold. If it is + # not good by either qqold or qq, then we add this prime to R._PGoodness under its goodness. - #Then if we have, we return the smallest such prime and delete it from the list. If not, we - #search through patience number of primes R._ell to find one good by qq but not qqold. If it is - #not good by either qqold or qq, then we add this prime to R._PGoodness under its goodness. + # Possible_Primes keeps track of possible primes satisfying our goodness requirements we might return + # check to see if anything in R._PGoodness fits our goodness requirements + Possible_Primes = [item[0] for j, item in R._PGoodness.items() + if qqold < j <= qq and item] - #Possible_Primes keeps track of possible primes satisfying our goodness requirements we might return - Possible_Primes = [] - - #check to see if anything in R._PGoodness fits our goodness requirements - for j in R._PGoodness: - if (qqold < j <= qq) and len(R._PGoodness[j]): - Possible_Primes.append(R._PGoodness[j][0]) - - #If we found good primes, we take the smallest + # If we found good primes, we take the smallest if Possible_Primes: q = min(Possible_Primes) n = _goodness(q, R, p) - del R._PGoodness[n][0] #if we are going to use it, then we delete it from R._PGoodness + del R._PGoodness[n][0] # if we are going to use it, then we delete it from R._PGoodness return q - #If nothing is already stored in R._PGoodness, we start (from where we left off at R._ell) checking - #for good primes. We only tolerate patience number of tries before giving up. + # If nothing is already stored in R._PGoodness, we start (from where we left off at R._ell) checking + # for good primes. We only tolerate patience number of tries before giving up. else: i = 0 while i < patience: i += 1 R._ell = next_prime(R._ell) - #we require that R._ell is 1 mod p, so that p divides the order of the multiplicative - #group mod R._ell, so that not all elements of GF(R._ell) are pth powers. + # we require that R._ell is 1 mod p, so that p divides the order of the multiplicative + # group mod R._ell, so that not all elements of GF(R._ell) are pth powers. if R._ell % p == 1: - #requiring that b^2 + 4c is a square in GF(R._ell) ensures that the period mod R._ell - #divides R._ell - 1 - if legendre_symbol(R.b**2+4*R.c, R._ell) == 1: + # requiring that b^2 + 4c is a square in GF(R._ell) ensures that the period mod R._ell + # divides R._ell - 1 + if legendre_symbol(R.b**2 + 4 * R.c, R._ell) == 1: N = _goodness(R._ell, R, p) - #proceed only if R._ell satisfies the goodness requirements + # proceed only if R._ell satisfies the goodness requirements if qqold < N <= qq: return R._ell - #if we do not use the prime, we store it in R._PGoodness + # if we do not use the prime, we store it in R._PGoodness else: if N in R._PGoodness: R._PGoodness[N].append(R._ell) @@ -958,19 +944,17 @@ def _is_p_power_mod(a, p, N): False sage: sage.combinat.binary_recurrence_sequences._is_p_power_mod(2**3,3,29) True - """ - - #By the chinese remainder theorem, we can answer this question by examining whether - #a is a pth power mod q^e, for all distinct prime powers q^e dividing N. + # By the chinese remainder theorem, we can answer this question by examining whether + # a is a pth power mod q^e, for all distinct prime powers q^e dividing N. for q, e in N.factor(): - #If a = q^v*x, with + # If a = q^v*x, with v = a.valuation(q) - #then if v>=e, a is congruent to 0 mod q^e and is thus a pth power trivially. + # then if v>=e, a is congruent to 0 mod q^e and is thus a pth power trivially. if v >= e: continue @@ -979,58 +963,58 @@ def _is_p_power_mod(a, p, N): if v % p: return False - #in this cse it is a pth power if x is a pth power mod q^(e-v), so let x = aa, - #and (e-v) = ee: + # in this cse it is a pth power if x is a pth power mod q^(e-v), so let x = aa, + # and (e-v) = ee: - aa = a/q**v + aa = a / q**v ee = e - v - #The above steps are equivalent to the statement that we may assume a and qq are - #relatively prime, if we replace a with aa and e with ee. Now we must determine when - #aa is a pth power mod q^ee for (aa,q)=1. + # The above steps are equivalent to the statement that we may assume a and qq are + # relatively prime, if we replace a with aa and e with ee. Now we must determine when + # aa is a pth power mod q^ee for (aa,q)=1. - #If q != p, then by Hensel's lemma, we may lift a pth power mod q, to a pth power - #mod q^2, etc. + # If q != p, then by Hensel's lemma, we may lift a pth power mod q, to a pth power + # mod q^2, etc. if q != p: - #aa is necessarily a pth power mod q if p does not divide the order of the multiplicative - #group mod q, ie if q is not 1 mod p. + # aa is necessarily a pth power mod q if p does not divide the order of the multiplicative + # group mod q, ie if q is not 1 mod p. if q % p == 1: - #otherwise aa if a pth power mod q iff aa^(q-1)/p == 1 + # otherwise aa if a pth power mod q iff aa^(q-1)/p == 1 - if GF(q)(aa)**((q-1)/p) != 1: + if GF(q)(aa)**((q - 1) / p) != 1: return False - #If q = p and ee = 1, then everything is a pth power p by Fermat's little theorem. + # If q = p and ee = 1, then everything is a pth power p by Fermat's little theorem. elif ee > 1: - #We use the strong statement of Hensel's lemma, which implies that if p is odd - #and aa is a pth power mod p^2, then aa is a pth power mod any higher power of p + # We use the strong statement of Hensel's lemma, which implies that if p is odd + # and aa is a pth power mod p^2, then aa is a pth power mod any higher power of p if p % 2: - #ZZ/(p^2)ZZ^\times is abstractly isomorphic to ZZ/(p)ZZ cross ZZ/(p-1)ZZ. then - #aa is a pth power mod p^2 if (aa)^(p*(p-1)/p) == 1, ie if aa^(p-1) == 1. + # ZZ/(p^2)ZZ^\times is abstractly isomorphic to ZZ/(p)ZZ cross ZZ/(p-1)ZZ. then + # aa is a pth power mod p^2 if (aa)^(p*(p-1)/p) == 1, ie if aa^(p-1) == 1. - if Integers(p**2)(aa)**(p-1) != 1: + if Integers(p**2)(aa)**(p - 1) != 1: return False - #Otherwise, p=2. By the strong statement of Hensel's lemma, if aa is a pth power - #mod p^3, then it is a pth power mod higher powers of p. So we need only check if it - #is a pth power mod p^2 and p^3. + # Otherwise, p=2. By the strong statement of Hensel's lemma, if aa is a pth power + # mod p^3, then it is a pth power mod higher powers of p. So we need only check if it + # is a pth power mod p^2 and p^3. elif ee == 2: - #all odd squares a 1 mod 4 + # all odd squares a 1 mod 4 if aa % 4 != 1: return False - #all odd squares are 1 mod 8 + # all odd squares are 1 mod 8 elif aa % 8 != 1: return False @@ -1061,21 +1045,19 @@ def _estimated_time(M2, M1, length, p): sage: from sage.combinat.binary_recurrence_sequences import _estimated_time sage: _estimated_time(2**4*3**2*5*7*11*13*17, 2**4*3**2*5*7*11*13, 20, 7) # needs sage.symbolic 106.211159309421 - """ + # The heuristic run time of the CRT step to go from modulus M1 to M2 - #The heuristic run time of the CRT step to go from modulus M1 to M2 - - #length is the current length of cong + # length is the current length of cong - Q = p * log(M2) #Size of our primes. - NPrimes = log(M2/M1) / log(Q) #The number of primes + Q = p * log(M2) # Size of our primes. + NPrimes = log(M2 / M1) / log(Q) # The number of primes - return (length * (Q/p)**NPrimes).n() + return (length * (Q / p)**NPrimes).n() -#Find the list of necessary congruences for the index n of binary recurrence -#sequence R using the fact that the reduction mod ell must be a pth power +# Find the list of necessary congruences for the index n of binary recurrence +# sequence R using the fact that the reduction mod ell must be a pth power def _find_cong1(p, R, ell): """ Find the list of permissible indices `n` for which `u_n = y^p` mod ``ell``. @@ -1103,33 +1085,33 @@ def _find_cong1(p, R, ell): u1 = F(R.u1) bf, cf = F(R.b), F(R.c) a0 = u0 - a1 = u1 #a0 and a1 are variables for terms in sequence + a1 = u1 # a0 and a1 are variables for terms in sequence - #The set of pth powers mod ell + # The set of pth powers mod ell PPowers = set(i**p for i in F) - #The period of R mod ell + # The period of R mod ell modu = R.period(ell) - #cong1 keeps track of congruences mod modu for the sequence mod ell + # cong1 keeps track of congruences mod modu for the sequence mod ell cong1 = [] - for n in range(modu): # n is the index of the a0 + for n in range(modu): # n is the index of the a0 - #Check whether a0 is a perfect power mod ell + # Check whether a0 is a perfect power mod ell if a0 in PPowers: - #if a0 is a perfect power mod ell, add the index - #to the list of necessary congruences + # if a0 is a perfect power mod ell, add the index + # to the list of necessary congruences cong1.append(n) - a0, a1 = a1, bf*a1 + cf*a0 #step up the variables + a0, a1 = a1, bf * a1 + cf * a0 # step up the variables cong1.sort() return cong1, modu -def _is_p_power(a, p): +def _is_p_power(a, p) -> bool: """ Determine whether ``a`` is a perfect ``p`` th power. @@ -1141,16 +1123,18 @@ def _is_p_power(a, p): OUTPUT: - - True if ``a`` is a ``p`` th power; else False. + boolean, whether ``a`` is a ``p`` th power EXAMPLES:: - sage: sage.combinat.binary_recurrence_sequences._is_p_power(2**7, 7) # needs sage.symbolic + sage: from sage.combinat.binary_recurrence_sequences import _is_p_power + sage: _is_p_power(2**7, 7) True - sage: sage.combinat.binary_recurrence_sequences._is_p_power(2**7*3**2, 7) # needs sage.symbolic + sage: _is_p_power(2**7*3**2, 7) False """ - return int(a**(1/p))**p == a - # slower tentative ? - # _, test = Integer(a).nth_root(p, truncate_mode=True) - # return test + try: + Integer(a).nth_root(p) + except ValueError: + return False + return True From e050fd5fa9005b810296535ac728abc9cfcd013c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Mon, 17 Jun 2024 17:23:11 +0200 Subject: [PATCH 035/231] Update binary_recurrence_sequences.py fix typos --- src/sage/combinat/binary_recurrence_sequences.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/combinat/binary_recurrence_sequences.py b/src/sage/combinat/binary_recurrence_sequences.py index ebe6570cc8b..f473ce162f2 100644 --- a/src/sage/combinat/binary_recurrence_sequences.py +++ b/src/sage/combinat/binary_recurrence_sequences.py @@ -214,7 +214,7 @@ def is_degenerate(self) -> bool: - `F` is nondiagonalizable -- this corresponds to `\\alpha = \\beta`. This sequence will be the point-wise product of an arithmetic and geometric sequence. - - `F^k` is scaler, for some `k>1` -- this corresponds to `\\alpha/\\beta` a `k` th root of unity. This sequence is a union of several geometric sequences, and so we again call it ``quasigeometric``. + - `F^k` is scalar, for some `k>1` -- this corresponds to `\\alpha/\\beta` a `k` th root of unity. This sequence is a union of several geometric sequences, and so we again call it ``quasigeometric``. EXAMPLES:: @@ -289,7 +289,7 @@ def is_quasigeometric(self) -> bool: i.e. the union of multiple geometric sequences, or geometric after term ``u0``. If `\\alpha/\\beta` is a `k` th root of unity, where `k>1`, then necessarily `k = 2, 3, 4, 6`. - Then `F = [[0,1],[c,b]` is diagonalizable, and `F^k = [[\\alpha^k, 0], [0,\\beta^k]]` is scaler + Then `F = [[0,1],[c,b]` is diagonalizable, and `F^k = [[\\alpha^k, 0], [0,\\beta^k]]` is a scalar matrix. Thus for all values of `j` mod `k`, the `j` mod `k` terms of `u_n` form a geometric series. From cdfaf8fd3b2a1e91fdf147590602b2e1ae4047a1 Mon Sep 17 00:00:00 2001 From: hadipourh Date: Mon, 17 Jun 2024 18:36:11 +0200 Subject: [PATCH 036/231] Debug component_function in S-box Module and Add the S-box of WARP Block Cipher --- src/sage/crypto/sbox.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/crypto/sbox.pyx b/src/sage/crypto/sbox.pyx index f177a9558a5..b786af7b0f3 100644 --- a/src/sage/crypto/sbox.pyx +++ b/src/sage/crypto/sbox.pyx @@ -1332,7 +1332,7 @@ cdef class SBox(SageObject): sage: from sage.crypto.sboxes import SBox sage: sb = SBox([0, 1, 2, 3, 0, 1, 2, 3]) sage: sb.component_function([1, 0]) - Boolean function with 3 variabl + Boolean function with 3 variables """ cdef Py_ssize_t m = self.m cdef Py_ssize_t n = self.n From d0fd16dd7178d7861fa147885f8e782576303eed Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 17 Jun 2024 11:18:07 -0700 Subject: [PATCH 037/231] MatrixSpace.zero_matrix: Pass entries=None to the element class --- src/sage/matrix/matrix_space.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/sage/matrix/matrix_space.py b/src/sage/matrix/matrix_space.py index 473d961d090..b5c49c76ce2 100644 --- a/src/sage/matrix/matrix_space.py +++ b/src/sage/matrix/matrix_space.py @@ -2170,9 +2170,20 @@ def zero_matrix(self): False sage: MM.zero().is_mutable() False + + Check that :issue:`38221` is fixed:: + + sage: # needs sage.groups + sage: G = CyclicPermutationGroup(7) + sage: R = GF(2) + sage: A = G.algebra(R) + sage: S = MatrixSpace(A, 3, 3) + sage: S.zero_matrix() + [0 0 0] + [0 0 0] + [0 0 0] """ - zero = self.base_ring().zero() - res = self.element_class(self, zero, False, False) + res = self.element_class(self, None, False, False) res.set_immutable() return res From 8e46414f148ba221c579bbc9765e5a409679363c Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 17 Jun 2024 11:32:06 -0700 Subject: [PATCH 038/231] sage.matrix.special.zero_matrix: Use MatrixSpace.matrix(None) --- src/sage/matrix/special.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/sage/matrix/special.py b/src/sage/matrix/special.py index 38f0876d589..1f4f95be263 100644 --- a/src/sage/matrix/special.py +++ b/src/sage/matrix/special.py @@ -1000,11 +1000,23 @@ def zero_matrix(ring, nrows=None, ncols=None, sparse=False): [0 0 0 0 0] [0 0 0 0 0] + TESTS: + + Check that :issue:`38221` is fixed:: + + sage: # needs sage.groups + sage: G = CyclicPermutationGroup(7) + sage: R = GF(2) + sage: A = G.algebra(R) + sage: zero_matrix(A, 3, 3) + [0 0 0] + [0 0 0] + [0 0 0] """ if isinstance(ring, (Integer, int)): nrows, ncols = (ring, nrows) ring = ZZ - return matrix_space.MatrixSpace(ring, nrows, ncols, sparse)(0) + return matrix_space.MatrixSpace(ring, nrows, ncols, sparse).matrix(None) @matrix_method From 6ed0045e12176a8fe15cbed45d8ecf99309ebc75 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 17 Jun 2024 11:55:29 -0700 Subject: [PATCH 039/231] MatrixArgs.get_type: Recognize elements of the base ring as MA_ENTRIES_SCALAR --- src/sage/matrix/args.pyx | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/sage/matrix/args.pyx b/src/sage/matrix/args.pyx index 4f578440df6..47633736f25 100644 --- a/src/sage/matrix/args.pyx +++ b/src/sage/matrix/args.pyx @@ -1500,6 +1500,21 @@ cdef class MatrixArgs: Traceback (most recent call last): ... NameError: name 'a' is not defined + + Check that :issue:`38221` is fixed:: + + sage: # needs sage.groups + sage: G = CyclicPermutationGroup(7) + sage: R = GF(2) + sage: A = G.algebra(R) + sage: matrix(A, 3, 3, A.zero()) + [0 0 0] + [0 0 0] + [0 0 0] + sage: matrix(A, 3, 3, A.one()) + [() 0 0] + [ 0 () 0] + [ 0 0 ()] """ # Check basic Python types. This is very fast, so it doesn't # hurt to do these first. @@ -1524,6 +1539,8 @@ cdef class MatrixArgs: cdef bint is_elt = isinstance(self.entries, Element) if is_elt and isinstance(self.entries, Matrix): return MA_ENTRIES_MATRIX + if is_elt and self.base is not None and self.entries.parent() == self.base: + return MA_ENTRIES_SCALAR t = type(self.entries) try: f = t._matrix_ From 4ff67bbade440d7d1ccf3bae6438ee2e61d10764 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 17 Jun 2024 18:04:46 -0700 Subject: [PATCH 040/231] src/sage/geometry/hyperbolic_space: Add # needs --- .../hyperbolic_space/hyperbolic_coercion.py | 4 ++-- .../hyperbolic_space/hyperbolic_geodesic.py | 6 ++--- .../hyperbolic_space/hyperbolic_isometry.py | 1 + .../hyperbolic_space/hyperbolic_model.py | 23 ++++++++++--------- .../hyperbolic_space/hyperbolic_point.py | 12 +++++----- 5 files changed, 24 insertions(+), 22 deletions(-) diff --git a/src/sage/geometry/hyperbolic_space/hyperbolic_coercion.py b/src/sage/geometry/hyperbolic_space/hyperbolic_coercion.py index ff509d0d97f..c88d573e0cb 100644 --- a/src/sage/geometry/hyperbolic_space/hyperbolic_coercion.py +++ b/src/sage/geometry/hyperbolic_space/hyperbolic_coercion.py @@ -649,7 +649,7 @@ def SL2R_to_SO21(A): sage: from sage.geometry.hyperbolic_space.hyperbolic_coercion import SL2R_to_SO21 sage: A = SL2R_to_SO21(identity_matrix(2)) sage: J = matrix([[1,0,0],[0,1,0],[0,0,-1]]) #Lorentzian Gram matrix - sage: norm(A.transpose()*J*A - J) < 10**-4 + sage: norm(A.transpose()*J*A - J) < 10**-4 # needs scipy True """ a, b, c, d = (A/A.det().sqrt()).list() @@ -689,7 +689,7 @@ def SO21_to_SL2R(M): EXAMPLES:: sage: from sage.geometry.hyperbolic_space.hyperbolic_coercion import SO21_to_SL2R - sage: (SO21_to_SL2R(identity_matrix(3)) - identity_matrix(2)).norm() < 10**-4 + sage: (SO21_to_SL2R(identity_matrix(3)) - identity_matrix(2)).norm() < 10**-4 # needs scipy True """ #################################################################### diff --git a/src/sage/geometry/hyperbolic_space/hyperbolic_geodesic.py b/src/sage/geometry/hyperbolic_space/hyperbolic_geodesic.py index ae51d2431d2..cb541e295d0 100644 --- a/src/sage/geometry/hyperbolic_space/hyperbolic_geodesic.py +++ b/src/sage/geometry/hyperbolic_space/hyperbolic_geodesic.py @@ -794,7 +794,7 @@ def reflection_involution(self): sage: g = HM.get_geodesic((0,0,1), (1,0, n(sqrt(2)))) sage: A = g.reflection_involution() sage: B = diagonal_matrix([1, -1, 1]) - sage: bool((B - A.matrix()).norm() < 10**-9) + sage: bool((B - A.matrix()).norm() < 10**-9) # needs scipy True The above tests go through the Upper Half Plane. It remains to @@ -1602,7 +1602,7 @@ def perpendicular_bisector(self): # UHP ....: return bool(x.dist(m) < 1e-9) sage: c, d, e = CC(1, 1), CC(2, 1), CC(2, 0.5) sage: pairs = [(c, d), (d, c), (c, e), (e, c), (d, e), (e, d)] - sage: all(bisector_gets_midpoint(a, b) for a, b in pairs) + sage: all(bisector_gets_midpoint(a, b) for a, b in pairs) # needs scipy True """ if self.length() == infinity: @@ -2379,7 +2379,7 @@ def _plot_vertices(self, points=75): sage: p1 = HM.get_point((4, -4, sqrt(33))) sage: p2 = HM.get_point((-3,-3,sqrt(19))) sage: g = HM.get_geodesic(p1, p2) - sage: g._plot_vertices(5) + sage: g._plot_vertices(5) # needs sage.plot [(4.0, -4.0, 5.744562...), (1.363213..., -1.637073..., 2.353372...), (0.138568..., -0.969980..., 1.400022...), diff --git a/src/sage/geometry/hyperbolic_space/hyperbolic_isometry.py b/src/sage/geometry/hyperbolic_space/hyperbolic_isometry.py index 89e73b83a07..45b37b7f91d 100644 --- a/src/sage/geometry/hyperbolic_space/hyperbolic_isometry.py +++ b/src/sage/geometry/hyperbolic_space/hyperbolic_isometry.py @@ -1,3 +1,4 @@ +# sage.doctest: needs scipy r""" Hyperbolic Isometries diff --git a/src/sage/geometry/hyperbolic_space/hyperbolic_model.py b/src/sage/geometry/hyperbolic_space/hyperbolic_model.py index 33e5f0008fe..8533329d7c5 100644 --- a/src/sage/geometry/hyperbolic_space/hyperbolic_model.py +++ b/src/sage/geometry/hyperbolic_space/hyperbolic_model.py @@ -488,13 +488,13 @@ def get_isometry(self, A): [1 0] [0 1] - sage: HyperbolicPlane().KM().get_isometry(identity_matrix(3)) + sage: HyperbolicPlane().KM().get_isometry(identity_matrix(3)) # needs scipy Isometry in KM [1 0 0] [0 1 0] [0 0 1] - sage: HyperbolicPlane().HM().get_isometry(identity_matrix(3)) + sage: HyperbolicPlane().HM().get_isometry(identity_matrix(3)) # needs scipy Isometry in HM [1 0 0] [0 1 0] @@ -586,6 +586,7 @@ def random_isometry(self, preserve_orientation=True, **kwargs): EXAMPLES:: + sage: # needs scipy sage: A = HyperbolicPlane().PD().random_isometry() sage: A.preserves_orientation() True @@ -934,7 +935,7 @@ def get_background_graphic(self, **bdry_options): EXAMPLES:: - sage: hp = HyperbolicPlane().UHP().get_background_graphic() + sage: hp = HyperbolicPlane().UHP().get_background_graphic() # needs sage.plot """ from sage.plot.line import line bd_min = bdry_options.get('bd_min', -5) @@ -1104,9 +1105,9 @@ def random_isometry(self, preserve_orientation=True, **kwargs): EXAMPLES:: - sage: A = HyperbolicPlane().UHP().random_isometry() - sage: B = HyperbolicPlane().UHP().random_isometry(preserve_orientation=False) - sage: B.preserves_orientation() + sage: A = HyperbolicPlane().UHP().random_isometry() # needs scipy + sage: B = HyperbolicPlane().UHP().random_isometry(preserve_orientation=False) # needs scipy + sage: B.preserves_orientation() # needs scipy False """ [a, b, c, d] = [RR.random_element() for k in range(4)] @@ -1272,7 +1273,7 @@ def get_background_graphic(self, **bdry_options): EXAMPLES:: - sage: circ = HyperbolicPlane().PD().get_background_graphic() + sage: circ = HyperbolicPlane().PD().get_background_graphic() # needs sage.plot """ from sage.plot.circle import circle return circle((0, 0), 1, axes=False, color='black') @@ -1380,7 +1381,7 @@ def isometry_in_model(self, A): EXAMPLES:: sage: A = matrix(3, [[1, 0, 0], [0, 17/8, 15/8], [0, 15/8, 17/8]]) - sage: HyperbolicPlane().KM().isometry_in_model(A) + sage: HyperbolicPlane().KM().isometry_in_model(A) # needs scipy True """ if isinstance(A, HyperbolicIsometry): @@ -1396,7 +1397,7 @@ def get_background_graphic(self, **bdry_options): EXAMPLES:: - sage: circ = HyperbolicPlane().KM().get_background_graphic() + sage: circ = HyperbolicPlane().KM().get_background_graphic() # needs sage.plot """ from sage.plot.circle import circle return circle((0, 0), 1, axes=False, color='black') @@ -1490,7 +1491,7 @@ def isometry_in_model(self, A): EXAMPLES:: sage: A = diagonal_matrix([1,1,-1]) - sage: HyperbolicPlane().HM().isometry_in_model(A) + sage: HyperbolicPlane().HM().isometry_in_model(A) # needs scipy True """ if isinstance(A, HyperbolicIsometry): @@ -1505,7 +1506,7 @@ def get_background_graphic(self, **bdry_options): EXAMPLES:: - sage: H = HyperbolicPlane().HM().get_background_graphic() + sage: H = HyperbolicPlane().HM().get_background_graphic() # needs sage.plot """ from sage.plot.plot3d.all import plot3d from sage.symbolic.ring import SR diff --git a/src/sage/geometry/hyperbolic_space/hyperbolic_point.py b/src/sage/geometry/hyperbolic_space/hyperbolic_point.py index 62127ffe425..67608311693 100644 --- a/src/sage/geometry/hyperbolic_space/hyperbolic_point.py +++ b/src/sage/geometry/hyperbolic_space/hyperbolic_point.py @@ -318,7 +318,7 @@ def __rmul__(self, other): We also lift matrices into isometries:: sage: B = diagonal_matrix([-1, -1, 1]) - sage: B = HyperbolicPlane().HM().get_isometry(B) + sage: B = HyperbolicPlane().HM().get_isometry(B) # needs scipy sage: B * HyperbolicPlane().HM().get_point((0, 1, sqrt(2))) Point in HM (0, -1, sqrt(2)) """ @@ -491,7 +491,7 @@ def symmetry_involution(self): sage: A.preserves_orientation() True - sage: A*A == HyperbolicPlane().UHP().get_isometry(identity_matrix(2)) + sage: A*A == HyperbolicPlane().UHP().get_isometry(identity_matrix(2)) # needs scipy True """ R = self.parent().realization_of().a_realization() @@ -508,11 +508,11 @@ def show(self, boundary=True, **options): EXAMPLES:: - sage: HyperbolicPlane().PD().get_point(0).show() + sage: HyperbolicPlane().PD().get_point(0).show() # needs sage.plot Graphics object consisting of 2 graphics primitives - sage: HyperbolicPlane().KM().get_point((0,0)).show() + sage: HyperbolicPlane().KM().get_point((0,0)).show() # needs sage.plot Graphics object consisting of 2 graphics primitives - sage: HyperbolicPlane().HM().get_point((0,0,1)).show() + sage: HyperbolicPlane().HM().get_point((0,0,1)).show() # needs sage.plot Graphics3d Object """ p = self.coordinates() @@ -587,7 +587,7 @@ def show(self, boundary=True, **options): sage: HyperbolicPlane().UHP().get_point(I).show() Graphics object consisting of 2 graphics primitives - sage: HyperbolicPlane().UHP().get_point(0).show() + sage: HyperbolicPlane().UHP().get_point(0).show() # needs sage.plot Graphics object consisting of 2 graphics primitives sage: HyperbolicPlane().UHP().get_point(infinity).show() Traceback (most recent call last): From 1cce2b8a365c04e7651897bc21cb41916cbd50d5 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 17 Jun 2024 18:08:47 -0700 Subject: [PATCH 041/231] src/sage/modules/free_module_integer.py: Compare norm squares instead of norms --- src/sage/modules/free_module_integer.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/sage/modules/free_module_integer.py b/src/sage/modules/free_module_integer.py index 5bc9f1a3836..0fe86437b7c 100644 --- a/src/sage/modules/free_module_integer.py +++ b/src/sage/modules/free_module_integer.py @@ -384,7 +384,10 @@ def LLL(self, *args, **kwds): basis = matrix(ZZ, len(basis), len(basis[0]), basis) basis.set_immutable() - if self.reduced_basis[0].norm() > basis[0].norm(): + b0 = basis[0] + rb0 = self.reduced_basis[0] + + if rb0.dot_product(rb0) > b0.dot_product(b0): self._reduced_basis = basis return basis From 47c19bb2099678874e6a7a2f8a7d2599ce676c73 Mon Sep 17 00:00:00 2001 From: Shriya M <25shriya@gmail.com> Date: Fri, 31 May 2024 12:38:22 +0100 Subject: [PATCH 042/231] Added example in documentation of set_legends_options --- src/sage/plot/graphics.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/sage/plot/graphics.py b/src/sage/plot/graphics.py index a5e46d07c2d..797fd498f25 100644 --- a/src/sage/plot/graphics.py +++ b/src/sage/plot/graphics.py @@ -310,7 +310,7 @@ def legend(self, show=None): False sage: P.legend(True) sage: P # show with the legend - Graphics object consisting of 1 graphics primitive + Graphics object consisting of 1 graphics primitive """ if show is None: return self._show_legend @@ -430,6 +430,19 @@ def set_legend_options(self, **kwds): sage: p.set_legend_options(loc=(0.5,0.5)); p # aligns the bottom of the box to the center # needs sage.symbolic Graphics object consisting of 1 graphics primitive + + The dictionary ``_extra_kwds`` stores the keywords for graphics. This can be used to adjust vertical or + horizonal displacements from the x-axis or y-axis respectively:: + + sage: p = line([(0, 0), (1, 1)], legend_label='test', axes_labels=('X LABEL', 'Y LABEL')) + sage: labels = p._extra_kwds.get('axes_labels') + sage: if labels and labels[0]: + ....: displace = -.14 - .005 * p.fontsize() + ....: else: + ....: displace = -.14 + ....: p.set_legend_options(bbox_to_anchor=(0., displace, 1., .102), loc=3, mode="expand", borderaxespad=0.) + sage: print(p) + Graphics object consisting of 1 graphics primitive """ if len(kwds) == 0: return self._legend_opts From cdc16e878f6ab0e4239a9a1d58c2dd1ca0e42e51 Mon Sep 17 00:00:00 2001 From: Shriya M <25shriya@gmail.com> Date: Tue, 4 Jun 2024 13:37:36 +0100 Subject: [PATCH 043/231] Edited last example of set_legend_options --- src/sage/plot/graphics.py | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/sage/plot/graphics.py b/src/sage/plot/graphics.py index 797fd498f25..4e8b4cf1140 100644 --- a/src/sage/plot/graphics.py +++ b/src/sage/plot/graphics.py @@ -431,16 +431,12 @@ def set_legend_options(self, **kwds): sage: p.set_legend_options(loc=(0.5,0.5)); p # aligns the bottom of the box to the center # needs sage.symbolic Graphics object consisting of 1 graphics primitive - The dictionary ``_extra_kwds`` stores the keywords for graphics. This can be used to adjust vertical or - horizonal displacements from the x-axis or y-axis respectively:: + The parameters ``loc`` and ``borderaxespad`` can be altered in order to place the legend below the x-axis label or to the left of the y-axis label. + The following example sets ``loc=3`` and ``borderaxespad = ``-7.5-0.01*p.fontsize()`` so as to obtain the legend below the x-axis label. sage: p = line([(0, 0), (1, 1)], legend_label='test', axes_labels=('X LABEL', 'Y LABEL')) - sage: labels = p._extra_kwds.get('axes_labels') - sage: if labels and labels[0]: - ....: displace = -.14 - .005 * p.fontsize() - ....: else: - ....: displace = -.14 - ....: p.set_legend_options(bbox_to_anchor=(0., displace, 1., .102), loc=3, mode="expand", borderaxespad=0.) + sage: p.axes_labels(['X-Label', 'Y-Label']) + sage: p.set_legend_options(loc=8, borderaxespad=-7.5-0.01*p.fontsize()) sage: print(p) Graphics object consisting of 1 graphics primitive """ From 5e7ece9479713d30e52afcdad6a53da6796e6dcc Mon Sep 17 00:00:00 2001 From: Shriya M <25shriya@gmail.com> Date: Tue, 4 Jun 2024 15:28:06 +0100 Subject: [PATCH 044/231] Added comments --- src/sage/plot/graphics.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/plot/graphics.py b/src/sage/plot/graphics.py index 4e8b4cf1140..0f6d0b686b8 100644 --- a/src/sage/plot/graphics.py +++ b/src/sage/plot/graphics.py @@ -435,7 +435,7 @@ def set_legend_options(self, **kwds): The following example sets ``loc=3`` and ``borderaxespad = ``-7.5-0.01*p.fontsize()`` so as to obtain the legend below the x-axis label. sage: p = line([(0, 0), (1, 1)], legend_label='test', axes_labels=('X LABEL', 'Y LABEL')) - sage: p.axes_labels(['X-Label', 'Y-Label']) + sage: p.axes_labels(['X-Label', 'Y-Label']) # adding labels for axes sage: p.set_legend_options(loc=8, borderaxespad=-7.5-0.01*p.fontsize()) sage: print(p) Graphics object consisting of 1 graphics primitive From 671d26828431c3af889e04fea1b343ce3538839d Mon Sep 17 00:00:00 2001 From: Shriya M <25shriya@gmail.com> Date: Tue, 4 Jun 2024 15:41:12 +0100 Subject: [PATCH 045/231] Corrected line() method --- src/sage/plot/graphics.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/plot/graphics.py b/src/sage/plot/graphics.py index 0f6d0b686b8..382b8046d1c 100644 --- a/src/sage/plot/graphics.py +++ b/src/sage/plot/graphics.py @@ -434,7 +434,7 @@ def set_legend_options(self, **kwds): The parameters ``loc`` and ``borderaxespad`` can be altered in order to place the legend below the x-axis label or to the left of the y-axis label. The following example sets ``loc=3`` and ``borderaxespad = ``-7.5-0.01*p.fontsize()`` so as to obtain the legend below the x-axis label. - sage: p = line([(0, 0), (1, 1)], legend_label='test', axes_labels=('X LABEL', 'Y LABEL')) + sage: p = line([(0, 0), (1, 1)], legend_label='test') sage: p.axes_labels(['X-Label', 'Y-Label']) # adding labels for axes sage: p.set_legend_options(loc=8, borderaxespad=-7.5-0.01*p.fontsize()) sage: print(p) From c46b63023bb7a9ef1ad991e2c39cde1a29f6fee7 Mon Sep 17 00:00:00 2001 From: Shriya M <25shriya@gmail.com> Date: Tue, 4 Jun 2024 15:51:55 +0100 Subject: [PATCH 046/231] Solved first set of linting errors --- src/sage/plot/graphics.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sage/plot/graphics.py b/src/sage/plot/graphics.py index 382b8046d1c..a6648405d8e 100644 --- a/src/sage/plot/graphics.py +++ b/src/sage/plot/graphics.py @@ -309,7 +309,7 @@ def legend(self, show=None): sage: P.legend() False sage: P.legend(True) - sage: P # show with the legend + sage: P # show with the legend Graphics object consisting of 1 graphics primitive """ if show is None: @@ -428,11 +428,11 @@ def set_legend_options(self, **kwds): :: - sage: p.set_legend_options(loc=(0.5,0.5)); p # aligns the bottom of the box to the center # needs sage.symbolic + sage: p.set_legend_options(loc=(0.5,0.5)); p # aligns the bottom of the box to the center # needs sage.symbolic Graphics object consisting of 1 graphics primitive The parameters ``loc`` and ``borderaxespad`` can be altered in order to place the legend below the x-axis label or to the left of the y-axis label. - The following example sets ``loc=3`` and ``borderaxespad = ``-7.5-0.01*p.fontsize()`` so as to obtain the legend below the x-axis label. + The following example sets ``loc=3`` and ``borderaxespad = -7.5-0.01*p.fontsize()`` so as to obtain the legend below the x-axis label. sage: p = line([(0, 0), (1, 1)], legend_label='test') sage: p.axes_labels(['X-Label', 'Y-Label']) # adding labels for axes From 9f3627e71c0820dafad9026729591370b93415ca Mon Sep 17 00:00:00 2001 From: Shriya M <25shriya@gmail.com> Date: Wed, 5 Jun 2024 12:44:28 +0100 Subject: [PATCH 047/231] Solved second set of linting errors --- src/sage/plot/graphics.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sage/plot/graphics.py b/src/sage/plot/graphics.py index a6648405d8e..c6fc065edcd 100644 --- a/src/sage/plot/graphics.py +++ b/src/sage/plot/graphics.py @@ -310,7 +310,7 @@ def legend(self, show=None): False sage: P.legend(True) sage: P # show with the legend - Graphics object consisting of 1 graphics primitive + Graphics object consisting of 1 graphics primitive """ if show is None: return self._show_legend @@ -430,10 +430,10 @@ def set_legend_options(self, **kwds): sage: p.set_legend_options(loc=(0.5,0.5)); p # aligns the bottom of the box to the center # needs sage.symbolic Graphics object consisting of 1 graphics primitive - + The parameters ``loc`` and ``borderaxespad`` can be altered in order to place the legend below the x-axis label or to the left of the y-axis label. The following example sets ``loc=3`` and ``borderaxespad = -7.5-0.01*p.fontsize()`` so as to obtain the legend below the x-axis label. - + sage: p = line([(0, 0), (1, 1)], legend_label='test') sage: p.axes_labels(['X-Label', 'Y-Label']) # adding labels for axes sage: p.set_legend_options(loc=8, borderaxespad=-7.5-0.01*p.fontsize()) From 116181336d8ee8990a7dfb4f121879403431d54c Mon Sep 17 00:00:00 2001 From: Shriya M <25shriya@gmail.com> Date: Wed, 5 Jun 2024 12:56:20 +0100 Subject: [PATCH 048/231] Solved third set of linting errors --- src/sage/plot/graphics.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/plot/graphics.py b/src/sage/plot/graphics.py index c6fc065edcd..e9e7e74abda 100644 --- a/src/sage/plot/graphics.py +++ b/src/sage/plot/graphics.py @@ -310,7 +310,7 @@ def legend(self, show=None): False sage: P.legend(True) sage: P # show with the legend - Graphics object consisting of 1 graphics primitive + Graphics object consisting of 1 graphics primitive """ if show is None: return self._show_legend From 7a758d01d90805eb6e0d9adb31766df9bdba9355 Mon Sep 17 00:00:00 2001 From: Shriya M <25shriya@gmail.com> Date: Wed, 5 Jun 2024 14:38:37 +0100 Subject: [PATCH 049/231] Edited Documentation --- src/sage/plot/graphics.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/plot/graphics.py b/src/sage/plot/graphics.py index e9e7e74abda..b247dd47fb3 100644 --- a/src/sage/plot/graphics.py +++ b/src/sage/plot/graphics.py @@ -432,7 +432,7 @@ def set_legend_options(self, **kwds): Graphics object consisting of 1 graphics primitive The parameters ``loc`` and ``borderaxespad`` can be altered in order to place the legend below the x-axis label or to the left of the y-axis label. - The following example sets ``loc=3`` and ``borderaxespad = -7.5-0.01*p.fontsize()`` so as to obtain the legend below the x-axis label. + The following example sets ``loc=3`` and ``borderaxespad = -7.5-0.01*p.fontsize()`` so as to obtain the legend below the x-axis label:: sage: p = line([(0, 0), (1, 1)], legend_label='test') sage: p.axes_labels(['X-Label', 'Y-Label']) # adding labels for axes From c8e850a8f80f1f46fef5772a014c16a1feaee067 Mon Sep 17 00:00:00 2001 From: Shriya M <25shriya@gmail.com> Date: Thu, 6 Jun 2024 09:52:29 +0100 Subject: [PATCH 050/231] Edited Documentation --- src/sage/plot/graphics.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/plot/graphics.py b/src/sage/plot/graphics.py index b247dd47fb3..e9e7e74abda 100644 --- a/src/sage/plot/graphics.py +++ b/src/sage/plot/graphics.py @@ -432,7 +432,7 @@ def set_legend_options(self, **kwds): Graphics object consisting of 1 graphics primitive The parameters ``loc`` and ``borderaxespad`` can be altered in order to place the legend below the x-axis label or to the left of the y-axis label. - The following example sets ``loc=3`` and ``borderaxespad = -7.5-0.01*p.fontsize()`` so as to obtain the legend below the x-axis label:: + The following example sets ``loc=3`` and ``borderaxespad = -7.5-0.01*p.fontsize()`` so as to obtain the legend below the x-axis label. sage: p = line([(0, 0), (1, 1)], legend_label='test') sage: p.axes_labels(['X-Label', 'Y-Label']) # adding labels for axes From 6f4e333c9e23a0bcdf34033bdd8ffb782e1ae73f Mon Sep 17 00:00:00 2001 From: Shriya M <25shriya@gmail.com> Date: Thu, 6 Jun 2024 11:16:50 +0100 Subject: [PATCH 051/231] Edited Documentation --- src/sage/plot/graphics.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/plot/graphics.py b/src/sage/plot/graphics.py index e9e7e74abda..b247dd47fb3 100644 --- a/src/sage/plot/graphics.py +++ b/src/sage/plot/graphics.py @@ -432,7 +432,7 @@ def set_legend_options(self, **kwds): Graphics object consisting of 1 graphics primitive The parameters ``loc`` and ``borderaxespad`` can be altered in order to place the legend below the x-axis label or to the left of the y-axis label. - The following example sets ``loc=3`` and ``borderaxespad = -7.5-0.01*p.fontsize()`` so as to obtain the legend below the x-axis label. + The following example sets ``loc=3`` and ``borderaxespad = -7.5-0.01*p.fontsize()`` so as to obtain the legend below the x-axis label:: sage: p = line([(0, 0), (1, 1)], legend_label='test') sage: p.axes_labels(['X-Label', 'Y-Label']) # adding labels for axes From 9c49a296950c4c54f6b5cbf5f5b97feca9c9d536 Mon Sep 17 00:00:00 2001 From: Shriya M <25shriya@gmail.com> Date: Mon, 10 Jun 2024 20:02:33 +0100 Subject: [PATCH 052/231] Formatted Documentation --- src/sage/plot/graphics.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/sage/plot/graphics.py b/src/sage/plot/graphics.py index b247dd47fb3..0d96d3d6150 100644 --- a/src/sage/plot/graphics.py +++ b/src/sage/plot/graphics.py @@ -431,13 +431,14 @@ def set_legend_options(self, **kwds): sage: p.set_legend_options(loc=(0.5,0.5)); p # aligns the bottom of the box to the center # needs sage.symbolic Graphics object consisting of 1 graphics primitive - The parameters ``loc`` and ``borderaxespad`` can be altered in order to place the legend below the x-axis label or to the left of the y-axis label. - The following example sets ``loc=3`` and ``borderaxespad = -7.5-0.01*p.fontsize()`` so as to obtain the legend below the x-axis label:: + The parameters ``loc`` and ``borderaxespad`` can be altered + in order to place the legend below the x-axis label or to + the left of the y-axis label:: sage: p = line([(0, 0), (1, 1)], legend_label='test') - sage: p.axes_labels(['X-Label', 'Y-Label']) # adding labels for axes + sage: p.axes_labels(['X-Label', 'Y-Label']) # adding labels for axes sage: p.set_legend_options(loc=8, borderaxespad=-7.5-0.01*p.fontsize()) - sage: print(p) + sage: p Graphics object consisting of 1 graphics primitive """ if len(kwds) == 0: From 94ed5e30cf7ffa1c18a5e98eaa06f2e02793e1f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Tue, 18 Jun 2024 08:55:17 +0200 Subject: [PATCH 053/231] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Matthias Köppe --- src/sage/combinat/binary_recurrence_sequences.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/combinat/binary_recurrence_sequences.py b/src/sage/combinat/binary_recurrence_sequences.py index f473ce162f2..76765b38aab 100644 --- a/src/sage/combinat/binary_recurrence_sequences.py +++ b/src/sage/combinat/binary_recurrence_sequences.py @@ -289,7 +289,7 @@ def is_quasigeometric(self) -> bool: i.e. the union of multiple geometric sequences, or geometric after term ``u0``. If `\\alpha/\\beta` is a `k` th root of unity, where `k>1`, then necessarily `k = 2, 3, 4, 6`. - Then `F = [[0,1],[c,b]` is diagonalizable, and `F^k = [[\\alpha^k, 0], [0,\\beta^k]]` is a scalar + Then `F = [[0,1],[c,b]` is diagonalizable, and `F^k = [[\\alpha^k, 0], [0,\\beta^k]]` is a diagonal matrix. Thus for all values of `j` mod `k`, the `j` mod `k` terms of `u_n` form a geometric series. @@ -900,7 +900,7 @@ def _next_good_prime(p, R, qq, patience, qqold): # requiring that b^2 + 4c is a square in GF(R._ell) ensures that the period mod R._ell # divides R._ell - 1 - if legendre_symbol(R.b**2 + 4 * R.c, R._ell) == 1: + if legendre_symbol(R.b**2 + 4*R.c, R._ell) == 1: N = _goodness(R._ell, R, p) From 7212185601162ee2ee485c75dac860f38487591d Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 8 Jun 2024 18:54:31 -0700 Subject: [PATCH 054/231] sage.features.topcom: New --- src/sage/features/topcom.py | 67 +++++++++++++++++++ .../triangulation/point_configuration.py | 11 ++- 2 files changed, 72 insertions(+), 6 deletions(-) create mode 100644 src/sage/features/topcom.py diff --git a/src/sage/features/topcom.py b/src/sage/features/topcom.py new file mode 100644 index 00000000000..5256519ce3d --- /dev/null +++ b/src/sage/features/topcom.py @@ -0,0 +1,67 @@ +# sage_setup: distribution = sagemath-environment +r""" +Features for testing the presence of topcom executables +""" + +# ***************************************************************************** +# Copyright (C) 2022-2024 Matthias Koeppe +# +# Distributed under the terms of the GNU General Public License (GPL) +# as published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# https://www.gnu.org/licenses/ +# ***************************************************************************** + +from . import Executable +from .join_feature import JoinFeature + + +class TOPCOMExecutable(Executable): + r""" + A :class:`~sage.features.Feature` which checks for executables from the :ref:`TOPCOM ` package. + + EXAMPLES:: + + sage: from sage.features.topcom import TOPCOMExecutable + sage: TOPCOMExecutable('points2allfinetriangs').is_present() # optional - topcom + FeatureTestResult('topcom_points2allfinetriangs', True) + """ + def __init__(self, name): + r""" + TESTS:: + + sage: from sage.features.topcom import TOPCOMExecutable + sage: isinstance(TOPCOMExecutable('points2finetriangs'), TOPCOMExecutable) + True + """ + Executable.__init__(self, name=f"topcom_{name}", + executable=name, + spkg="topcom") + + +class TOPCOM(JoinFeature): + r""" + A :class:`~sage.features.Feature` describing the presence of the executables + which comes as a part of :ref:`TOPCOM `. + + EXAMPLES:: + + sage: from sage.features.topcom import TOPCOM + sage: TOPCOM().is_present() # optional - topcom + FeatureTestResult('topcom', True) + """ + def __init__(self): + r""" + TESTS:: + + sage: from sage.features.topcom import TOPCOM + sage: isinstance(TOPCOM(), TOPCOM) + True + """ + JoinFeature.__init__(self, "topcom", + [TOPCOMExecutable(name) + for name in ('points2allfinetriangs',)]) + + +def all_features(): + return [TOPCOM()] diff --git a/src/sage/geometry/triangulation/point_configuration.py b/src/sage/geometry/triangulation/point_configuration.py index b71ae4cb348..3e24f3ee8cb 100644 --- a/src/sage/geometry/triangulation/point_configuration.py +++ b/src/sage/geometry/triangulation/point_configuration.py @@ -18,11 +18,7 @@ Finding a single triangulation and listing all connected triangulations is implemented natively in this package. However, for -more advanced options [TOPCOM]_ needs to be installed. It is available -as an optional package for Sage, and you can install it with the -shell command :: - - sage -i topcom +more advanced options [TOPCOM]_ needs to be installed; see :ref:`spkg_topcom`. .. note:: @@ -184,6 +180,7 @@ import itertools +from sage.features.topcom import TOPCOMExecutable from sage.structure.unique_representation import UniqueRepresentation from sage.misc.cachefunc import cached_method from sage.misc.lazy_import import lazy_import @@ -613,7 +610,9 @@ def _TOPCOM_exec(cls, executable, input_string, verbose=True): ['{{0,1,2,4},{1,2,3,4}}'] """ timeout = 600 - proc = pexpect.spawn(executable, timeout=timeout) + executable_name, *args = executable.split() + executable_absname = TOPCOMExecutable(executable_name).absolute_filename() + proc = pexpect.spawn(executable_absname, args, timeout=timeout) proc.expect(r'Evaluating Commandline Options \.\.\.') proc.expect(r'\.\.\. done\.') proc.setecho(0) From cd2eb15393ff6e5d8dd1f7a20d6e3ae820a958c6 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 8 Jun 2024 18:55:00 -0700 Subject: [PATCH 055/231] PointConfiguration._have_TOPCOM: Handle FeatureNotPresentError --- src/sage/geometry/triangulation/point_configuration.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/sage/geometry/triangulation/point_configuration.py b/src/sage/geometry/triangulation/point_configuration.py index 3e24f3ee8cb..d515f43ec8a 100644 --- a/src/sage/geometry/triangulation/point_configuration.py +++ b/src/sage/geometry/triangulation/point_configuration.py @@ -180,6 +180,7 @@ import itertools +from sage.features import FeatureNotPresentError from sage.features.topcom import TOPCOMExecutable from sage.structure.unique_representation import UniqueRepresentation from sage.misc.cachefunc import cached_method @@ -288,7 +289,7 @@ def _have_TOPCOM(cls): PointConfiguration._have_TOPCOM_cached = True assert out == '{{0,1}}',\ 'TOPCOM ran but did not produce the correct output!' - except pexpect.ExceptionPexpect: + except (FeatureNotPresentError, pexpect.ExceptionPexpect): PointConfiguration._have_TOPCOM_cached = False PointConfiguration.set_engine('auto') From aedbf6191bdc599904257cf4e3ba9de957ba1d38 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 26 Apr 2024 17:06:42 -0700 Subject: [PATCH 056/231] src/doc/bootstrap: Only generate parts of src/doc/en/reference/spkg/index.rst --- src/doc/bootstrap | 126 +++++++--------------------------------------- 1 file changed, 18 insertions(+), 108 deletions(-) diff --git a/src/doc/bootstrap b/src/doc/bootstrap index 32a31430554..e99ecd52c28 100755 --- a/src/doc/bootstrap +++ b/src/doc/bootstrap @@ -84,28 +84,15 @@ mkdir -p "$OUTPUT_DIR" if [ "${BOOTSTRAP_QUIET}" = "no" ]; then echo >&2 $0:$LINENO: installing "$OUTPUT_DIR"/"*.rst" fi -OUTPUT_INDEX="$OUTPUT_DIR"/index.rst -cat > "$OUTPUT_INDEX" <> "$OUTPUT_INDEX" -cat >> "$OUTPUT_INDEX" <> "$OUTPUT_INDEX" -cat >> "$OUTPUT_INDEX" <> "$OUTPUT_INDEX" -cat >> "$OUTPUT_INDEX" < "$OUTPUT_DIR"/index_standard.rst +(cat <> "$OUTPUT_INDEX" -cat >> "$OUTPUT_INDEX" <> "$OUTPUT_INDEX" -cat >> "$OUTPUT_INDEX" <> "$OUTPUT_INDEX" -cat >> "$OUTPUT_INDEX" <> "$OUTPUT_INDEX" < "$OUTPUT_DIR"/index_optional.rst for PKG_BASE in $(sage-package list --has-file SPKG.rst | grep '^sagemath_'); do echo "* :ref:\`spkg_$PKG_BASE\`" -done >> "$OUTPUT_INDEX" -cat >> "$OUTPUT_INDEX" < "$OUTPUT_DIR"/index_sagemath.rst +(cat <> "$OUTPUT_INDEX" +done -cat >> "$OUTPUT_INDEX" <> "$OUTPUT_INDEX" - -cat >> "$OUTPUT_INDEX" < "$OUTPUT_DIR"/index_experimental.rst (cat < "$OUTPUT_INDEX" +) > "$OUTPUT_DIR"/index_alph.rst sage-package list --has-file SPKG.rst | OUTPUT_DIR=$OUTPUT_DIR OUTPUT_RST=1 xargs -P 99 -n 1 sage-spkg-info From 21cc69ac9f0d480c29a358984626c15d2d462b34 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 26 Apr 2024 17:12:49 -0700 Subject: [PATCH 057/231] src/doc/en/reference/spkg/index.rst: No longer auto-generated, use '.. include' --- .gitignore | 1 + Makefile | 2 +- src/doc/en/reference/spkg/index.rst | 87 +++++++++++++++++++++++++++++ 3 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 src/doc/en/reference/spkg/index.rst diff --git a/.gitignore b/.gitignore index 1d7eacdf9e4..70a6739c33b 100644 --- a/.gitignore +++ b/.gitignore @@ -261,6 +261,7 @@ build/pkgs/wheel/version_requirements.txt /src/doc/en/reference/*/sage_docbuild /src/doc/en/reference/sage /src/doc/en/reference/spkg/*.rst +!/src/doc/en/reference/spkg/index.rst /src/doc/output /src/doc/en/installation/*.txt /src/doc/en/reference/repl/*.txt diff --git a/Makefile b/Makefile index 00989597a11..60358a0dfec 100644 --- a/Makefile +++ b/Makefile @@ -173,7 +173,7 @@ distclean: build-clean bootstrap-clean: rm -rf config/install-sh config/compile config/config.guess config/config.sub config/missing configure build/make/Makefile-auto.in rm -f src/doc/en/installation/*.txt - rm -rf src/doc/en/reference/spkg/*.rst + find src/doc/en/reference/spkg -name index.rst -prune -o -name *.rst -exec rm -f {} \+ for a in environment environment-optional src/environment src/environment-dev src/environment-optional; do rm -f $$a.yml $$a-3.[89].yml $$a-3.1[0-9].yml; done rm -f src/Pipfile rm -f src/requirements.txt diff --git a/src/doc/en/reference/spkg/index.rst b/src/doc/en/reference/spkg/index.rst new file mode 100644 index 00000000000..e9ba934a540 --- /dev/null +++ b/src/doc/en/reference/spkg/index.rst @@ -0,0 +1,87 @@ +.. _spkg: + +Packages and Features +===================== + +Standard Packages +----------------- + +The Sage distribution includes most programs and libraries on which +Sage depends. It installs them automatically if it does not find +equivalent system packages. + +.. include:: index_standard.rst + + +Optional Packages +----------------- + +For additional functionality, you can install some of the following +optional packages. + +.. include:: index_optional.rst + + +Features +-------- + +.. toctree:: + :maxdepth: 1 + + sage/features + sage/features/join_feature + sage/features/all + sage/features/sagemath + sage/features/pkg_systems + sage/features/bliss + sage/features/csdp + sage/features/databases + sage/features/dvipng + sage/features/ffmpeg + sage/features/four_ti_2 + sage/features/gap + sage/features/graph_generators + sage/features/graphviz + sage/features/imagemagick + sage/features/interfaces + sage/features/internet + sage/features/kenzo + sage/features/latex + sage/features/latte + sage/features/lrs + sage/features/mcqd + sage/features/meataxe + sage/features/mip_backends + sage/features/normaliz + sage/features/pandoc + sage/features/pdf2svg + sage/features/polymake + sage/features/rubiks + sage/features/tdlib + sage/features/topcom + + +Distribution Packages of the Sage Library +----------------------------------------- + +.. include:: index_sagemath.rst + + +Experimental Packages +--------------------- + +Some packages that provide additional functionality are marked as +"experimental". Developers are needed in order to improve the +integration of these packages into the Sage distribution. + +.. include:: index_experimental.rst + + +All External Packages +--------------------- + +.. toctree:: + :maxdepth: 1 + + index_alph + From b2298a602c1b58ca8ab9a156320935555c58cd7e Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 28 Apr 2024 12:28:41 -0700 Subject: [PATCH 058/231] bootstrap: Do not put src/doc/en/reference/spkg/index.rst in the configure tarball --- bootstrap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bootstrap b/bootstrap index eb5bcd732b6..3fb3b594548 100755 --- a/bootstrap +++ b/bootstrap @@ -234,7 +234,7 @@ save () { config/install-sh config/compile config/config.guess config/config.sub config/missing \ build/make/Makefile-auto.in \ src/doc/en/installation/*.txt \ - src/doc/en/reference/spkg/*.rst \ + $(find src/doc/en/reference/spkg -name index.rst -prune -o -name *.rst -print) \ environment-3.[89].yml environment-3.1[0-9].yml \ src/environment-3.[89].yml src/environment-3.1[0-9].yml \ environment-optional-3.[89].yml environment-optional-3.1[0-9].yml \ From 1c6e248a38c4344f1dd2152968198ee9dd2ae702 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 18 Jun 2024 09:19:20 -0700 Subject: [PATCH 059/231] bootstrap, Makefile (bootstrap-clean): Do not recurse into autodoc directories of src/doc/en/reference/spkg --- Makefile | 2 +- bootstrap | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 60358a0dfec..53d2c689843 100644 --- a/Makefile +++ b/Makefile @@ -173,7 +173,7 @@ distclean: build-clean bootstrap-clean: rm -rf config/install-sh config/compile config/config.guess config/config.sub config/missing configure build/make/Makefile-auto.in rm -f src/doc/en/installation/*.txt - find src/doc/en/reference/spkg -name index.rst -prune -o -name *.rst -exec rm -f {} \+ + find src/doc/en/reference/spkg -name index.rst -prune -o -maxdepth 1 -name "*.rst" -exec rm -f {} \+ for a in environment environment-optional src/environment src/environment-dev src/environment-optional; do rm -f $$a.yml $$a-3.[89].yml $$a-3.1[0-9].yml; done rm -f src/Pipfile rm -f src/requirements.txt diff --git a/bootstrap b/bootstrap index 3fb3b594548..434a3b87396 100755 --- a/bootstrap +++ b/bootstrap @@ -234,7 +234,7 @@ save () { config/install-sh config/compile config/config.guess config/config.sub config/missing \ build/make/Makefile-auto.in \ src/doc/en/installation/*.txt \ - $(find src/doc/en/reference/spkg -name index.rst -prune -o -name *.rst -print) \ + $(find src/doc/en/reference/spkg -name index.rst -prune -o -maxdepth 1 -name "*.rst" -print) \ environment-3.[89].yml environment-3.1[0-9].yml \ src/environment-3.[89].yml src/environment-3.1[0-9].yml \ environment-optional-3.[89].yml environment-optional-3.1[0-9].yml \ From ab610a3195d90c11bb101532290d2049c79ffc96 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 18 Jun 2024 16:01:30 -0700 Subject: [PATCH 060/231] src/sage/groups/all.py: Deprecate import of GroupExp_Class, GroupExpElement --- src/sage/groups/all.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/sage/groups/all.py b/src/sage/groups/all.py index 66f3a106e54..e84ec20b2bc 100644 --- a/src/sage/groups/all.py +++ b/src/sage/groups/all.py @@ -32,6 +32,7 @@ lazy_import('sage.groups.semimonomial_transformations.semimonomial_transformation_group', 'SemimonomialTransformationGroup') -lazy_import('sage.groups.group_exp', ['GroupExp', 'GroupExp_Class', 'GroupExpElement']) +lazy_import('sage.groups.group_exp', ['GroupExp']) +lazy_import('sage.groups.group_exp', ['GroupExp_Class', 'GroupExpElement'], deprecation=99999) lazy_import('sage.groups.group_semidirect_product', ['GroupSemidirectProduct', 'GroupSemidirectProductElement']) From 39442e7db9f713694ec7a0aa375159ebc8583b77 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 18 Jun 2024 16:04:02 -0700 Subject: [PATCH 061/231] src/sage/groups/all.py: Deprecate import of GroupExp_Class, GroupExpElement, GroupSemidirectProductElement --- src/sage/groups/all.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/sage/groups/all.py b/src/sage/groups/all.py index e84ec20b2bc..601ba6c7ec0 100644 --- a/src/sage/groups/all.py +++ b/src/sage/groups/all.py @@ -32,7 +32,10 @@ lazy_import('sage.groups.semimonomial_transformations.semimonomial_transformation_group', 'SemimonomialTransformationGroup') -lazy_import('sage.groups.group_exp', ['GroupExp']) -lazy_import('sage.groups.group_exp', ['GroupExp_Class', 'GroupExpElement'], deprecation=99999) +lazy_import('sage.groups.group_exp', 'GroupExp') +lazy_import('sage.groups.group_exp', ['GroupExp_Class', 'GroupExpElement'], + deprecation=38238) -lazy_import('sage.groups.group_semidirect_product', ['GroupSemidirectProduct', 'GroupSemidirectProductElement']) +lazy_import('sage.groups.group_semidirect_product', 'GroupSemidirectProduct') +lazy_import('sage.groups.group_semidirect_product', 'GroupSemidirectProductElement', + deprecation=38238) From a19d2de0f48ea10ac2bac6e1069b6d510556e930 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 18 Jun 2024 17:09:18 -0700 Subject: [PATCH 062/231] src/sage/groups/group_exp.py: In doctest, import GroupExpElement explicitly; doctest cosmetics --- src/sage/groups/group_exp.py | 44 +++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/src/sage/groups/group_exp.py b/src/sage/groups/group_exp.py index 49f2315eae3..434608c5264 100644 --- a/src/sage/groups/group_exp.py +++ b/src/sage/groups/group_exp.py @@ -14,15 +14,16 @@ # (at your option) any later version. # http://www.gnu.org/licenses/ #***************************************************************************** + from sage.categories.commutative_additive_groups import CommutativeAdditiveGroups -from sage.categories.groups import Groups -from sage.structure.element import MultiplicativeGroupElement -from sage.structure.unique_representation import UniqueRepresentation -from sage.structure.parent import Parent -from sage.categories.morphism import SetMorphism from sage.categories.functor import Functor +from sage.categories.groups import Groups from sage.categories.homset import Hom +from sage.categories.morphism import SetMorphism +from sage.structure.element import MultiplicativeGroupElement from sage.structure.element_wrapper import ElementWrapper +from sage.structure.parent import Parent +from sage.structure.unique_representation import UniqueRepresentation class GroupExp(Functor): @@ -59,7 +60,7 @@ class GroupExp(Functor): -3 sage: x.parent() Multiplicative form of Integer Ring - sage: EZ(-1)*EZ(6) == EZ(5) + sage: EZ(-1) * EZ(6) == EZ(5) True sage: EZ(3)^(-1) -3 @@ -77,9 +78,10 @@ class GroupExp(Functor): ....: return s2.action(mu) sage: from sage.categories.morphism import SetMorphism sage: from sage.categories.homset import Hom - sage: f = SetMorphism(Hom(L,L,CommutativeAdditiveGroups()), my_action) + sage: f = SetMorphism(Hom(L, L, CommutativeAdditiveGroups()), my_action) sage: F = E(f); F - Generic endomorphism of Multiplicative form of Ambient space of the Root system of type ['A', 2] + Generic endomorphism of + Multiplicative form of Ambient space of the Root system of type ['A', 2] sage: v = L.an_element(); v (2, 2, 3) sage: y = F(EL(v)); y @@ -114,8 +116,8 @@ def _apply_functor(self, x): OUTPUT: an isomorphic group whose operation is multiplication rather than addition - In the following example, ``self`` is the functor `GroupExp()`, - `x` is the additive group `QQ^2`, and the output group is stored as `EQ2`. + In the following example, ``self`` is the functor ``GroupExp()``, + ``x`` is the additive group ``QQ^2``, and the output group is stored as ``EQ2``. EXAMPLES:: @@ -145,8 +147,6 @@ def _apply_functor_to_morphism(self, f): OUTPUT: the above homomorphism, but between the corresponding multiplicative groups - - The above homomorphism, but between the corresponding multiplicative groups. - In the following example, ``self`` is the functor :class:`GroupExp` and `f` is an endomorphism of the additive group of integers. @@ -156,7 +156,7 @@ def _apply_functor_to_morphism(self, f): ....: return x + x sage: from sage.categories.morphism import SetMorphism sage: from sage.categories.homset import Hom - sage: f = SetMorphism(Hom(ZZ,ZZ,CommutativeAdditiveGroups()),double) + sage: f = SetMorphism(Hom(ZZ, ZZ, CommutativeAdditiveGroups()), double) sage: E = GroupExp() sage: EZ = E._apply_functor(ZZ) sage: F = E._apply_functor_to_morphism(f) @@ -164,7 +164,7 @@ def _apply_functor_to_morphism(self, f): True sage: F.codomain() == EZ True - sage: F(EZ(3)) == EZ(3)*EZ(3) + sage: F(EZ(3)) == EZ(3) * EZ(3) True """ new_domain = self._apply_functor(f.domain()) @@ -172,6 +172,7 @@ def _apply_functor_to_morphism(self, f): new_f = lambda a: new_codomain(f(a.value)) return SetMorphism(Hom(new_domain, new_codomain, Groups()), new_f) + class GroupExpElement(ElementWrapper, MultiplicativeGroupElement): r""" An element in the exponential of a commutative additive group. @@ -184,13 +185,14 @@ class GroupExpElement(ElementWrapper, MultiplicativeGroupElement): EXAMPLES:: + sage: from sage.groups.group_exp import GroupExpElement sage: G = QQ^2 sage: EG = GroupExp()(G) - sage: z = GroupExpElement(EG, vector(QQ, (1,-3))); z + sage: z = GroupExpElement(EG, vector(QQ, (1, -3))); z (1, -3) sage: z.parent() Multiplicative form of Vector space of dimension 2 over Rational Field - sage: EG(vector(QQ,(1,-3)))==z + sage: EG(vector(QQ, (1, -3))) == z True """ @@ -202,7 +204,7 @@ def __init__(self, parent, x): sage: EG = GroupExp()(G) sage: x = EG.an_element(); x (1, 0) - sage: TestSuite(x).run(skip = "_test_category") + sage: TestSuite(x).run(skip="_test_category") See the documentation of :meth:`sage.structure.element_wrapper.ElementWrapper.__init__` for the reason behind skipping the category test. @@ -233,7 +235,7 @@ def __mul__(self, x): sage: x = G(2) sage: x.__mul__(G(3)) 5 - sage: G.product(G(2),G(3)) + sage: G.product(G(2), G(3)) 5 """ return GroupExpElement(self.parent(), self.value + x.value) @@ -245,7 +247,7 @@ class GroupExp_Class(UniqueRepresentation, Parent): INPUT: - - `G` -- a commutative additive group + - ``G`` -- a commutative additive group OUTPUT: the multiplicative form of `G` @@ -260,7 +262,7 @@ def __init__(self, G): EXAMPLES:: sage: EG = GroupExp()(QQ^2) - sage: TestSuite(EG).run(skip = "_test_elements") + sage: TestSuite(EG).run(skip="_test_elements") """ if G not in CommutativeAdditiveGroups(): raise TypeError("%s must be a commutative additive group" % G) @@ -286,7 +288,7 @@ def _element_constructor_(self, x): EXAMPLES:: sage: G = GroupExp()(ZZ) - sage: G(4) # indirect doctest + sage: G(4) # indirect doctest 4 """ return GroupExpElement(self, x) From bd4724e9d2b9a29cf991e8ffaad4e3edecaf21d3 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 18 Jun 2024 16:59:18 -0700 Subject: [PATCH 063/231] src/sage/features/sat.py: New --- src/sage/features/sat.py | 103 ++++++++++++++++++++++++++ src/sage/sat/solvers/cryptominisat.py | 6 +- src/sage/sat/solvers/picosat.py | 6 +- 3 files changed, 109 insertions(+), 6 deletions(-) create mode 100644 src/sage/features/sat.py diff --git a/src/sage/features/sat.py b/src/sage/features/sat.py new file mode 100644 index 00000000000..6a05491ddb7 --- /dev/null +++ b/src/sage/features/sat.py @@ -0,0 +1,103 @@ +# sage_setup: distribution = sagemath-environment +r""" +Feature for testing the presence of SAT solvers +""" + +from . import Executable, PythonModule + + +class Glucose(Executable): + r""" + A :class:`~sage.features.Feature` describing the presence of an + executable from the :ref:`Glucose SAT solver `. + + EXAMPLES:: + + sage: from sage.features.sat import Glucose + sage: GlucoseExecutable().is_present() # optional - glucose + FeatureTestResult('glucose', True) + """ + def __init__(self, executable="glucose"): + r""" + TESTS:: + + sage: from sage.features.sat import Glucose + sage: isinstance(Glucose(), Glucose) + True + """ + Executable.__init__(self, name=executable, executable=executable, + spkg="glucose", type="optional") + + +class Kissat(Executable): + r""" + A :class:`~sage.features.Feature` describing the presence of the + :ref:`Kissat SAT solver `. + + EXAMPLES:: + + sage: from sage.features.sat import Kissat + sage: Kissat().is_present() # optional - kissat + FeatureTestResult('kissat', True) + """ + def __init__(self): + r""" + TESTS:: + + sage: from sage.features.sat import Kissat + sage: isinstance(Kissat(), Kissat) + True + """ + Executable.__init__(self, name="kissat", executable="kissat", + spkg="kissat", type="optional") + + +class Pycosat(PythonModule): + r""" + A :class:`~sage.features.Feature` describing the presence of :ref:`spkg_pycosat`. + + EXAMPLES:: + + sage: from sage.features.sat import Pycosat + sage: PycosatExecutable().is_present() # optional - pycosat + FeatureTestResult('pycosat', True) + """ + def __init__(self): + r""" + TESTS:: + + sage: from sage.features.sat import Pycosat + sage: isinstance(Pycosat(), Pycosat) + True + """ + PythonModule.__init__(self, "pycosat", + spkg="pycosat", type="optional") + + +class Pycryptosat(PythonModule): + r""" + A :class:`~sage.features.Feature` describing the presence of :ref:`spkg_pycryptosat`. + + EXAMPLES:: + + sage: from sage.features.sat import Pycryptosat + sage: PycryptosatExecutable().is_present() # optional - pycryptosat + FeatureTestResult('pycryptosat', True) + """ + def __init__(self): + r""" + TESTS:: + + sage: from sage.features.sat import Pycryptosat + sage: isinstance(Pycryptosat(), Pycryptosat) + True + """ + PythonModule.__init__(self, "pycryptosat", + spkg="pycryptosat", type="optional") + + +def all_features(): + return [Glucose(), + Kissat(), + Pycosat(), + Pycryptosat()] diff --git a/src/sage/sat/solvers/cryptominisat.py b/src/sage/sat/solvers/cryptominisat.py index 27955c43eef..dfb1295195d 100644 --- a/src/sage/sat/solvers/cryptominisat.py +++ b/src/sage/sat/solvers/cryptominisat.py @@ -22,9 +22,9 @@ from .satsolver import SatSolver from sage.misc.lazy_import import lazy_import -from sage.features import PythonModule -lazy_import('pycryptosat', ['Solver'], - feature=PythonModule('pycryptosat', spkg='pycryptosat')) +from sage.features.sat import Pycryptosat + +lazy_import('pycryptosat', ['Solver'], feature=Pycryptosat()) class CryptoMiniSat(SatSolver): diff --git a/src/sage/sat/solvers/picosat.py b/src/sage/sat/solvers/picosat.py index a88f69da883..89e82170b7f 100644 --- a/src/sage/sat/solvers/picosat.py +++ b/src/sage/sat/solvers/picosat.py @@ -21,9 +21,9 @@ from .satsolver import SatSolver from sage.misc.lazy_import import lazy_import -from sage.features import PythonModule -lazy_import('pycosat', ['solve'], - feature=PythonModule('pycosat', spkg='pycosat')) +from sage.features.sat import Pycosat + +lazy_import('pycosat', ['solve'], feature=Pycosat()) class PicoSAT(SatSolver): From ea126923e6cfa0849c608decfe101277468cd6ea Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Fri, 5 Jan 2024 16:28:32 +0900 Subject: [PATCH 064/231] Adding contravariant form. Fixing Verma module embedding by a root. --- .../lie_algebras/poincare_birkhoff_witt.py | 201 ++++++++++++++++-- .../algebras/lie_algebras/verma_module.py | 194 ++++++++++++++--- src/sage/categories/coxeter_groups.py | 16 +- .../triangular_kac_moody_algebras.py | 136 +++++++++++- src/sage/monoids/indexed_free_monoid.py | 29 ++- 5 files changed, 512 insertions(+), 64 deletions(-) diff --git a/src/sage/algebras/lie_algebras/poincare_birkhoff_witt.py b/src/sage/algebras/lie_algebras/poincare_birkhoff_witt.py index 3b59303d0dc..56be8304681 100644 --- a/src/sage/algebras/lie_algebras/poincare_birkhoff_witt.py +++ b/src/sage/algebras/lie_algebras/poincare_birkhoff_witt.py @@ -18,9 +18,11 @@ #***************************************************************************** from sage.misc.cachefunc import cached_method +from sage.misc.lazy_attribute import lazy_attribute from sage.structure.element import get_coercion_model from operator import mul from sage.categories.algebras import Algebras +from sage.categories.triangular_kac_moody_algebras import TriangularKacMoodyAlgebras from sage.monoids.indexed_free_monoid import IndexedFreeAbelianMonoid from sage.combinat.free_module import CombinatorialFreeModule from sage.sets.family import Family @@ -61,12 +63,12 @@ class PoincareBirkhoffWittBasis(CombinatorialFreeModule): We then do some computations; in particular, we check that `[E, F] = H`:: - sage: E,F,H = PBW.algebra_generators() - sage: E*F + sage: E, F, H = PBW.algebra_generators() + sage: E * F PBW['E']*PBW['F'] - sage: F*E + sage: F * E PBW['E']*PBW['F'] - PBW['H'] - sage: E*F - F*E + sage: E * F - F * E PBW['H'] Next we construct another instance of the PBW basis, but sorted in the @@ -108,7 +110,7 @@ class PoincareBirkhoffWittBasis(CombinatorialFreeModule): """ @staticmethod def __classcall_private__(cls, g, basis_key=None, prefix='PBW', **kwds): - """ + r""" Normalize input to ensure a unique representation. TESTS:: @@ -120,25 +122,30 @@ def __classcall_private__(cls, g, basis_key=None, prefix='PBW', **kwds): sage: P1 is P2 True """ - return super().__classcall__(cls, - g, basis_key, prefix, **kwds) + if g in TriangularKacMoodyAlgebras.FiniteDimensional: + return PoincareBirkhoffWittBasisSemisimpleLieAlgebra(g, basis_key, prefix, **kwds) + return super().__classcall__(cls, g, basis_key, prefix, **kwds) def __init__(self, g, basis_key, prefix, **kwds): - """ + r""" Initialize ``self``. TESTS:: - sage: L = lie_algebras.sl(QQ, 2) - sage: PBW = L.pbw_basis() - sage: E,F,H = PBW.algebra_generators() - sage: TestSuite(PBW).run(elements=[E, F, H]) - sage: TestSuite(PBW).run(elements=[E, F, H, E*F + H]) # long time + sage: L = lie_algebras.VirasoroAlgebra(QQ) + sage: U = L.pbw_basis() + sage: d = U.algebra_generators() + sage: TestSuite(U).run() + sage: elts = [d[1], d[-1], d[2], d[-2]*d[1], d[-1]*d[1], d[3]^3*d[5], d['c']] + sage: TestSuite(U).run(elements=elts) # long time """ if basis_key is not None: self._basis_key = basis_key else: - self._basis_key_inverse = None + try: + self._basis_key = g._basis_key + except AttributeError: + self._basis_key_inverse = None R = g.base_ring() self._g = g @@ -630,3 +637,169 @@ def _act_on_(self, x, self_on_left): ret += term return ret return None + + +class PoincareBirkhoffWittBasisSemisimpleLieAlgebra(PoincareBirkhoffWittBasis): + r""" + The Poincare-Birkhoff-Witt basis of a finite dimensional triangular + Kac-Moody Lie algebra (i.e., a semisimple Lie algebra). + """ + def __init__(self, g, basis_key=None, *args, **kwds): + r""" + Initialize ``self``. + + EXAMPLES:: + + sage: U = lie_algebras.so(QQ, 5).pbw_basis() + sage: TestSuite(U).run() + + sage: L = lie_algebras.sl(QQ, 2) + sage: PBW = L.pbw_basis() + sage: E, F, H = PBW.algebra_generators() + sage: TestSuite(PBW).run(elements=[E, F, H]) + sage: TestSuite(PBW).run(elements=[E, F, H, E*F + H]) # long time + """ + super().__init__(g, basis_key, *args, **kwds) + if self._basis_key == self._g._triangular_key: + self._triangular_pbw = self + else: + self._triangular_pbw = self._g.pbw_basis(basis_key=self._g._triangular_key) + + def e(self, i=None): + r""" + Return the generators `e` of ``self``. + + INPUT: + + - ``i`` -- (optional) if specified, return just the + generator `e_i` + + EXAMPLES:: + + sage: U = lie_algebras.so(QQ, 5).pbw_basis() + sage: U.e() + Finite family {1: PBW[alpha[1]], 2: PBW[alpha[2]]} + sage: U.e(1) + PBW[alpha[1]] + """ + if i is None: + return Family({i: self.e(i) for i in self._g.cartan_type().index_set()}) + return self(self._g.e(i)) + + def f(self, i=None): + r""" + Return the generators `f` of ``self``. + + INPUT: + + - ``i`` -- (optional) if specified, return just the + generator `f_i` + + EXAMPLES:: + + sage: U = lie_algebras.so(QQ, 5).pbw_basis() + sage: U.f() + Finite family {1: PBW[-alpha[1]], 2: PBW[-alpha[2]]} + sage: U.f(1) + PBW[-alpha[1]] + """ + if i is None: + return Family({i: self.f(i) for i in self._g.cartan_type().index_set()}) + return self(self._g.f(i)) + + def contravariant_form(self, x, y): + r""" + Return the (universal) contravariant form of ``x`` and ``y``. + + Let `\varphi \colon U(\mathfrak{g}) \to U(\mathfrak{h})` denote + the projection onto the Cartan subalgebra and `\tau` be the transpose + map. The *(universal) contravariant form* is defined as + + .. MATH:: + + (x, y) = \varphi(\tau(x) y). + + EXAMPLES:: + + sage: g = LieAlgebra(QQ, cartan_type=['G', 2]) + sage: U = g.pbw_basis() + sage: f1, f2 = U.f() + sage: e1, e2 = U.e() + sage: U.contravariant_form(U.one(), U.one()) + 1 + sage: U.contravariant_form(f1, f1) + PBW[alphacheck[1]] + sage: U.contravariant_form(f2, f2) + PBW[alphacheck[2]] + sage: U.contravariant_form(f1*f2, f1*f2) + PBW[alphacheck[1]]*PBW[alphacheck[2]] + 3*PBW[alphacheck[2]] + sage: U.contravariant_form(e1*e1*e2, e2*e1*e2) + 0 + sage: cas = U.casimir_element() + sage: ccc = U.contravariant_form(cas, cas); ccc + 1/144*PBW[alphacheck[1]]^4 + 1/24*PBW[alphacheck[1]]^3*PBW[alphacheck[2]] + + 5/48*PBW[alphacheck[1]]^2*PBW[alphacheck[2]]^2 + + 1/8*PBW[alphacheck[1]]*PBW[alphacheck[2]]^3 + 1/16*PBW[alphacheck[2]]^4 + + 5/72*PBW[alphacheck[1]]^3 + 1/3*PBW[alphacheck[1]]^2*PBW[alphacheck[2]] + + 7/12*PBW[alphacheck[1]]*PBW[alphacheck[2]]^2 + 3/8*PBW[alphacheck[2]]^3 + + 25/144*PBW[alphacheck[1]]^2 + 5/8*PBW[alphacheck[1]]*PBW[alphacheck[2]] + + 9/16*PBW[alphacheck[2]]^2 + sage: ccc.parent() is U + True + """ + x = self._triangular_pbw(x) + y = self._triangular_pbw(y) + temp = (x.transpose() * y)._monomial_coefficients + part = self._g._part_on_basis + ret = {mon: temp[mon] for mon in temp if all(part(b) == 0 for b in mon.support())} + # TODO: Construct this direct in ``self`` + return self(self._triangular_pbw.element_class(self._triangular_pbw, ret)) + + @cached_method + def _transpose_on_basis(self, m): + """ + Return the transpose map applied to the basis element indexed by ``m``. + + EXAMPLES:: + + sage: g = LieAlgebra(QQ, cartan_type=['E', 6]) + sage: U = g.pbw_basis() + sage: f1, f2, f3, f4, f5, f6 = U.f() + sage: e1, e2, e3, e4, e5, e6 = U.e() + sage: elt = e1 * e4^2 * f1 * f2^3 + sage: U._transpose_on_basis(elt.support()[0]) + PBW[alpha[2]]^3*PBW[alpha[1]]*PBW[-alpha[4]]^2*PBW[-alpha[1]] + """ + I = self._indices + basis_mapping = self._g._transpose_basis_mapping + return self.prod(self.monomial(I({basis_mapping[k]: e})) + for k, e in reversed(m._sorted_items())) + + @lazy_attribute + def transpose(self): + r""" + The transpose map. + + EXAMPLES:: + + sage: g = LieAlgebra(QQ, cartan_type=['F', 4]) + sage: U = g.pbw_basis() + sage: U.transpose + Generic endomorphism of Universal enveloping algebra of Lie algebra + of ['F', 4] in the Chevalley basis in the Poincare-Birkhoff-Witt basis + """ + return self.module_morphism(self._transpose_on_basis, codomain=self) + + class Element(PoincareBirkhoffWittBasis.Element): + def transpose(self): + r""" + Return the transpose map of ``self``. + + This is the tranpose map on the Lie algebra extended + as an anti-involution of ``self``. + + EXAMPLES:: + + sage: g = LieAlgebra(QQ, cartan_type=['D', 4]) + """ + return self.parent().transpose(self) diff --git a/src/sage/algebras/lie_algebras/verma_module.py b/src/sage/algebras/lie_algebras/verma_module.py index 7970e30ef8d..9cd53cbc4ef 100644 --- a/src/sage/algebras/lie_algebras/verma_module.py +++ b/src/sage/algebras/lie_algebras/verma_module.py @@ -120,7 +120,7 @@ def __init__(self, g, weight, basis_key=None, prefix='f', **kwds): category=Modules(R).WithBasis().Graded()) def _triangular_key(self, x): - """ + r""" Return a key for sorting for the index ``x`` that respects the triangular decomposition by `U^-, U^0, U^+`. @@ -242,7 +242,7 @@ def _repr_generator(self, m): sage: L = lie_algebras.sp(QQ, 4) sage: La = L.cartan_type().root_system().ambient_space().fundamental_weights() sage: M = L.verma_module(-1/2*La[1] + 3/7*La[2]) - sage: f1, f2 = L.f(1), L.f(2) + sage: f1, f2 = L.f() sage: x = M.pbw_basis()(L([f1, [f1, f2]])) sage: v = x * M.highest_weight_vector() sage: M._repr_generator(v.leading_support()) @@ -269,7 +269,7 @@ def _latex_generator(self, m): sage: L = lie_algebras.sp(QQ, 4) sage: La = L.cartan_type().root_system().ambient_space().fundamental_weights() sage: M = L.verma_module(-1/2*La[1] + 3/7*La[2]) - sage: f1, f2 = L.f(1), L.f(2) + sage: f1, f2 = L.f() sage: x = M.pbw_basis()(L([f1, [f1, f2]])) sage: v = x * M.highest_weight_vector() sage: M._latex_generator(v.leading_support()) @@ -451,6 +451,47 @@ def _element_constructor_(self, x): return self.highest_weight_vector()._acted_upon_(x, False) return super()._element_constructor_(self, x) + def contravariant_form(self, x, y): + r""" + Return the contravariant form of ``x`` and ``y``. + + Let `C(x, y)` denote the (universal) contravariant form on + `U(\mathfrak{g})`. Then the contravariant form on `M(\lambda)` is + given by evaluating `C(x, y) \in U(\mathfrak{h})` at `\lambda`. + + EXAMPLES:: + + sage: g = LieAlgebra(QQ, cartan_type=['A', 1]) + sage: La = g.cartan_type().root_system().weight_lattice().fundamental_weights() + sage: M = g.verma_module(2*La[1]) + sage: U = M.pbw_basis() + sage: v = M.highest_weight_vector() + sage: e, h, f = U.algebra_generators() + sage: elts = [f^k * v for k in range(8)]; elts + [v[2*Lambda[1]], f[-alpha[1]]*v[2*Lambda[1]], + f[-alpha[1]]^2*v[2*Lambda[1]], f[-alpha[1]]^3*v[2*Lambda[1]], + f[-alpha[1]]^4*v[2*Lambda[1]], f[-alpha[1]]^5*v[2*Lambda[1]], + f[-alpha[1]]^6*v[2*Lambda[1]], f[-alpha[1]]^7*v[2*Lambda[1]]] + sage: matrix([[M.contravariant_form(x, y) for x in elts] for y in elts]) + [1 0 0 0 0 0 0 0] + [0 2 0 0 0 0 0 0] + [0 0 4 0 0 0 0 0] + [0 0 0 0 0 0 0 0] + [0 0 0 0 0 0 0 0] + [0 0 0 0 0 0 0 0] + [0 0 0 0 0 0 0 0] + [0 0 0 0 0 0 0 0] + """ + pbw = self._pbw + I = pbw._indices + xlift = pbw.element_class(pbw, {I(m._monomial): c for m, c in x._monomial_coefficients.items()}) + ylift = pbw.element_class(pbw, {I(m._monomial): c for m, c in y._monomial_coefficients.items()}) + univ = pbw.contravariant_form(xlift, ylift) + la = self._weight + R = self.base_ring() + return R.sum(c * R.prod(la.scalar(k) ** e for k, e in m._monomial.items()) + for m, c in univ._monomial_coefficients.items()) + @lazy_attribute def _dominant_data(self): r""" @@ -800,7 +841,7 @@ def _call_(self, x): sage: M = L.verma_module(La[1] + La[2]) sage: Mp = L.verma_module(M.highest_weight().dot_action([1,2])) sage: pbw = M.pbw_basis() - sage: f1, f2 = pbw(L.f(1)), pbw(L.f(2)) + sage: f1, f2 = pbw.f() sage: v = Mp.highest_weight_vector() sage: phi = Hom(Mp, M).natural_map() sage: phi(f1 * v) == f1 * phi(v) @@ -833,7 +874,7 @@ def _on_basis(self, m): sage: M = L.verma_module(La[1] + La[2]) sage: Mp = L.verma_module(M.highest_weight().dot_action([1,2])) sage: pbw = M.pbw_basis() - sage: f1, f2 = pbw(L.f(1)), pbw(L.f(2)) + sage: f1, f2 = pbw.f() sage: v = Mp.highest_weight_vector() sage: phi = Hom(Mp, M).natural_map() sage: phi._on_basis((f1 * v).leading_support()) == f1 * phi(v) @@ -1087,12 +1128,16 @@ def singular_vector(self): ALGORITHM: We essentially follow the algorithm laid out in [deG2005]_. - We use the `\mathfrak{sl}_2` relation on - `M_{s_i \cdot \lambda} \to M_{\lambda}`, where - `\langle \lambda + \delta, \alpha_i^{\vee} \rangle = m > 0`, - i.e., the weight `\lambda` is `i`-dominant with respect to - the dot action. From here, we construct the singular vector - `f_i^m v_{\lambda}`. We iterate this until we reach `\mu`. + We split the main computation into two cases. If there exists + an `i` such that `\langle \lambda + \rho, \alpha_i^{\vee} + \rangle = m > 0` (i.e., the weight `\lambda` is `i`-dominant + with respect to the dot action), then we use the `\mathfrak{sl}_2` + relation on `M_{s_i \cdot \lambda} \to M_{\lambda}` to + construct the singular vector `f_i^m v_{\lambda}`. Otherwise + we find the shortest root `\alpha` such that `\langle \lambda + + \rho, \alpha^{\vee} \rangle > 0` and explicitly compute the + kernel with respect to the weight basis elements. We iterate + this until we reach `\mu`. EXAMPLES:: @@ -1103,13 +1148,15 @@ def singular_vector(self): sage: M = L.verma_module(la) sage: Mp = L.verma_module(mu) sage: H = Hom(Mp, M) - sage: H.singular_vector() + sage: v = H.singular_vector(); v f[-alpha[2]]*f[-alpha[1]]^3*v[Lambda[1] - Lambda[3]] + 3*f[-alpha[1]]^2*f[-alpha[1] - alpha[2]]*v[Lambda[1] - Lambda[3]] + sage: v.degree() == Mp.highest_weight() + True :: - sage: L = LieAlgebra(QQ, cartan_type=['F',4]) + sage: L = LieAlgebra(QQ, cartan_type=['F', 4]) sage: La = L.cartan_type().root_system().weight_space().fundamental_weights() sage: la = La[1] + La[2] - La[3] sage: mu = la.dot_action([1,2,3,2]) @@ -1119,7 +1166,9 @@ def singular_vector(self): sage: v = H.singular_vector() sage: pbw = M.pbw_basis() sage: E = [pbw(e) for e in L.e()] - sage: all(e * v == M.zero() for e in E) + sage: all(e * v == M.zero() for e in E) # long time + True + sage: v.degree() == Mp.highest_weight() True When `w \cdot \lambda \notin \lambda + Q^-`, there does not @@ -1135,6 +1184,24 @@ def singular_vector(self): sage: H.singular_vector() is None True + When we need to apply a non-simple reflection, we can compute + the singular vector (see :issue:`36793`):: + + sage: g = LieAlgebra(QQ, cartan_type=['A', 2]) + sage: La = g.cartan_type().root_system().weight_lattice().fundamental_weights() + sage: M = g.verma_module((0*La[1]).dot_action([1])) + sage: Mp = g.verma_module((0*La[1]).dot_action([1,2])) + sage: H = Hom(Mp, M) + sage: v = H.singular_vector(); v + 1/2*f[-alpha[2]]*f[-alpha[1]]*v[-2*Lambda[1] + Lambda[2]] + + f[-alpha[1] - alpha[2]]*v[-2*Lambda[1] + Lambda[2]] + sage: pbw = M.pbw_basis() + sage: E = [pbw(e) for e in g.e()] + sage: all(e * v == M.zero() for e in E) + True + sage: v.degree() == Mp.highest_weight() + True + TESTS:: sage: L = lie_algebras.sl(QQ, 3) @@ -1154,29 +1221,100 @@ def singular_vector(self): return None from sage.combinat.root_system.coxeter_group import CoxeterGroup + from sage.matrix.constructor import matrix W = CoxeterGroup(self.domain()._g._cartan_type) - wp = W.from_reduced_word(self.domain()._dominant_data[1]) - w = W.from_reduced_word(self.codomain()._dominant_data[1]) + # We take the inverse to account for the left versus right action + wp = W.from_reduced_word(reversed(self.domain()._dominant_data[1])) + w = W.from_reduced_word(reversed(self.codomain()._dominant_data[1])) if not w.bruhat_le(wp): return None C = self.codomain() pbw = C._pbw - f = C._g.f() - F = {i: pbw(f[i]) for i in f.keys()} - red_word = (wp * ~w).reduced_word() + F = pbw.f() + E = pbw.e() + index_set = F.keys() + cur_w = w rho = C._weight.parent().rho() ac = C._weight.parent().simple_coroots() elt = pbw.one() wt = C._weight - # Construct the singular vector by iterated embeddings of Verma - # modules (without constructing the modules themselves) - for i in reversed(red_word): - exp = (wt + rho).scalar(ac[i]) - if exp not in ZZ or exp < 0: - return None - elt = F[i]**ZZ(exp) * elt - wt = wt.dot_action([i]) - return C.highest_weight_vector()._acted_upon_(elt, False) + pos_roots_by_ht = C._g._cartan_type.root_system().root_lattice().positive_roots_by_height() + assert all(sum(rt.coefficients()) == 1 for rt in pos_roots_by_ht[:len(index_set)]) + # for this, we don't need to check the simple roots + pos_roots_by_ht = pos_roots_by_ht[len(index_set):] + + while cur_w != wp: + ind = None + for i in cur_w.descents(side='right', positive=True): + exp = (wt + rho).scalar(ac[i]) + if exp not in ZZ or exp <= 0: + continue + # We need to check that the result is still smaller in Bruhat order + next_w = cur_w.apply_simple_reflection_right(i) + if not next_w.bruhat_le(wp): + continue + ind = i + # favor a path in weak order so we only do sl_2 relations + if not next_w.weak_le(wp, side="right"): + continue + break + if ind is None: # no simple root; need a more general approach + # We search for the shortest root that can be applied to minimize + # the size of the basis needed to compute the kernel. + for rt in pos_roots_by_ht: + exp = (wt + rho).scalar(rt.associated_coroot()) + # We need to check that the result is still smaller in Bruhat order + i, wd = rt.to_simple_root(reduced_word=True) + refl = wd + (i,) + tuple(reversed(wd)) + next_w = cur_w.apply_reflections(refl, side='right', word_type="simple") + if exp not in ZZ or exp <= 0: + continue + if not next_w.bruhat_le(wp): + continue + # We construct the Verma module of the appropriate weight in + # order to reduce the dimension and number of multiplications. + Mp = C._g.verma_module(wt) + basis = sorted(Mp._homogeneous_component_f(-rt.to_vector()), key=str) + for i in index_set: + image = [E[i] * b for b in basis] + supp = set() + for vec in image: + supp.update(vec._monomial_coefficients) + supp = sorted(supp, key=pbw._monomial_key) + if not supp: # everything is in the kernel + continue + M = matrix(pbw.base_ring(), [[v[s] for v in image] for s in supp]) + ker = M.right_kernel_matrix() + basis = [C.linear_combination((basis[j], c) for j, c in kv.iteritems()) + for kv in ker.rows()] + + assert len(basis) == 1 + if Mp is C: # We've constructed the element in the codomain + assert next_w == wp + assert basis[0].degree() == self.domain().highest_weight() + return basis[0] + pbw_elt = pbw.element_class(pbw, {pbw._indices(m._monomial): c + for m, c in basis[0]._monomial_coefficients.items()}) + elt = pbw_elt * elt + wt = wt.dot_action(refl) + cur_w = next_w + break + else: + #assert False, "unable to find root" + # Have a more explicit check at the beginning using the integral + # orbit action for the correct version of dominance; see, e.g., + # Humphreys "Representations of Semisimple Lie Algebras in the BGG Category O". + return None + else: + # Construct the singular vector by iterated embeddings of Verma + # modules from the sl_2 relations (without constructing + # the modules themselves) + elt = F[ind]**ZZ(exp) * elt + wt = wt.dot_action([ind]) + cur_w = cur_w.apply_simple_reflection_right(ind) + ret = C.highest_weight_vector()._acted_upon_(elt, False) + assert ret.degree() == self.domain().highest_weight() + return ret @cached_method def natural_map(self): diff --git a/src/sage/categories/coxeter_groups.py b/src/sage/categories/coxeter_groups.py index 8b9e20ad03e..3d62d98272b 100644 --- a/src/sage/categories/coxeter_groups.py +++ b/src/sage/categories/coxeter_groups.py @@ -2715,21 +2715,23 @@ def bruhat_le(self, other): return self.apply_simple_projection(desc, length_increasing=False).bruhat_le(other.apply_simple_reflection(desc)) return self == other + @cached_in_parent_method def weak_le(self, other, side='right'): """ - Comparison in weak order. + Perform the comparison between ``self`` and ``other`` in + weak (Bruhat) order. INPUT: - - other -- an element of the same Coxeter group - - side -- 'left' or 'right' (default: 'right') + - ``other`` -- an element of the same Coxeter group + - ``side`` -- string (default: ``'right'``); ``'left'`` or ``'right'`` OUTPUT: a boolean - This returns whether ``self`` <= ``other`` in left - (resp. right) weak order, that is if 'v' can be obtained - from 'v' by length increasing multiplication by simple - reflections on the left (resp. right). + This returns whether `u \leq v`, where `u` is ``self`` and `v` + is ``other``, in left (resp. right) weak order, that is if `v` + can be obtained from `u` by length increasing multiplication by + simple reflections on the left (resp. right). EXAMPLES:: diff --git a/src/sage/categories/triangular_kac_moody_algebras.py b/src/sage/categories/triangular_kac_moody_algebras.py index 0a7988282d3..543f97533b5 100644 --- a/src/sage/categories/triangular_kac_moody_algebras.py +++ b/src/sage/categories/triangular_kac_moody_algebras.py @@ -19,12 +19,14 @@ from sage.misc.abstract_method import abstract_method from sage.misc.cachefunc import cached_method +from sage.misc.lazy_attribute import lazy_attribute from sage.categories.category_types import Category_over_base_ring +from sage.categories.category_with_axiom import CategoryWithAxiom_over_base_ring from sage.categories.kac_moody_algebras import KacMoodyAlgebras class TriangularKacMoodyAlgebras(Category_over_base_ring): - """ + r""" Category of Kac-Moody algebras with a distinguished basis that respects the triangular decomposition. @@ -61,11 +63,18 @@ def _part_on_basis(self, m): EXAMPLES:: - sage: L = lie_algebras.so(QQ, 5) # needs sage.combinat sage.modules - sage: L.f() # needs sage.combinat sage.modules + sage: # needs sage.combinat sage.modules + sage: L = lie_algebras.so(QQ, 5) + sage: L.f() # indirect doctest Finite family {1: E[-alpha[1]], 2: E[-alpha[2]]} - sage: L.f(1) # needs sage.combinat sage.modules + sage: f1 = L.f(1); f1 # indirect doctest E[-alpha[1]] + sage: L._part_on_basis(f1.leading_support()) + -1 + sage: L._part_on_basis(L.e(1).leading_support()) + 1 + sage: all(L._part_on_basis(b) == 0 for b in L.basis() if b.degree() == 0) + True """ deg = self.degree_on_basis(m) if not deg: @@ -200,6 +209,29 @@ def _weight_action(self, m, wt): 0 """ + def _triangular_key(self, x): + r""" + Return a key for sorting for the index ``x`` that respects + the triangular decomposition by `U^-, U^0, U^+`. + + EXAMPLES:: + + sage: L = lie_algebras.sl(QQ, 3) + sage: La = L.cartan_type().root_system().weight_lattice().fundamental_weights() + sage: sorted(L.basis().keys(), key=L._basis_key) + [alpha[2], alpha[1], alpha[1] + alpha[2], + alphacheck[1], alphacheck[2], + -alpha[2], -alpha[1], -alpha[1] - alpha[2]] + sage: sorted(L.basis().keys(), key=L._triangular_key) + [-alpha[2], -alpha[1], -alpha[1] - alpha[2], + alphacheck[1], alphacheck[2], + alpha[2], alpha[1], alpha[1] + alpha[2]] + """ + try: + return (self._part_on_basis(x), self._basis_key(x)) + except AttributeError: + return (self._part_on_basis(x), x) + def verma_module(self, la, basis_key=None, **kwds): """ Return the Verma module with highest weight ``la`` @@ -263,3 +295,99 @@ def part(self): if all(k == 0 for k in S): return 0 raise ValueError("element is not in one part") + + class FiniteDimensional(CategoryWithAxiom_over_base_ring): + r""" + Category of finite dimensional Kac-Moody algebras (which correspond + to semisimple Lie algebras) with a distinguished basis that + respects the triangular decomposition. + """ + class ParentMethods: + @lazy_attribute + def _transpose_basis_mapping(self): + """ + The mapping on basis elements for the transpose map. + + EXAMPLES:: + + sage: g = LieAlgebra(QQ, cartan_type=['A', 2]) + sage: g._transpose_basis_mapping + {-alpha[1]: alpha[1], + -alpha[1] - alpha[2]: alpha[1] + alpha[2], + -alpha[2]: alpha[2], + alpha[1]: -alpha[1], + alpha[1] + alpha[2]: -alpha[1] - alpha[2], + alpha[2]: -alpha[2], + alphacheck[1]: alphacheck[1], + alphacheck[2]: alphacheck[2]} + """ + Q = self.cartan_type().root_system().root_lattice() + K = self.basis().keys() + deg_map = {} + ret = {} + for k in K: + deg = self.degree_on_basis(k) + if deg: + deg_map[deg] = k + else: + ret[k] = k + for al, k in deg_map.items(): + ret[k] = deg_map[-al] + return ret + + @cached_method + def _transpose_on_basis(self, m): + r""" + Return the transpose map on the basis element indexed by ``m``. + + EXAMPLES:: + + sage: g = LieAlgebra(QQ, cartan_type=['B', 2]) + sage: B = g.basis() + sage: [(B[k], g._transpose_on_basis(k)) for k in B.keys()] + [(E[alpha[2]], E[-alpha[2]]), + (E[alpha[1]], E[-alpha[1]]), + (E[alpha[1] + alpha[2]], E[-alpha[1] - alpha[2]]), + (E[alpha[1] + 2*alpha[2]], E[-alpha[1] - 2*alpha[2]]), + (h1, h1), + (h2, h2), + (E[-alpha[2]], E[alpha[2]]), + (E[-alpha[1]], E[alpha[1]]), + (E[-alpha[1] - alpha[2]], E[alpha[1] + alpha[2]]), + (E[-alpha[1] - 2*alpha[2]], E[alpha[1] + 2*alpha[2]])] + """ + return self.monomial(self._transpose_basis_mapping[m]) + + @lazy_attribute + def transpose(self): + r""" + The transpose map of ``self``. + + EXAMPLES:: + + sage: g = LieAlgebra(QQ, cartan_type=['B', 2]) + sage: g.transpose + Generic endomorphism of Lie algebra of ['B', 2] in the Chevalley basis + """ + return self.module_morphism(self._transpose_on_basis, codomain=self) + + class ElementMethods: + def transpose(self): + r""" + Return the transpose of ``self``. + + The transpose `\tau` is the map that sends the root basis + elements `e_{\alpha} \leftrightarrow e_{-\alpha}` and fixes + the Cartan subalgebra `h_{\alpha}`. It is an anti-involution + in the sense `[\tau(a), \tau(b)] = \tau([a, b])`. + + EXAMPLES:: + + sage: g = LieAlgebra(QQ, cartan_type=['G', 2]) + sage: for b in g.basis(): + ....: for bp in g.basis(): + ....: a = g[b.transpose(), bp.transpose()] + ....: ap = g[bp, b].transpose() + ....: assert a == ap + """ + return self.parent().transpose(self) diff --git a/src/sage/monoids/indexed_free_monoid.py b/src/sage/monoids/indexed_free_monoid.py index 66af0a2fb5c..ef82ef41705 100644 --- a/src/sage/monoids/indexed_free_monoid.py +++ b/src/sage/monoids/indexed_free_monoid.py @@ -288,7 +288,11 @@ def support(self): [0, 2] """ supp = {key for key, exp in self._sorted_items() if exp != 0} - return sorted(supp) + try: + return sorted(supp, key=print_options['sorting_key'], + reverse=print_options['sorting_reverse']) + except Exception: # Sorting the output is a plus, but if we can't, no big deal + return list(supp) def leading_support(self): """ @@ -773,14 +777,12 @@ def _element_constructor_(self, x=None): sage: F([[1, 3], [-2, 12]]) F[-2]^12*F[1]^3 sage: F(-5) - Traceback (most recent call last): - ... - TypeError: unable to convert -5, use gen() instead + F[-5] """ if x is None: return self.one() if x in self._indices: - raise TypeError(f"unable to convert {x!r}, use gen() instead") + return self.gen(x) return self.element_class(self, x) def _an_element_(self): @@ -933,9 +935,9 @@ def gen(self, x): if x not in self._indices: raise IndexError(f"{x} is not in the index set") try: - return self.element_class(self, ((self._indices(x),1),)) - except (TypeError, NotImplementedError): # Backup (e.g., if it is a string) - return self.element_class(self, ((x,1),)) + return self.element_class(self, ((self._indices(x), ZZ.one()),)) + except (ValueError, TypeError, NotImplementedError): # Backup (e.g., if it is a string) + return self.element_class(self, ((x, ZZ.one()),)) class IndexedFreeAbelianMonoid(IndexedMonoid): """ @@ -1045,10 +1047,15 @@ def gen(self, x): Traceback (most recent call last): ... IndexError: 0 is not in the index set + + sage: F = lie_algebras.VirasoroAlgebra(QQ).pbw_basis().indices(); F + Free abelian monoid indexed by Disjoint union of Family ({'c'}, Integer Ring) + sage: F.gen('c') + PBW['c'] """ if x not in self._indices: raise IndexError(f"{x} is not in the index set") try: - return self.element_class(self, {self._indices(x): 1}) - except (TypeError, NotImplementedError): # Backup (e.g., if it is a string) - return self.element_class(self, {x: 1}) + return self.element_class(self, {self._indices(x): ZZ.one()}) + except (ValueError, TypeError, NotImplementedError): # Backup (e.g., if it is a string) + return self.element_class(self, {x: ZZ.one()}) From 4aa6dd71d00f2438d4ae03fb4edd92163d4519b5 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Sat, 6 Jan 2024 03:17:26 +0900 Subject: [PATCH 065/231] Adding BGG dual (Verma) modules and generalizing Verma module hom(set)s. --- .../algebras/lie_algebras/bgg_dual_module.py | 266 ++++++++++++++++++ .../algebras/lie_algebras/verma_module.py | 161 +++++++++-- 2 files changed, 401 insertions(+), 26 deletions(-) create mode 100644 src/sage/algebras/lie_algebras/bgg_dual_module.py diff --git a/src/sage/algebras/lie_algebras/bgg_dual_module.py b/src/sage/algebras/lie_algebras/bgg_dual_module.py new file mode 100644 index 00000000000..b0681cb0304 --- /dev/null +++ b/src/sage/algebras/lie_algebras/bgg_dual_module.py @@ -0,0 +1,266 @@ +r""" +BGG Category O Dual Modules + +AUTHORS: + +- Travis Scrimshaw (2024-01-07): Initial version +""" + +#***************************************************************************** +# Copyright (C) 2023 Travis Scrimshaw +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# http://www.gnu.org/licenses/ +#***************************************************************************** + +from sage.misc.lazy_attribute import lazy_attribute +from sage.misc.cachefunc import cached_method +from sage.categories.modules import Modules +from sage.categories.morphism import Morphism +from sage.categories.homset import Hom, Homset +from sage.monoids.indexed_free_monoid import IndexedFreeAbelianMonoid +from sage.combinat.free_module import CombinatorialFreeModule + +class BGGDualModule(CombinatorialFreeModule): + r""" + The dual module `M^{\vee}` in the BGG Category `\mathcal{O}`. + + Let `\tau` be the transpose map of a semisimple (finite dimensional) + Lie algebra `\mathfrak{g}` over a field `R`. Let `M \in \mathcal{O}`. + The *BGG dual module* is the `R`-module `M^{\vee} := + \bigoplus_{\lambda} M_{\lambda}^*` which has a `U(\mathfrak{g})`-module + structure given by + + .. MATH:: + + x \cdot \phi(v) := \phi(\tau(x) \cdot v), + + which is also a weight module with the same grading as `M`. + + The basis we chose to work with here is the natural dual basis to the + distinguished basis `B` of `M`. That is, we define the dual function + to `b` as `\phi_b(c) = \delta_{bc}`. + + EXAMPLES:: + + sage: g = LieAlgebra(QQ, cartan_type=['A', 1]) + sage: La = g.cartan_type().root_system().weight_lattice().fundamental_weights() + sage: M = g.verma_module(2*La[1]) + sage: Mc = M.dual() + sage: B = Mc.basis() + sage: it = iter(B) + sage: elts = [next(it) for _ in range(7)]; elts + [v[2*Lambda[1]], + f[-alpha[1]]*v[2*Lambda[1]], + f[-alpha[1]]^2*v[2*Lambda[1]], + f[-alpha[1]]^3*v[2*Lambda[1]], + f[-alpha[1]]^4*v[2*Lambda[1]], + f[-alpha[1]]^5*v[2*Lambda[1]], + f[-alpha[1]]^6*v[2*Lambda[1]]] + sage: e, h, f = g.pbw_basis().algebra_generators() + sage: [f * vec for vec in elts] + [2*f[-alpha[1]]*v[2*Lambda[1]], + 2*f[-alpha[1]]^2*v[2*Lambda[1]], + 0, + -4*f[-alpha[1]]^4*v[2*Lambda[1]], + -10*f[-alpha[1]]^5*v[2*Lambda[1]], + -18*f[-alpha[1]]^6*v[2*Lambda[1]], + -28*f[-alpha[1]]^7*v[2*Lambda[1]]] + sage: [e * vec for vec in elts] + [0, + v[2*Lambda[1]], + f[-alpha[1]]*v[2*Lambda[1]], + f[-alpha[1]]^2*v[2*Lambda[1]], + f[-alpha[1]]^3*v[2*Lambda[1]], + f[-alpha[1]]^4*v[2*Lambda[1]], + f[-alpha[1]]^5*v[2*Lambda[1]]] + sage: [h * vec for vec in elts] + [2*v[2*Lambda[1]], + 0, + -2*f[-alpha[1]]^2*v[2*Lambda[1]], + -4*f[-alpha[1]]^3*v[2*Lambda[1]], + -6*f[-alpha[1]]^4*v[2*Lambda[1]], + -8*f[-alpha[1]]^5*v[2*Lambda[1]], + -10*f[-alpha[1]]^6*v[2*Lambda[1]]] + """ + def __init__(self, module): + r""" + Initialize ``self``. + """ + self._module = module + self._g = module.lie_algebra() + self._pbw = self._g.pbw_basis() + base_ring = module.base_ring() + indices = module.indices() + category = module.category() + CombinatorialFreeModule.__init__(self, base_ring, indices, category=category, + **module.print_options()) + + def _repr_(self): + r""" + Return a string representation of ``self``. + + EXAMPLES:: + + sage: g = LieAlgebra(QQ, cartan_type=['A', 1]) + sage: La = g.cartan_type().root_system().weight_lattice().fundamental_weights() + sage: M = g.verma_module(2*La[1]) + sage: M.dual() + BGG Dual of Verma module with highest weight 2*Lambda[1] of + Lie algebra of ['A', 1] in the Chevalley basis + """ + return "BGG Dual of " + repr(self._module) + + def _latex_(self): + r""" + Return a latex representation of ``self``. + + EXAMPLES:: + + sage: g = LieAlgebra(QQ, cartan_type=['A', 1]) + sage: La = g.cartan_type().root_system().weight_lattice().fundamental_weights() + sage: M = g.verma_module(2*La[1]) + sage: Mc = M.dual() + sage: latex(Mc) + { M_{2 \Lambda_{1}} }^{\vee} + """ + from sage.misc.latex import latex + return "{" + latex(self._module) + "}^{\\vee}" + + def _repr_generator(self, m): + return self._module._repr_generator(m) + + def _latex_generator(self, m): + return self._module._latex_generator(m) + + _repr_term = _repr_generator + _latex_term = _latex_generator + + def degree_on_basis(self, m): + return self._module.degree_on_basis(m) + + def highest_weight(self): + return self._module.highest_weight() + + def highest_weight_vector(self): + r""" + Return the highest weight vector of ``self`` (assuming the + defining module defines such a vector). + + EXAMPLES:: + + sage: g = LieAlgebra(QQ, cartan_type=['A', 1]) + sage: La = g.cartan_type().root_system().weight_lattice().fundamental_weights() + sage: M = g.verma_module(2*La[1]) + sage: Mc = M.dual() + sage: Mc + BGG Dual of Verma module with highest weight 2*Lambda[1] of + Lie algebra of ['A', 1] in the Chevalley basis + """ + hwv = self._module.highest_weight_vector() + return self.element_class(self, hwv.monomial_coefficients(copy=False)) + + def lie_algebra(self): + return self._g + + def dual(self): + return self._module + + @cached_method + def _lie_algebra_on_basis(self, b, m): + r""" + Return the action of the Lie algebra basis element indexed by ``b`` + on the basis element of ``self`` indexed by ``m``. + """ + al = self._g.degree_on_basis(b) + wt = self.degree_on_basis(m) + if al == 0: # b is indexing part of the Cartan subalgebra + # We are assuming b is part of the coroot lattice. + # FIXME: Add something at the category level to return this. + ac = b + return self.term(m, wt.scalar(ac)) + + gens = self._module.homogeneous_component_basis(wt + al) + elt = self._g.basis()[b] + vecs = {g.leading_support(): elt.transpose() * g for g in gens} + return self.element_class(self, {k: c for k, v in vecs.items() if (c := v[m])}) + + def _pbw_monomial_on_basis(self, p, m): + r""" + Return the action of the PBW monomial indexed by ``p`` on the basis + element of ``self`` indexed by ``m``. + + EXAMPLES:: + + sage: g = LieAlgebra(QQ, cartan_type=['A', 1]) + sage: La = g.cartan_type().root_system().weight_lattice().fundamental_weights() + sage: M = g.verma_module(2*La[1]) + sage: Mc = M.dual() + sage: B = Mc.basis() + sage: it = iter(B) + sage: elts = [next(it) for _ in range(7)]; elts + [v[2*Lambda[1]], + f[-alpha[1]]*v[2*Lambda[1]], + f[-alpha[1]]^2*v[2*Lambda[1]], + f[-alpha[1]]^3*v[2*Lambda[1]], + f[-alpha[1]]^4*v[2*Lambda[1]], + f[-alpha[1]]^5*v[2*Lambda[1]], + f[-alpha[1]]^6*v[2*Lambda[1]]] + sage: e, h, f = g.pbw_basis().algebra_generators() + """ + ret = self.monomial(m) + for b, exp in reversed(p._sorted_items()): + for _ in range(exp): + ret = self.linear_combination((self._lie_algebra_on_basis(b, m), mc) + for m, mc in ret._monomial_coefficients.items()) + return ret + + class Element(CombinatorialFreeModule.Element): + def _acted_upon_(self, scalar, self_on_left=False): + r""" + Return the action of ``scalar`` on ``self``. + """ + P = self.parent() + # Check for scalars first + if scalar in P.base_ring(): + # Don't have this be a super call + return CombinatorialFreeModule.Element._acted_upon_(self, scalar, self_on_left) + + # Check for Lie algebra elements + try: + scalar = P._g(scalar) + except (ValueError, TypeError): + pass + if scalar.parent() is P._g: + if self_on_left: # only implemented as a left module + return None + mc = scalar.monomial_coefficients(copy=False) + return P.linear_combination((P._lie_algebra_on_basis(b, m), bc * mc) + for b, bc in mc.items() + for m, mc in self._monomial_coefficients.items()) + + # Check for PBW elements + try: + scalar = P._pbw(scalar) + except (ValueError, TypeError): + # Cannot be made into a PBW element, so propagate it up + return CombinatorialFreeModule.Element._acted_upon_(self, + scalar, self_on_left) + + # We only implement x * self, i.e., as a left module + if self_on_left: + return None + + mc = scalar.monomial_coefficients(copy=False) + return P.linear_combination((P._pbw_monomial_on_basis(p, m), pc * mc) + for p, pc in mc.items() + for m, mc in self._monomial_coefficients.items()) + +class SimpleModule(CombinatorialFreeModule): + r""" + Return the simple module `L_{\lambda}` as the image of the natural + morphism `\phi \colom M_{\lambda} \to M_{\lambda}^{\vee}`. + """ diff --git a/src/sage/algebras/lie_algebras/verma_module.py b/src/sage/algebras/lie_algebras/verma_module.py index 9cd53cbc4ef..057a32328da 100644 --- a/src/sage/algebras/lie_algebras/verma_module.py +++ b/src/sage/algebras/lie_algebras/verma_module.py @@ -366,6 +366,20 @@ def highest_weight(self): """ return self._weight + def dual(self): + r""" + Return the dual module `M(\lambda)^{\vee}` in Category `\mathcal{O}`. + + EXAMPLES:: + + sage: L = lie_algebras.sl(QQ, 2) + sage: La = L.cartan_type().root_system().weight_space().fundamental_weights() + sage: M = L.verma_module(2*La[1]) + sage: Mc = M.dual() + """ + from sage.algebras.lie_algebras.bgg_dual_module import BGGDualModule + return BGGDualModule(self) + def degree_on_basis(self, m): r""" Return the degree (or weight) of the basis element indexed by ``m``. @@ -546,6 +560,50 @@ def is_singular(self): """ return not self._dominant_data[0].is_dominant() + def is_simple(self): + r""" + Return if ``self`` is a simple module. + + A Verma module `M_{\lambda}` is simple if and only if `\lambda` + is *antidominant* in the sense + + .. MATH:: + + \langle \lambda + \rho, \alpha^{\vee} \rangle \notin \ZZ_{>0} + + for all positive roots `\alpha`. + """ + pos_roots = self._g._cartan_type.root_system().root_lattice().positive_roots() + wt = self._weight + self._weight.parent().rho() + for rt in pos_roots: + val = wt.scalar(rt.associated_coroot()) + if val in ZZ and val > 0: + return False + return True + + def is_projective(self): + r""" + Return if ``self`` is a projective module in Category `\mathcal{O}`. + + A Verma module `M_{\lambda}` is projective (in Category `\mathcal{O}` + if and only if `\lambda` is *dominant* in the sense + + .. MATH:: + + \langle \lambda + \rho, \alpha^{\vee} \rangle \notin \ZZ_{<0} + + for all positive roots `\alpha`. + """ + Q = self._g._cartan_type.root_system().root_lattice() + pos_roots = Q.positive_roots() + wt = self._weight + self._weight.parent().rho() + is_dominant = True + for rt in pos_roots: + val = wt.scalar(rt.associated_coroot()) + if val in ZZ and val < 0: + return False + return True + def homogeneous_component_basis(self, d): r""" Return a basis for the ``d``-th homogeneous component of ``self``. @@ -646,17 +704,22 @@ def _Hom_(self, Y, category=None, **options): sage: type(H) <...VermaModuleHomset_with_category_with_equality_by_id'> """ - if not (isinstance(Y, VermaModule) and self._g is Y._g): - raise TypeError("{} must be a Verma module of {}".format(Y, self._g)) + from sage.algebras.lie_algebras.bgg_dual_module import BGGDualModule + if not ((isinstance(Y, VermaModule) + or (isinstance(Y, BGGDualModule) and Y._module is self)) + and self._g is Y.lie_algebra()): + raise TypeError("{} must be an object in Category O of {}".format(Y, self._g)) if category is not None and not category.is_subcategory(self.category()): raise TypeError("{} is not a subcategory of {}".format(category, self.category())) return VermaModuleHomset(self, Y) class Element(CombinatorialFreeModule.Element): def _acted_upon_(self, scalar, self_on_left=False): - """ + r""" Return the action of ``scalar`` on ``self``. + EXAMPLES: + Check that other PBW algebras have an action:: sage: L = lie_algebras.sp(QQ, 6) @@ -735,13 +798,14 @@ def _acted_upon_(self, scalar, self_on_left=False): _lmul_ = _acted_upon_ _rmul_ = _acted_upon_ + ##################################################################### ## Morphisms and Homset class VermaModuleMorphism(Morphism): - """ - A morphism of Verma modules. + r""" + A morphism of a Verma module to another module in Category `\mathcal{O}`. """ def __init__(self, parent, scalar): """ @@ -806,7 +870,7 @@ def _repr_defn(self): v = self.domain().highest_weight_vector() if not self._scalar: return "{} |--> {}".format(v, self.codomain().zero()) - return "{} |--> {}".format(v, self._scalar * self.parent().singular_vector()) + return "{} |--> {}".format(v, self._scalar * self.parent().highest_weight_image()) def _richcmp_(self, other, op): r""" @@ -857,14 +921,14 @@ def _call_(self, x): sage: psi(v) 0 """ - if not self._scalar or self.parent().singular_vector() is None: + if not self._scalar or not self.parent().highest_weight_image(): return self.codomain().zero() mc = x.monomial_coefficients(copy=False) return self.codomain().linear_combination((self._on_basis(m), self._scalar * c) for m,c in mc.items()) def _on_basis(self, m): - """ + r""" Return the image of the basis element indexed by ``m``. EXAMPLES:: @@ -880,8 +944,11 @@ def _on_basis(self, m): sage: phi._on_basis((f1 * v).leading_support()) == f1 * phi(v) True """ + vec = self.parent().highest_weight_image() + if not vec: + return vec pbw = self.codomain()._pbw - return pbw.monomial(pbw._indices(m.dict())) * self.parent().singular_vector() + return pbw.monomial(pbw._indices(m.dict())) * vec def _add_(self, other): """ @@ -977,8 +1044,10 @@ def is_injective(self): r""" Return if ``self`` is injective or not. - A Verma module morphism `\phi : M \to M'` is injective if - and only if `\dim \hom(M, M') = 1` and `\phi \neq 0`. + A morphism `\phi : M \to M'` from a Verma module `M` to another + Verma module `M'` is injective if and only if `\dim \hom(M, M') = 1` + and `\phi \neq 0`. If `M'` is a dual Verma or simple module, then + the result is not injective. EXAMPLES:: @@ -996,15 +1065,20 @@ def is_injective(self): sage: psi.is_injective() False """ - return self.parent().singular_vector() is not None and bool(self._scalar) + if not isinstance(self.codomain(), VermaModule): + return False + return bool(self._scalar) def is_surjective(self): - """ + r""" Return if ``self`` is surjective or not. - A Verma module morphism is surjective if and only if the - domain is equal to the codomain and it is not the zero - morphism. + A morphism `\phi : M \to M'` from a Verma module `M` to another + Verma module `M'` is surjective if and only if the domain is + equal to the codomain and it is not the zero morphism. + + If `M'` is a simple module, then this surjective if and only if + `\dim \hom(M, M') = 1` and `\phi \neq 0`. EXAMPLES:: @@ -1021,13 +1095,27 @@ def is_surjective(self): sage: psi.is_surjective() False """ - return self.domain() == self.codomain() and bool(self._scalar) + if not bool(self._scalar): + return False + + if isinstance(self.codomain(), VermaModule): + return self.domain() == self.codomain() + + from sage.algebras.lie_algebras.bgg_dual_module import SimpleModule + if isinstance(self.codomain(), SimpleModule): + return self.domain().highest_weight() == self.codomain().highest_weight() + + return False + class VermaModuleHomset(Homset): r""" - The set of morphisms from one Verma module to another - considered as `U(\mathfrak{g})`-representations. + The set of morphisms from a Verma module to another module in + Category `\mathcal{O}` considered as `U(\mathfrak{g})`-representations. + + This currently assumes the codomain is a Verma module, its dual, + or a simple module. Let `M_{w \cdot \lambda}` and `M_{w' \cdot \lambda'}` be Verma modules, `\cdot` is the dot action, and `\lambda + \rho`, @@ -1039,9 +1127,13 @@ class VermaModuleHomset(Homset): if and only if `\lambda = \lambda'` and `w' \leq w` in Bruhat order. Otherwise the homset is 0 dimensional. + + If the codomain is a dual Verma module `M_{\mu}^{\vee}`, then the + homset is `\delta_{\lambda\mu}` dimensional. When `\mu = \lambda`, + the image is the simple module `L_{\lambda}`. """ def __call__(self, x, **options): - """ + r""" Construct a morphism in this homset from ``x`` if possible. EXAMPLES:: @@ -1097,7 +1189,7 @@ def __call__(self, x, **options): return super().__call__(x, **options) def _an_element_(self): - """ + r""" Return an element of ``self``. EXAMPLES:: @@ -1118,6 +1210,23 @@ def _an_element_(self): """ return self.natural_map() + def highest_weight_image(self): + r""" + Return the image of the highest weight vector of the domain + in the codomain. + """ + C = self.codomain() + if isinstance(C, VermaModule): + # singular_vector() is cached, so we can safely call it twice + if self.singular_vector() is None: + return C.zero() + return self.singular_vector() + # Otherwise, it is a dual Verma or a simple, so the image + # must be the highest weight vector. + if self.domain().highest_weight() == C.highest_weight(): + return C.highest_weight_vector() + return C.zero() + @cached_method def singular_vector(self): r""" @@ -1347,7 +1456,7 @@ def natural_map(self): of Lie algebra of ['A', 2] in the Chevalley basis Defn: v[Lambda[1] + 2*Lambda[2]] |--> 0 """ - if self.singular_vector() is None: + if not self.highest_weight_image(): return self.zero() return self.element_class(self, self.base_ring().one()) @@ -1374,7 +1483,7 @@ def zero(self): return self.element_class(self, self.base_ring().zero()) def dimension(self): - """ + r""" Return the dimension of ``self`` (as a vector space over the base ring). @@ -1393,12 +1502,12 @@ def dimension(self): sage: H.dimension() 0 """ - if self.singular_vector() is None: + if not self.highest_weight_image(): return ZZ.zero() return ZZ.one() def basis(self): - """ + r""" Return a basis of ``self``. EXAMPLES:: @@ -1416,7 +1525,7 @@ def basis(self): sage: H.basis() Family () """ - if self.singular_vector() is None: + if not self.highest_weight_image(): return Family([]) return Family([self.natural_map()]) From 73a5012c4a26fddeba3ac0961bc60f680145e2c0 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Tue, 9 Jan 2024 22:09:37 +0900 Subject: [PATCH 066/231] Implementation of simple modules by using the image of the Verma into its dual. --- .../algebras/lie_algebras/bgg_dual_module.py | 953 +++++++++++++++++- .../algebras/lie_algebras/verma_module.py | 299 +++--- src/sage/categories/coxeter_groups.py | 2 +- .../triangular_kac_moody_algebras.py | 43 + .../root_system/root_lattice_realizations.py | 45 + .../weight_lattice_realizations.py | 57 +- src/sage/combinat/root_system/weight_space.py | 66 +- src/sage/monoids/indexed_free_monoid.py | 5 + 8 files changed, 1297 insertions(+), 173 deletions(-) diff --git a/src/sage/algebras/lie_algebras/bgg_dual_module.py b/src/sage/algebras/lie_algebras/bgg_dual_module.py index b0681cb0304..d7538c30018 100644 --- a/src/sage/algebras/lie_algebras/bgg_dual_module.py +++ b/src/sage/algebras/lie_algebras/bgg_dual_module.py @@ -18,11 +18,20 @@ from sage.misc.lazy_attribute import lazy_attribute from sage.misc.cachefunc import cached_method -from sage.categories.modules import Modules -from sage.categories.morphism import Morphism -from sage.categories.homset import Hom, Homset -from sage.monoids.indexed_free_monoid import IndexedFreeAbelianMonoid +from sage.categories.enumerated_sets import EnumeratedSets +from sage.categories.monoids import Monoids +from sage.structure.parent import Parent +from sage.structure.indexed_generators import IndexedGenerators +from sage.monoids.indexed_free_monoid import IndexedFreeAbelianMonoid, IndexedMonoid from sage.combinat.free_module import CombinatorialFreeModule +from sage.sets.non_negative_integers import NonNegativeIntegers +from sage.sets.family import Family +from sage.sets.finite_enumerated_set import FiniteEnumeratedSet +from sage.matrix.constructor import matrix +from sage.rings.integer_ring import ZZ +from sage.data_structures.blas_dict import iaxpy +from sage.algebras.lie_algebras.verma_module import ModulePrinting + class BGGDualModule(CombinatorialFreeModule): r""" @@ -53,42 +62,54 @@ class BGGDualModule(CombinatorialFreeModule): sage: B = Mc.basis() sage: it = iter(B) sage: elts = [next(it) for _ in range(7)]; elts - [v[2*Lambda[1]], - f[-alpha[1]]*v[2*Lambda[1]], - f[-alpha[1]]^2*v[2*Lambda[1]], - f[-alpha[1]]^3*v[2*Lambda[1]], - f[-alpha[1]]^4*v[2*Lambda[1]], - f[-alpha[1]]^5*v[2*Lambda[1]], - f[-alpha[1]]^6*v[2*Lambda[1]]] + [v[2*Lambda[1]]^*, + f[-alpha[1]]*v[2*Lambda[1]]^*, + f[-alpha[1]]^2*v[2*Lambda[1]]^*, + f[-alpha[1]]^3*v[2*Lambda[1]]^*, + f[-alpha[1]]^4*v[2*Lambda[1]]^*, + f[-alpha[1]]^5*v[2*Lambda[1]]^*, + f[-alpha[1]]^6*v[2*Lambda[1]]^*] sage: e, h, f = g.pbw_basis().algebra_generators() sage: [f * vec for vec in elts] - [2*f[-alpha[1]]*v[2*Lambda[1]], - 2*f[-alpha[1]]^2*v[2*Lambda[1]], + [2*f[-alpha[1]]*v[2*Lambda[1]]^*, + 2*f[-alpha[1]]^2*v[2*Lambda[1]]^*, 0, - -4*f[-alpha[1]]^4*v[2*Lambda[1]], - -10*f[-alpha[1]]^5*v[2*Lambda[1]], - -18*f[-alpha[1]]^6*v[2*Lambda[1]], - -28*f[-alpha[1]]^7*v[2*Lambda[1]]] + -4*f[-alpha[1]]^4*v[2*Lambda[1]]^*, + -10*f[-alpha[1]]^5*v[2*Lambda[1]]^*, + -18*f[-alpha[1]]^6*v[2*Lambda[1]]^*, + -28*f[-alpha[1]]^7*v[2*Lambda[1]]^*] sage: [e * vec for vec in elts] [0, - v[2*Lambda[1]], - f[-alpha[1]]*v[2*Lambda[1]], - f[-alpha[1]]^2*v[2*Lambda[1]], - f[-alpha[1]]^3*v[2*Lambda[1]], - f[-alpha[1]]^4*v[2*Lambda[1]], - f[-alpha[1]]^5*v[2*Lambda[1]]] + v[2*Lambda[1]]^*, + f[-alpha[1]]*v[2*Lambda[1]]^*, + f[-alpha[1]]^2*v[2*Lambda[1]]^*, + f[-alpha[1]]^3*v[2*Lambda[1]]^*, + f[-alpha[1]]^4*v[2*Lambda[1]]^*, + f[-alpha[1]]^5*v[2*Lambda[1]]^*] sage: [h * vec for vec in elts] - [2*v[2*Lambda[1]], + [2*v[2*Lambda[1]]^*, 0, - -2*f[-alpha[1]]^2*v[2*Lambda[1]], - -4*f[-alpha[1]]^3*v[2*Lambda[1]], - -6*f[-alpha[1]]^4*v[2*Lambda[1]], - -8*f[-alpha[1]]^5*v[2*Lambda[1]], - -10*f[-alpha[1]]^6*v[2*Lambda[1]]] + -2*f[-alpha[1]]^2*v[2*Lambda[1]]^*, + -4*f[-alpha[1]]^3*v[2*Lambda[1]]^*, + -6*f[-alpha[1]]^4*v[2*Lambda[1]]^*, + -8*f[-alpha[1]]^5*v[2*Lambda[1]]^*, + -10*f[-alpha[1]]^6*v[2*Lambda[1]]^*] """ def __init__(self, module): r""" Initialize ``self``. + + EXAMPLES:: + + sage: g = LieAlgebra(QQ, cartan_type=['B', 2]) + sage: La = g.cartan_type().root_system().weight_space().fundamental_weights() + sage: M = g.verma_module(2*La[1]+La[2]) + sage: Mc = M.dual() + sage: TestSuite(Mc).run() + + sage: M = g.verma_module(2/3*La[1]-3/5*La[2]) + sage: Mc = M.dual() + sage: TestSuite(Mc).run() """ self._module = module self._g = module.lie_algebra() @@ -131,18 +152,78 @@ def _latex_(self): return "{" + latex(self._module) + "}^{\\vee}" def _repr_generator(self, m): - return self._module._repr_generator(m) + r""" + Return a string representation of the generator indexed by ``m``. + + EXAMPLES:: + + sage: g = lie_algebras.sp(QQ, 4) + sage: La = g.cartan_type().root_system().ambient_space().fundamental_weights() + sage: Mc = g.verma_module(La[1] + 3/7*La[2]).dual() + sage: f1, f2 = g.f() + sage: x = g.pbw_basis()(g([f1, [f1, f2]])) + sage: v = x * Mc.highest_weight_vector() + sage: Mc._repr_generator(v.leading_support()) + 'f[-alpha[1]]*f[-alpha[1] - alpha[2]]*v[(10/7, 3/7)]^*' + """ + return self._module._repr_generator(m) + "^*" def _latex_generator(self, m): - return self._module._latex_generator(m) + """ + Return a latex representation of the generator indexed by ``m``. + + EXAMPLES:: + + sage: g = lie_algebras.sp(QQ, 4) + sage: La = g.cartan_type().root_system().ambient_space().fundamental_weights() + sage: Mc = g.verma_module(La[1] + 3/7*La[2]).dual() + sage: f1, f2 = g.f() + sage: x = g.pbw_basis()(g([f1, [f1, f2]])) + sage: v = x * Mc.highest_weight_vector() + sage: Mc._latex_generator(v.leading_support()) + { f_{-\alpha_{1}} f_{-\alpha_{1} - \alpha_{2}} v_{\frac{10}{7} e_{0} + \frac{3}{7} e_{1}} }^{\vee} + """ + return "{" + self._module._latex_generator(m) + "}^{\\vee}" _repr_term = _repr_generator _latex_term = _latex_generator def degree_on_basis(self, m): + r""" + Return the degree of the basis element indexed by ``m``. + + EXAMPLES:: + + sage: g = LieAlgebra(QQ, cartan_type=['D', 5]) + sage: La = g.cartan_type().root_system().weight_space().fundamental_weights() + sage: M = g.verma_module(La[1] + La[4] - 1/3*La[5]) + sage: Mc = M.dual() + sage: elt = Mc.an_element(); elt + f[-alpha[5]]^2*f[-alpha[4]]^2*f[-alpha[3]]^3*v[Lambda[1] + Lambda[4] - 1/3*Lambda[5]]^* + + 2*f[-alpha[5]]*v[Lambda[1] + Lambda[4] - 1/3*Lambda[5]]^* + + 3*f[-alpha[4]]*v[Lambda[1] + Lambda[4] - 1/3*Lambda[5]]^* + + v[Lambda[1] + Lambda[4] - 1/3*Lambda[5]]^* + sage: [M.degree_on_basis(m) for m in elt.support()] + [Lambda[1] + 3*Lambda[2] - 2*Lambda[3] - 4/3*Lambda[5], + Lambda[1] + Lambda[4] - 1/3*Lambda[5], + Lambda[1] + Lambda[3] + Lambda[4] - 7/3*Lambda[5], + Lambda[1] + Lambda[3] - Lambda[4] - 1/3*Lambda[5]] + """ return self._module.degree_on_basis(m) def highest_weight(self): + r""" + Return the highest weight of ``self``. + + EXAMPLES:: + + sage: g = LieAlgebra(QQ, cartan_type=['E', 7]) + sage: La = g.cartan_type().root_system().weight_space().fundamental_weights() + sage: M = g.verma_module(2*La[1] + 5/3*La[4] - 3*La[6]) + sage: Mc = M.dual() + sage: Mc.highest_weight() + 2*Lambda[1] + 5/3*Lambda[4] - 3*Lambda[6] + """ return self._module.highest_weight() def highest_weight_vector(self): @@ -156,17 +237,43 @@ def highest_weight_vector(self): sage: La = g.cartan_type().root_system().weight_lattice().fundamental_weights() sage: M = g.verma_module(2*La[1]) sage: Mc = M.dual() - sage: Mc - BGG Dual of Verma module with highest weight 2*Lambda[1] of - Lie algebra of ['A', 1] in the Chevalley basis + sage: Mc.highest_weight_vector() + v[2*Lambda[1]]^* """ hwv = self._module.highest_weight_vector() return self.element_class(self, hwv.monomial_coefficients(copy=False)) def lie_algebra(self): + r""" + Return the underlying Lie algebra of ``self``. + + EXAMPLES:: + + sage: g = LieAlgebra(QQ, cartan_type=['B', 3]) + sage: La = g.cartan_type().root_system().weight_lattice().fundamental_weights() + sage: M = g.verma_module(2*La[1] + La[3]) + sage: Mc = M.dual() + sage: Mc.lie_algebra() is g + True + """ return self._g def dual(self): + r""" + Return the dual module of ``self``. + + In Category `\mathcal{O}`, we have `(M^{\vee})^{\vee} \conj M`, so + we return the defining module `M` of `M^{\vee}`. + + EXAMPLES:: + + sage: g = LieAlgebra(QQ, cartan_type=['F', 4]) + sage: La = g.cartan_type().root_system().weight_space().fundamental_weights() + sage: M = g.verma_module(La[1] - 5/3*La[2] + 3*La[4]) + sage: Mc = M.dual() + sage: Mc.dual() is M + True + """ return self._module @cached_method @@ -174,6 +281,35 @@ def _lie_algebra_on_basis(self, b, m): r""" Return the action of the Lie algebra basis element indexed by ``b`` on the basis element of ``self`` indexed by ``m``. + + EXAMPLES:: + + sage: g = LieAlgebra(QQ, cartan_type=['B', 2]) + sage: La = g.cartan_type().root_system().weight_space().fundamental_weights() + sage: M = g.verma_module(La[1]) + sage: Mc = M.dual() + sage: it = iter(Mc.basis()) + sage: list(g.basis()) + [E[alpha[2]], E[alpha[1]], E[alpha[1] + alpha[2]], E[alpha[1] + 2*alpha[2]], + h1, h2, + E[-alpha[2]], E[-alpha[1]], E[-alpha[1] - alpha[2]], E[-alpha[1] - 2*alpha[2]]] + sage: for _ in range(3): + ....: m = next(it).leading_support() + ....: print(m, [Mc._lie_algebra_on_basis(k, m) for k in g.basis().keys()]) + 1 [0, 0, 0, 0, v[Lambda[1]]^*, 0, 0, f[-alpha[1]]*v[Lambda[1]]^*, + -2*f[-alpha[2]]*f[-alpha[1]]*v[Lambda[1]]^* + 2*f[-alpha[1] - alpha[2]]*v[Lambda[1]]^*, + -2*f[-alpha[2]]^2*f[-alpha[1]]*v[Lambda[1]]^* + + 2*f[-alpha[2]]*f[-alpha[1] - alpha[2]]*v[Lambda[1]]^* + + f[-alpha[1] - 2*alpha[2]]*v[Lambda[1]]^*] + f[-alpha[2]] [v[Lambda[1]]^*, 0, 0, 0, 2*f[-alpha[2]]*v[Lambda[1]]^*, + -2*f[-alpha[2]]*v[Lambda[1]]^*, -2*f[-alpha[2]]^2*v[Lambda[1]]^*, + f[-alpha[2]]*f[-alpha[1]]*v[Lambda[1]]^* + f[-alpha[1] - alpha[2]]*v[Lambda[1]]^*, + -4*f[-alpha[2]]^2*f[-alpha[1]]*v[Lambda[1]]^* - f[-alpha[1] - 2*alpha[2]]*v[Lambda[1]]^*, + -6*f[-alpha[2]]^3*f[-alpha[1]]*v[Lambda[1]]^* + 2*f[-alpha[2]]^2*f[-alpha[1] - alpha[2]]*v[Lambda[1]]^*] + f[-alpha[1]] [0, v[Lambda[1]]^*, 0, 0, -f[-alpha[1]]*v[Lambda[1]]^*, + 2*f[-alpha[1]]*v[Lambda[1]]^*, + 2*f[-alpha[2]]*f[-alpha[1]]*v[Lambda[1]]^* - 2*f[-alpha[1] - alpha[2]]*v[Lambda[1]]^*, + 0, 0, f[-alpha[1]]*f[-alpha[1] - 2*alpha[2]]*v[Lambda[1]]^* + 2*f[-alpha[1] - alpha[2]]^2*v[Lambda[1]]^*] """ al = self._g.degree_on_basis(b) wt = self.degree_on_basis(m) @@ -183,8 +319,11 @@ def _lie_algebra_on_basis(self, b, m): ac = b return self.term(m, wt.scalar(ac)) + # TODO: Avoid calling homogeneous_component_basis() as the result is not cached gens = self._module.homogeneous_component_basis(wt + al) elt = self._g.basis()[b] + # TODO: Determine if we can meaningfully store these results. + # Computing gens is ~1/3 of the computation and vecs is ~2/3. vecs = {g.leading_support(): elt.transpose() * g for g in gens} return self.element_class(self, {k: c for k, v in vecs.items() if (c := v[m])}) @@ -197,19 +336,23 @@ def _pbw_monomial_on_basis(self, p, m): sage: g = LieAlgebra(QQ, cartan_type=['A', 1]) sage: La = g.cartan_type().root_system().weight_lattice().fundamental_weights() + sage: PBW = g.pbw_basis() + sage: e, h, f = PBW.algebra_generators() sage: M = g.verma_module(2*La[1]) sage: Mc = M.dual() + sage: v = Mc.highest_weight_vector() + sage: Mc._pbw_monomial_on_basis((e*f^2).leading_support(), v.leading_support()) + 4*f[-alpha[1]]*v[2*Lambda[1]]^* sage: B = Mc.basis() sage: it = iter(B) sage: elts = [next(it) for _ in range(7)]; elts - [v[2*Lambda[1]], - f[-alpha[1]]*v[2*Lambda[1]], - f[-alpha[1]]^2*v[2*Lambda[1]], - f[-alpha[1]]^3*v[2*Lambda[1]], - f[-alpha[1]]^4*v[2*Lambda[1]], - f[-alpha[1]]^5*v[2*Lambda[1]], - f[-alpha[1]]^6*v[2*Lambda[1]]] - sage: e, h, f = g.pbw_basis().algebra_generators() + [v[2*Lambda[1]]^*, + f[-alpha[1]]*v[2*Lambda[1]]^*, + f[-alpha[1]]^2*v[2*Lambda[1]]^*, + f[-alpha[1]]^3*v[2*Lambda[1]]^*, + f[-alpha[1]]^4*v[2*Lambda[1]]^*, + f[-alpha[1]]^5*v[2*Lambda[1]]^*, + f[-alpha[1]]^6*v[2*Lambda[1]]^*] """ ret = self.monomial(m) for b, exp in reversed(p._sorted_items()): @@ -222,6 +365,22 @@ class Element(CombinatorialFreeModule.Element): def _acted_upon_(self, scalar, self_on_left=False): r""" Return the action of ``scalar`` on ``self``. + + EXAMPLES:: + + sage: g = LieAlgebra(QQ, cartan_type=['A', 1]) + sage: La = g.cartan_type().root_system().weight_lattice().fundamental_weights() + sage: PBW = g.pbw_basis() + sage: e, h, f = PBW.algebra_generators() + sage: M = g.verma_module(2*La[1]) + sage: Mc = M.dual() + sage: v = Mc.highest_weight_vector() + sage: (h*e^2*f^2) * v + 8*v[2*Lambda[1]]^* + sage: g.casimir_element(UEA=PBW) * v + v[2*Lambda[1]]^* + sage: 5 * v + 5*v[2*Lambda[1]]^* """ P = self.parent() # Check for scalars first @@ -259,8 +418,716 @@ def _acted_upon_(self, scalar, self_on_left=False): for p, pc in mc.items() for m, mc in self._monomial_coefficients.items()) -class SimpleModule(CombinatorialFreeModule): + +##################################################################### +## Simple modules + + +# This is an abuse as the monoid is not free. +# FIXME: +# TODO: Rewrite this (or the indexed monoid class) to use explicit vectors +# since we only want to consider ordered elements. +# Note, such a rewrite would force the Lie algebra to be finite dimensional. +class SimpleModuleIndices(IndexedFreeAbelianMonoid): + r""" + The indices of the basis for a simple `U(\mathfrak{g})`-module. + + .. NOTE:: + + The current implementation assumes the Lie algebra `\mathfrak{g}` + is finite dimensional. + """ + # This is only necessary because of the IndexedMonoid.__classcall__. + @staticmethod + def __classcall__(cls, simple, prefix='f', **kwds): + r""" + Normalize input to ensure a unique representation. + + TESTS:: + + sage: g = LieAlgebra(QQ, cartan_type=['E', 6]) + sage: La = g.cartan_type().root_system().weight_lattice().fundamental_weights() + sage: L = g.simple_module(La[1]+La[3]) + sage: from sage.algebras.lie_algebras.bgg_dual_module import SimpleModuleIndices + sage: SimpleModuleIndices(L) is L._indices + True + """ + return super(IndexedMonoid, cls).__classcall__(cls, simple, prefix=prefix, **kwds) + + def __init__(self, simple, prefix, category=None, **kwds): + r""" + Initialize ``self``. + + TESTS:: + + sage: g = LieAlgebra(QQ, cartan_type=['A', 2]) + sage: La = g.cartan_type().root_system().weight_space().fundamental_weights() + sage: I = g.simple_module(2*La[1]+La[2]).indices() + sage: TestSuite(I).run() + + sage: I = g.simple_module(2*La[1]-1/3*La[2]).indices() + sage: TestSuite(I).run(max_runs=150) # long time + """ + self._simple = simple + self._g = simple.lie_algebra() + self._reached_max_depth = False + # Below was mostly copied from IndexedMonoid.__init__() + self._indices = FiniteEnumeratedSet(self._g._negative_half_index_set()) + category = Monoids().or_subcategory(category) + category = category & EnumeratedSets() + category = category.FinitelyGeneratedAsMagma() + if self._simple._dom_int: + category = category.Finite() + else: + category = category.Infinite() + Parent.__init__(self, category=category) + + # ignore the optional 'key' since it only affects CachedRepresentation + kwds.pop('key', None) + sorting_key = kwds.pop('sorting_key', self._simple._pbw._monoid_key) + IndexedGenerators.__init__(self, self._indices, prefix, sorting_key=sorting_key, **kwds) + + self._sorted_supp = sorted(self._g._negative_half_index_set(), key=self._simple._pbw._basis_key, + reverse=self.print_options()['sorting_reverse']) + self._basis = {self.one(): self._simple._ambient.highest_weight_vector()} + self._lead_supp_to_index = {self._simple._ambient.highest_weight_vector().leading_support(): self.one()} + # This is used for iteration and keeps track of the current depth + self._basis_by_depth = [dict(self._basis)] + # The basis is given as a list of indices corresponding to basis vectors in self._basis + self._weight_space_bases = {self._simple.highest_weight(): [self.one()]} + + def _an_element_(self): + r""" + Return an element of ``self``. + + The only element we can quickly guarantee is in ``self`` is 1, + so we return this. + + EXAMPLES:: + + sage: g = LieAlgebra(QQ, cartan_type=['E', 6]) + sage: La = g.cartan_type().root_system().weight_lattice().fundamental_weights() + sage: I = g.simple_module(2*La[1]+La[2]).indices() + sage: I._an_element_() + 1 + """ + return self.one() + + def _weight_max_depth(self, mu): + r""" + Return the maximum depth of the weight ``mu``. + + EXAMPLES:: + + sage: g = LieAlgebra(QQ, cartan_type=['E', 6]) + sage: P = g.cartan_type().root_system().weight_lattice() + sage: La = P.fundamental_weights() + sage: al = P.simple_roots() + sage: wt = 2*La[1] + La[2] + sage: I = g.simple_module(wt).indices() + sage: I._weight_max_depth(wt) + 0 + sage: I._weight_max_depth(wt + al[2]) is None + True + sage: I._weight_max_depth(wt - 2*al[2] - 5*al[4] - 3*al[6]) + 10 + + sage: g = LieAlgebra(QQ, cartan_type=['F', 4]) + sage: P = g.cartan_type().root_system().weight_space() + sage: La = P.fundamental_weights() + sage: al = P.simple_roots() + sage: wt = 2*La[1] - 3/2*La[2] + sage: I = g.simple_module(wt).indices() + sage: I._weight_max_depth(wt) + 0 + sage: I._weight_max_depth(wt + al[2]) is None + True + sage: I._weight_max_depth(wt - 2*al[2] - 3*al[4]) + 5 + sage: I._weight_max_depth(wt - 2/3*al[1]) is None + True + """ + al = (self._simple.highest_weight() - mu)._to_root_vector() + if any(c not in ZZ or c < 0 for c in al): + return None + return sum(al) + + def weight_space_basis(self, mu): + r""" + Return the indices of the ``mu`` weight space basis elements. + + EXAMPLES:: + + sage: g = LieAlgebra(QQ, cartan_type=['A', 2]) + sage: P = g.cartan_type().root_system().weight_lattice() + sage: La = P.fundamental_weights() + sage: al = P.simple_roots() + sage: wt = -3*La[1] + 3*La[2] + sage: I = g.simple_module(wt).indices() + sage: I.weight_space_basis(wt) + [1] + sage: I.weight_space_basis(wt - al[1]) + [f[-alpha[1]]] + sage: I.weight_space_basis(wt - al[2]) + [f[-alpha[2]]] + sage: I.weight_space_basis(wt - al[1] - al[2]) + [f[-alpha[1] - alpha[2]], f[-alpha[2]]*f[-alpha[1]]] + sage: I.weight_space_basis(wt - 4*al[1]) + [f[-alpha[1]]^4] + sage: I.weight_space_basis(wt - 4*al[2]) + [] + """ + if self._reached_max_depth: + return self._weight_space_bases.get(mu, []) + + max_depth = self._weight_max_depth(mu) + while max_depth >= len(self._basis_by_depth): + if self._reached_max_depth: # we've already reached everything + break + self._construct_next_level() + return self._weight_space_bases.get(mu, []) + + def __contains__(self, m): + r""" + Check if ``m`` is contained in ``self``. + + EXAMPLES:: + + sage: g = LieAlgebra(QQ, cartan_type=['G', 2]) + sage: La = g.cartan_type().root_system().weight_lattice().fundamental_weights() + sage: L = g.simple_module(La[1]) + sage: I = L.indices() + sage: I.one() in I + True + sage: it = iter(I) + sage: for _ in range(3): + ....: elt = next(it) + ....: print(elt, elt in I) + 1 True + f[-alpha[1]] True + f[-alpha[1] - alpha[2]] True + sage: gens = list(I.gens()); gens + [f[-alpha[2]], + f[-alpha[1]], + f[-alpha[1] - alpha[2]], + f[-2*alpha[1] - alpha[2]], + f[-3*alpha[1] - alpha[2]], + f[-3*alpha[1] - 2*alpha[2]]] + sage: gens[1] in I + True + sage: gens[0] * gens[1] in I + False + sage: gens[2] in I + True + sage: gens[0]^10 in I + False + sage: gens[5]^6 * gens[2]^10 in I + False + """ + if not isinstance(m, self.Element) or m.parent() is not self: + return False + depth = m.length() + while depth >= len(self._basis_by_depth): + if self._reached_max_depth: # we've already reached everything + break + self._construct_next_level() + return m in self._basis + + def __iter__(self): + r""" + Iterate over ``self``. + + EXAMPLES:: + + sage: g = LieAlgebra(QQ, cartan_type=['B', 2]) + sage: La = g.cartan_type().root_system().weight_lattice().fundamental_weights() + sage: L = g.simple_module(La[2]) + sage: I = L.indices() + sage: list(I) + [1, f[-alpha[2]], f[-alpha[1] - alpha[2]], f[-alpha[1] - 2*alpha[2]]] + + sage: L = g.simple_module(La[1]-La[2]) + sage: I = L.indices() + sage: it = iter(I) + sage: [next(it) for _ in range(6)] + [1, f[-alpha[2]], f[-alpha[1]], f[-alpha[1] - alpha[2]], + f[-alpha[1] - 2*alpha[2]], f[-alpha[2]]^2] + """ + depth = 0 + while True: + while depth >= len(self._basis_by_depth): + if self._reached_max_depth: # we've already reached everything + return + self._construct_next_level() + yield from self._basis_by_depth[depth] + depth += 1 + + def _construct_next_level(self): + r""" + Construct the image for the next level of ``self``. + + ALGORITHM: + + For each image vector of `f_{\beta_1}^{b_1} \cdots f_{\beta_k}^{b_k} + v_{\lambda}` at the current depth `b_1 + \cdots b_k`, consider the + image under multiplication by every generator `f_{\alpha}` for + all `\alpha \leq \beta_1` in the fixed PBW ordering of the (dual) + Verma module. + + .. TODO:: + + Avoid unnecessary computations by using the corresponding + (combinastorial) crystal. + + EXAMPLES:: + + sage: g = LieAlgebra(QQ, cartan_type=['C', 3]) + sage: La = g.cartan_type().root_system().weight_lattice().fundamental_weights() + sage: L = g.simple_module(La[1]) + sage: I = L.indices() + sage: len(I._basis) + 1 + sage: I._construct_next_level() + sage: len(I._basis) + 6 + sage: I._reached_max_depth + False + sage: I._construct_next_level() # long time + sage: len(I._basis) # long time + 6 + sage: I._reached_max_depth # long time + True + sage: I._construct_next_level() # long time + """ + if self._reached_max_depth: # we've already reached everything + return # so nothing more to do + + gens = self._g.basis() + next_level = {} + R = self._g.base_ring() + ambient = self._simple._ambient + pbw = ambient._pbw + for m, vec in self._basis_by_depth[-1].items(): + # find the first support index + ind = len(self._sorted_supp) + for i, ls in enumerate(self._sorted_supp): + if ls in m._monomial: + ind = i + 1 + break + + for ls in self._sorted_supp[:ind]: + mp = dict(m._monomial) # make a (shallow) copy + mp[ls] = mp.get(ls, 0) + 1 + key = self.element_class(self, mp) + new_vec = gens[ls] * vec + if not new_vec: + continue + # Echelonize the corresponding weight space + mu = ambient.degree_on_basis(key) + if mu not in self._weight_space_bases: + # the only vector in the weight space + self._weight_space_bases[mu] = [key] + next_level[key] = new_vec + self._basis[key] = next_level[key] + lead_supp = next_level[key].trailing_support(key=pbw._monomial_key) + self._lead_supp_to_index[lead_supp] = key + continue + + supp = set() + wt_basis = [self._basis[k] for k in self._weight_space_bases[mu]] + wt_basis.append(new_vec) + for b in wt_basis: + supp.update(b.support()) + supp = sorted(supp, key=pbw._monomial_key) + mat = matrix(R, [[b[s] for s in supp] for b in wt_basis]) + mat.echelonize() + for i, k in enumerate(self._weight_space_bases[mu]): + data = {supp[ind]: R(c) for ind, c in mat[i].iteritems() if c} + self._basis[k] = ambient.element_class(ambient, data) + i = mat.nrows() - 1 + data = {supp[ind]: R(c) for ind, c in mat[i].iteritems() if c} + if data: + next_level[key] = ambient.element_class(ambient, data) + self._basis[key] = next_level[key] + lead_supp = next_level[key].trailing_support(key=pbw._monomial_key) + self._lead_supp_to_index[lead_supp] = key + self._weight_space_bases[mu].append(key) + + if not next_level: + self._reached_max_depth = True + return + self._basis_by_depth.append(next_level) + + @cached_method + def cardinality(self): + r""" + Return the cardinality of ``self``. + + EXAMPLES:: + + sage: g = LieAlgebra(QQ, cartan_type=['E', 6]) + sage: La = g.cartan_type().root_system().weight_lattice().fundamental_weights() + sage: L = g.simple_module(La[1]+La[4]) + sage: L._indices.cardinality() + 51975 + """ + if self._simple._dom_int: + weight = self._simple.highest_weight() + Phi = self._g.cartan_type().root_system() + P = Phi.weight_lattice() + coroots = Phi.root_lattice().simple_coroots() + la = P._from_dict({i: weight.scalar(ac) for i, ac in coroots.items()}) + from sage.combinat.crystals.monomial_crystals import CrystalOfNakajimaMonomials + return CrystalOfNakajimaMonomials(la).cardinality() + from sage.rings.infinity import infinity + return infinity + + +class SimpleModule(ModulePrinting, CombinatorialFreeModule): r""" Return the simple module `L_{\lambda}` as the image of the natural morphism `\phi \colom M_{\lambda} \to M_{\lambda}^{\vee}`. """ + def __init__(self, g, weight, prefix='f', basis_key=None, **kwds): + r""" + Initialize ``self``. + + EXAMPLES:: + + sage: g = LieAlgebra(QQ, cartan_type=['G', 2]) + sage: La = g.cartan_type().root_system().weight_lattice().fundamental_weights() + sage: L = g.simple_module(La[1]+La[2]) + sage: TestSuite(L).run() + + sage: g = LieAlgebra(QQ, cartan_type=['A', 2]) + sage: La = g.cartan_type().root_system().weight_lattice().fundamental_weights() + sage: L = g.simple_module(La[1]-La[2]) + sage: TestSuite(L).run() + """ + self._g = g + self._weight = weight + coroots = g.cartan_type().root_system().root_lattice().simple_coroots() + self._dom_int = weight.is_dominant_weight() + self._verma = g.verma_module(weight, basis_key=basis_key) + self._ambient = self._verma.dual() + self._pbw = self._verma.pbw_basis() + base_ring = self._g.base_ring() + indices = SimpleModuleIndices(self, prefix=prefix, **kwds) + category = self._ambient.category().Subobjects() + if self._dom_int: + category = category.FiniteDimensional() + ModulePrinting.__init__(self, 'u') + CombinatorialFreeModule.__init__(self, base_ring, indices, category=category, + **self._ambient.print_options()) + + def _repr_(self): + r""" + Return a string representation of ``self``. + + EXAMPLES:: + + sage: g = LieAlgebra(QQ, cartan_type=['A', 1]) + sage: La = g.cartan_type().root_system().weight_lattice().fundamental_weights() + sage: g.simple_module(2*La[1]) + Simple module with highest weight 2*Lambda[1] of + Lie algebra of ['A', 1] in the Chevalley basis + """ + return "Simple module with highest weight {} of {}".format(self._weight, self._g) + + def _latex_(self): + r""" + Return a latex representation of ``self``. + + EXAMPLES:: + + sage: g = LieAlgebra(QQ, cartan_type=['A', 1]) + sage: La = g.cartan_type().root_system().weight_lattice().fundamental_weights() + sage: L = g.simple_module(2*La[1]) + sage: latex(L) + L_{2 \Lambda_{1}} + """ + from sage.misc.latex import latex + return "L_{{{}}}".format(latex(self._weight)) + + def ambient(self): + r""" + Return the ambient module of ``self``. + + EXAMPLES:: + + sage: g = LieAlgebra(QQ, cartan_type=['G', 2]) + sage: La = g.cartan_type().root_system().weight_lattice().fundamental_weights() + sage: L = g.simple_module(2*La[1]) + sage: L.ambient() + BGG Dual of Verma module with highest weight 2*Lambda[1] of + Lie algebra of ['G', 2] in the Chevalley basis + """ + return self._ambient + + @lazy_attribute + def lift(self): + r""" + Return the lift map of ``self`` to the ambient dual Verma module. + + EXAMPLES:: + + sage: g = LieAlgebra(QQ, cartan_type=['G', 2]) + sage: La = g.cartan_type().root_system().weight_lattice().fundamental_weights() + sage: L = g.simple_module(La[1]) + sage: [L.lift(b) for b in L.basis()] # long time + [v[Lambda[1]]^*, + f[-alpha[1]]*v[Lambda[1]]^*, + f[-alpha[2]]*f[-alpha[1]]*v[Lambda[1]]^* - f[-alpha[1] - alpha[2]]*v[Lambda[1]]^*, + f[-alpha[1]]*f[-alpha[1] - alpha[2]]*v[Lambda[1]]^* + + f[-2*alpha[1] - alpha[2]]*v[Lambda[1]]^*, + f[-alpha[1]]^2*f[-alpha[1] - alpha[2]]*v[Lambda[1]]^* + + f[-alpha[1]]*f[-2*alpha[1] - alpha[2]]*v[Lambda[1]]^* + + 1/2*f[-3*alpha[1] - alpha[2]]*v[Lambda[1]]^*, + f[-alpha[2]]*f[-alpha[1]]^2*f[-alpha[1] - alpha[2]]*v[Lambda[1]]^* + + f[-alpha[2]]*f[-alpha[1]]*f[-2*alpha[1] - alpha[2]]*v[Lambda[1]]^* + + 1/2*f[-alpha[2]]*f[-3*alpha[1] - alpha[2]]*v[Lambda[1]]^* + - f[-alpha[1] - alpha[2]]*f[-2*alpha[1] - alpha[2]]*v[Lambda[1]]^* + + 1/2*f[-3*alpha[1] - 2*alpha[2]]*v[Lambda[1]]^*, + f[-alpha[1]]*f[-alpha[1] - alpha[2]]*f[-2*alpha[1] - alpha[2]]*v[Lambda[1]]^* + - 1/2*f[-alpha[1]]*f[-3*alpha[1] - 2*alpha[2]]*v[Lambda[1]]^* + - 1/2*f[-alpha[1] - alpha[2]]*f[-3*alpha[1] - alpha[2]]*v[Lambda[1]]^* + + f[-2*alpha[1] - alpha[2]]^2*v[Lambda[1]]^*] + """ + return self.module_morphism(self._lift_on_basis, codomain=self._ambient, unitriangular="upper") + + def retract(self, x): + r""" + Return the retraction of ``x`` in ``self``. + + EXAMPLES:: + + sage: g = LieAlgebra(QQ, cartan_type=['A', 2]) + sage: La = g.cartan_type().root_system().weight_lattice().fundamental_weights() + sage: L = g.simple_module(2*La[1]) + sage: L.retract(L.lift(sum(L.basis()))) + f[-alpha[1]]^2*u[2*Lambda[1]] + f[-alpha[1]]*f[-alpha[1] - alpha[2]]*u[2*Lambda[1]] + + f[-alpha[1] - alpha[2]]^2*u[2*Lambda[1]] + f[-alpha[1]]*u[2*Lambda[1]] + + f[-alpha[1] - alpha[2]]*u[2*Lambda[1]] + u[2*Lambda[1]] + sage: B = list(L.basis()) + sage: L.retract(3/2*L.lift(B[0]) - L.lift(B[2]) - 10/3*L.lift(B[3])) + -10/3*f[-alpha[1]]^2*u[2*Lambda[1]] + - f[-alpha[1] - alpha[2]]*u[2*Lambda[1]] + + 3/2*u[2*Lambda[1]] + """ + supp = sorted(x.support(), key=self._pbw._monomial_key) + data = x.monomial_coefficients(copy=True) # this is destructive to data + R = self.base_ring() + ret = {} + wt_space_bases = self._indices._weight_space_bases + for ls in supp: + if ls not in data: + continue + if ls not in self._indices._lead_supp_to_index: + mu = self._ambient.degree_on_basis(ls) + # this will guarantee the computation is correct + self._indices.weight_space_basis(mu) + if ls not in self._indices._lead_supp_to_index: + raise ValueError(f"not an element of the simple module of weight {self._weight}") + key = self._indices._lead_supp_to_index[ls] + vec = self._indices._basis[key] + coeff = R(data[ls] / vec[ls]) + iaxpy(-coeff, vec._monomial_coefficients, data) + ret[key] = coeff + return self.element_class(self, ret) + + def _lift_on_basis(self, m): + r""" + Return the lift of the basis element indexed by ``m``. + + EXAMPLES:: + + sage: g = LieAlgebra(QQ, cartan_type=['A', 1]) + sage: La = g.cartan_type().root_system().weight_lattice().fundamental_weights() + sage: L = g.simple_module(2*La[1]) + sage: I = L.indices() + sage: gen = list(I.gens())[0] + sage: L._lift_on_basis(gen^2) + 4*f[-alpha[1]]^2*v[2*Lambda[1]]^* + sage: L._lift_on_basis(gen^3) + Traceback (most recent call last): + ... + ValueError: f[-alpha[1]]^3 does not index a basis element + """ + # This builds the result up to the necessary depth + if m not in self._indices: + raise ValueError(f"{m} does not index a basis element") + return self._indices._basis[m] + + def dual(self): + r""" + Return the dual module of ``self``, which is ``self`` since simple + modules are self-dual. + + EXAMPLES:: + + sage: g = LieAlgebra(QQ, cartan_type=['B', 4]) + sage: La = g.cartan_type().root_system().weight_lattice().fundamental_weights() + sage: L = g.simple_module(2*La[1]+3*La[4]) + sage: L.dual() is L + True + """ + return self + + def highest_weight(self): + r""" + Return the highest weight of ``self``. + + EXAMPLES:: + + sage: g = lie_algebras.so(QQ, 7) + sage: La = g.cartan_type().root_system().weight_lattice().fundamental_weights() + sage: L = g.simple_module(La[1] + La[2]) + sage: L.highest_weight() + Lambda[1] + Lambda[2] + """ + return self._weight + + @cached_method + def highest_weight_vector(self): + r""" + Return the highest weight vector of ``self``. + + EXAMPLES:: + + sage: g = lie_algebras.sp(QQ, 6) + sage: La = g.cartan_type().root_system().weight_lattice().fundamental_weights() + sage: L = g.simple_module(La[1] + La[2]) + sage: L.highest_weight_vector() + u[Lambda[1] + Lambda[2]] + """ + one = self.base_ring().one() + return self._from_dict({self._indices.one(): one}, + remove_zeros=False, coerce=False) + + def lie_algebra(self): + r""" + Return the underlying Lie algebra of ``self``. + + EXAMPLES:: + + sage: g = lie_algebras.so(QQ, 9) + sage: La = g.cartan_type().root_system().weight_space().fundamental_weights() + sage: L = g.simple_module(La[3] - 1/2*La[1]) + sage: L.lie_algebra() + Lie algebra of ['B', 4] in the Chevalley basis + """ + return self._g + + def pbw_basis(self): + r""" + Return the PBW basis of the underlying Lie algebra + used to define ``self``. + + EXAMPLES:: + + sage: g = lie_algebras.so(QQ, 8) + sage: La = g.cartan_type().root_system().weight_lattice().fundamental_weights() + sage: L = g.simple_module(La[2] - 2*La[3]) + sage: L.pbw_basis() + Universal enveloping algebra of Lie algebra of ['D', 4] in the Chevalley basis + in the Poincare-Birkhoff-Witt basis + """ + return self._pbw + + def homogeneous_component_basis(self, mu): + r""" + Return a basis for the ``mu`` weight space of ``self``. + + EXAMPLES:: + + sage: g = LieAlgebra(QQ, cartan_type=['A', 2]) + sage: P = g.cartan_type().root_system().weight_lattice() + sage: La = P.fundamental_weights() + sage: la = La[1]+La[2] + sage: L = g.simple_module(la) + sage: from itertools import product + sage: al = P.simple_roots() + sage: for wts in product(range(4), repeat=2): + ....: mu = la - wts[0] * al[1] - wts[1] * al[2] + ....: print(mu) + ....: print(L.homogeneous_component_basis(mu)) + Lambda[1] + Lambda[2] + Family (u[Lambda[1] + Lambda[2]],) + 2*Lambda[1] - Lambda[2] + Family (f[-alpha[2]]*u[Lambda[1] + Lambda[2]],) + 3*Lambda[1] - 3*Lambda[2] + Family () + 4*Lambda[1] - 5*Lambda[2] + Family () + -Lambda[1] + 2*Lambda[2] + Family (f[-alpha[1]]*u[Lambda[1] + Lambda[2]],) + 0 + Family (f[-alpha[1] - alpha[2]]*u[Lambda[1] + Lambda[2]], f[-alpha[2]]*f[-alpha[1]]*u[Lambda[1] + Lambda[2]]) + Lambda[1] - 2*Lambda[2] + Family (f[-alpha[2]]*f[-alpha[1] - alpha[2]]*u[Lambda[1] + Lambda[2]],) + 2*Lambda[1] - 4*Lambda[2] + Family () + -3*Lambda[1] + 3*Lambda[2] + Family () + -2*Lambda[1] + Lambda[2] + Family (f[-alpha[1]]*f[-alpha[1] - alpha[2]]*u[Lambda[1] + Lambda[2]],) + -Lambda[1] - Lambda[2] + Family (f[-alpha[1] - alpha[2]]^2*u[Lambda[1] + Lambda[2]],) + -3*Lambda[2] + Family () + -5*Lambda[1] + 4*Lambda[2] + Family () + -4*Lambda[1] + 2*Lambda[2] + Family () + -3*Lambda[1] + Family () + -2*Lambda[1] - 2*Lambda[2] + Family () + """ + return Family([self.monomial(b) for b in self._indices.weight_space_basis(mu)]) + + weight_space_basis = homogeneous_component_basis + + class Element(CombinatorialFreeModule.Element): + def _acted_upon_(self, scalar, self_on_left=True): + r""" + Return the action of ``scalar`` on ``self``. + + EXAMPLES:: + + sage: g = LieAlgebra(QQ, cartan_type=['A', 2]) + sage: La = g.cartan_type().root_system().weight_lattice().fundamental_weights() + sage: L = g.simple_module(La[1]+La[2]) + sage: v = L.highest_weight_vector(); v + u[Lambda[1] + Lambda[2]] + sage: f1, f2 = g.pbw_basis().f() + sage: 5 * v + 5*u[Lambda[1] + Lambda[2]] + sage: f1 * f2 * v + f[-alpha[2]]*f[-alpha[1]]*u[Lambda[1] + Lambda[2]] + + f[-alpha[1] - alpha[2]]*u[Lambda[1] + Lambda[2]] + sage: f2 * f1 * v + -f[-alpha[2]]*f[-alpha[1]]*u[Lambda[1] + Lambda[2]] + + 2*f[-alpha[1] - alpha[2]]*u[Lambda[1] + Lambda[2]] + sage: f2 * f2 * f1 * v + -2*f[-alpha[2]]*f[-alpha[1] - alpha[2]]*u[Lambda[1] + Lambda[2]] + sage: f1 * f2 * f1 * v + f[-alpha[1]]*f[-alpha[1] - alpha[2]]*u[Lambda[1] + Lambda[2]] + sage: f2 * f1 * f2 * f1 * v + f[-alpha[1] - alpha[2]]^2*u[Lambda[1] + Lambda[2]] + sage: f1 * f2 * f2 * f1 * v + 2*f[-alpha[1] - alpha[2]]^2*u[Lambda[1] + Lambda[2]] + """ + # check for scalars first + ret = CombinatorialFreeModule.Element._acted_upon_(self, scalar, self_on_left) + if ret is not None: + return ret + + if self_on_left: # this is a left module action + return None + + P = self.parent() + return P.retract(scalar * P.lift(self)) + + _lmul_ = _acted_upon_ + _rmul_ = _acted_upon_ diff --git a/src/sage/algebras/lie_algebras/verma_module.py b/src/sage/algebras/lie_algebras/verma_module.py index 057a32328da..ede30deeaae 100644 --- a/src/sage/algebras/lie_algebras/verma_module.py +++ b/src/sage/algebras/lie_algebras/verma_module.py @@ -35,7 +35,80 @@ from sage.rings.rational_field import QQ -class VermaModule(CombinatorialFreeModule): +class ModulePrinting(object): + """ + Helper mixin class for printing the module vectors. + """ + def __init__(self, vector_name='v'): + r""" + Initialize ``self``. + + EXAMPLES:: + + sage: from sage.algebras.lie_algebras.verma_module import ModulePrinting + sage: MP = ModulePrinting() + sage: TestSuite(MP).run() + """ + self.__vector_name = vector_name + + def _repr_generator(self, m): + r""" + Return a string representation of the generator indexed by ``m``. + + EXAMPLES:: + + sage: L = lie_algebras.sp(QQ, 4) + sage: La = L.cartan_type().root_system().ambient_space().fundamental_weights() + sage: M = L.verma_module(-1/2*La[1] + 3/7*La[2]) + sage: f1, f2 = L.f() + sage: x = M.pbw_basis()(L([f1, [f1, f2]])) + sage: v = x * M.highest_weight_vector() + sage: M._repr_generator(v.leading_support()) + 'f[-2*alpha[1] - alpha[2]]*v[(-1/14, 3/7)]' + + sage: M.highest_weight_vector() + v[(-1/14, 3/7)] + sage: 2 * M.highest_weight_vector() + 2*v[(-1/14, 3/7)] + """ + ret = super()._repr_generator(m) + if ret == '1': + ret = '' + else: + ret += '*' + return ret + self.__vector_name + "[{}]".format(self._weight) + + def _latex_generator(self, m): + r""" + Return a latex representation of the generator indexed by ``m``. + + EXAMPLES:: + + sage: L = lie_algebras.sp(QQ, 4) + sage: La = L.cartan_type().root_system().ambient_space().fundamental_weights() + sage: M = L.verma_module(-1/2*La[1] + 3/7*La[2]) + sage: f1, f2 = L.f() + sage: x = M.pbw_basis()(L([f1, [f1, f2]])) + sage: v = x * M.highest_weight_vector() + sage: M._latex_generator(v.leading_support()) + f_{-2 \alpha_{1} - \alpha_{2}} v_{-\frac{1}{14} e_{0} + \frac{3}{7} e_{1}} + + sage: latex(2 * M.highest_weight_vector()) + 2 v_{-\frac{1}{14} e_{0} + \frac{3}{7} e_{1}} + sage: latex(M.highest_weight_vector()) + v_{-\frac{1}{14} e_{0} + \frac{3}{7} e_{1}} + """ + ret = super()._latex_generator(m) + if ret == '1': + ret = '' + from sage.misc.latex import latex + return ret + " {}_{{{}}}".format(self.__vector_name, latex(self._weight)) + + _repr_term = _repr_generator + _latex_term = _latex_generator + + +class VermaModule(ModulePrinting, CombinatorialFreeModule): r""" A Verma module. @@ -118,6 +191,7 @@ def __init__(self, g, weight, basis_key=None, prefix='f', **kwds): prefix='', bracket=False, latex_bracket=False, sorting_key=self._monomial_key, category=Modules(R).WithBasis().Graded()) + ModulePrinting.__init__(self) def _triangular_key(self, x): r""" @@ -233,64 +307,8 @@ def _latex_(self): from sage.misc.latex import latex return "M_{{{}}}".format(latex(self._weight)) - def _repr_generator(self, m): - r""" - Return a string representation of the generator indexed by ``m``. - - EXAMPLES:: - - sage: L = lie_algebras.sp(QQ, 4) - sage: La = L.cartan_type().root_system().ambient_space().fundamental_weights() - sage: M = L.verma_module(-1/2*La[1] + 3/7*La[2]) - sage: f1, f2 = L.f() - sage: x = M.pbw_basis()(L([f1, [f1, f2]])) - sage: v = x * M.highest_weight_vector() - sage: M._repr_generator(v.leading_support()) - 'f[-2*alpha[1] - alpha[2]]*v[(-1/14, 3/7)]' - - sage: M.highest_weight_vector() - v[(-1/14, 3/7)] - sage: 2 * M.highest_weight_vector() - 2*v[(-1/14, 3/7)] - """ - ret = super()._repr_generator(m) - if ret == '1': - ret = '' - else: - ret += '*' - return ret + "v[{}]".format(self._weight) - - def _latex_generator(self, m): - r""" - Return a latex representation of the generator indexed by ``m``. - - EXAMPLES:: - - sage: L = lie_algebras.sp(QQ, 4) - sage: La = L.cartan_type().root_system().ambient_space().fundamental_weights() - sage: M = L.verma_module(-1/2*La[1] + 3/7*La[2]) - sage: f1, f2 = L.f() - sage: x = M.pbw_basis()(L([f1, [f1, f2]])) - sage: v = x * M.highest_weight_vector() - sage: M._latex_generator(v.leading_support()) - f_{-2 \alpha_{1} - \alpha_{2}} v_{-\frac{1}{14} e_{0} + \frac{3}{7} e_{1}} - - sage: latex(2 * M.highest_weight_vector()) - 2 v_{-\frac{1}{14} e_{0} + \frac{3}{7} e_{1}} - sage: latex(M.highest_weight_vector()) - v_{-\frac{1}{14} e_{0} + \frac{3}{7} e_{1}} - """ - ret = super()._latex_generator(m) - if ret == '1': - ret = '' - from sage.misc.latex import latex - return ret + " v_{{{}}}".format(latex(self._weight)) - - _repr_term = _repr_generator - _latex_term = _latex_generator - def lie_algebra(self): - """ + r""" Return the underlying Lie algebra of ``self``. EXAMPLES:: @@ -304,7 +322,7 @@ def lie_algebra(self): return self._g def pbw_basis(self): - """ + r""" Return the PBW basis of the underlying Lie algebra used to define ``self``. @@ -376,7 +394,13 @@ def dual(self): sage: La = L.cartan_type().root_system().weight_space().fundamental_weights() sage: M = L.verma_module(2*La[1]) sage: Mc = M.dual() + + sage: Mp = L.verma_module(-2*La[1]) + sage: Mp.dual() is Mp + True """ + if self.is_simple(): + return self from sage.algebras.lie_algebras.bgg_dual_module import BGGDualModule return BGGDualModule(self) @@ -565,44 +589,60 @@ def is_simple(self): Return if ``self`` is a simple module. A Verma module `M_{\lambda}` is simple if and only if `\lambda` - is *antidominant* in the sense + is *Verma antidominant* in the sense .. MATH:: \langle \lambda + \rho, \alpha^{\vee} \rangle \notin \ZZ_{>0} for all positive roots `\alpha`. + + EXAMPLES:: + + sage: L = lie_algebras.sl(QQ, 3) + sage: La = L.cartan_type().root_system().weight_space().fundamental_weights() + sage: L.verma_module(La[1] + La[2]).is_simple() + False + sage: L.verma_module(-La[1] - La[2]).is_simple() + True + sage: L.verma_module(3/2*La[1] + 1/2*La[2]).is_simple() + False + sage: L.verma_module(3/2*La[1] + 1/3*La[2]).is_simple() + True + sage: L.verma_module(-3*La[1] + 2/3*La[2]).is_simple() + True """ - pos_roots = self._g._cartan_type.root_system().root_lattice().positive_roots() - wt = self._weight + self._weight.parent().rho() - for rt in pos_roots: - val = wt.scalar(rt.associated_coroot()) - if val in ZZ and val > 0: - return False - return True + return self._weight.is_verma_dominant(positive=False) def is_projective(self): r""" Return if ``self`` is a projective module in Category `\mathcal{O}`. A Verma module `M_{\lambda}` is projective (in Category `\mathcal{O}` - if and only if `\lambda` is *dominant* in the sense + if and only if `\lambda` is *Verma dominant* in the sense .. MATH:: \langle \lambda + \rho, \alpha^{\vee} \rangle \notin \ZZ_{<0} for all positive roots `\alpha`. + + EXAMPLES:: + + sage: L = lie_algebras.sl(QQ, 3) + sage: La = L.cartan_type().root_system().weight_space().fundamental_weights() + sage: L.verma_module(La[1] + La[2]).is_projective() + True + sage: L.verma_module(-La[1] - La[2]).is_projective() + True + sage: L.verma_module(3/2*La[1] + 1/2*La[2]).is_projective() + True + sage: L.verma_module(3/2*La[1] + 1/3*La[2]).is_projective() + True + sage: L.verma_module(-3*La[1] + 2/3*La[2]).is_projective() + False """ - Q = self._g._cartan_type.root_system().root_lattice() - pos_roots = Q.positive_roots() - wt = self._weight + self._weight.parent().rho() - is_dominant = True - for rt in pos_roots: - val = wt.scalar(rt.associated_coroot()) - if val in ZZ and val < 0: - return False - return True + return self._weight.is_verma_dominant() def homogeneous_component_basis(self, d): r""" @@ -627,11 +667,13 @@ def homogeneous_component_basis(self, d): sage: M.homogeneous_component_basis(mu - La[1]) Family () """ - diff = _convert_wt_to_root(d - self._weight) + diff = (d - self._weight)._to_root_vector() if diff is None or not all(coeff <= 0 and coeff in ZZ for coeff in diff): return Family([]) return sorted(self._homogeneous_component_f(diff)) + weight_space_basis = homogeneous_component_basis + @cached_method def _homogeneous_component_f(self, d): r""" @@ -704,8 +746,8 @@ def _Hom_(self, Y, category=None, **options): sage: type(H) <...VermaModuleHomset_with_category_with_equality_by_id'> """ - from sage.algebras.lie_algebras.bgg_dual_module import BGGDualModule - if not ((isinstance(Y, VermaModule) + from sage.algebras.lie_algebras.bgg_dual_module import BGGDualModule, SimpleModule + if not ((isinstance(Y, (VermaModule, SimpleModule)) or (isinstance(Y, BGGDualModule) and Y._module is self)) and self._g is Y.lie_algebra()): raise TypeError("{} must be an object in Category O of {}".format(Y, self._g)) @@ -743,6 +785,7 @@ def _acted_upon_(self, scalar, self_on_left=False): """ P = self.parent() # Check for scalars first + # TODO: Pass by these checks if a PBW basis element of the Lie algebra if scalar in P.base_ring(): # Don't have this be a super call return CombinatorialFreeModule.Element._acted_upon_(self, scalar, self_on_left) @@ -1107,6 +1150,46 @@ def is_surjective(self): return False + def image(self): + r""" + Return the image of ``self``. + + EXAMPLES:: + + sage: g = LieAlgebra(QQ, cartan_type=['B', 2]) + sage: La = g.cartan_type().root_system().weight_lattice().fundamental_weights() + sage: M = g.verma_module(La[1]+2*La[2]) + sage: Mp = g.verma_module(La[1]+3*La[2]) + sage: phi = Hom(M, Mp).natural_map() + sage: phi.image() + Free module generated by {} over Rational Field + sage: Mc = M.dual() + sage: phi = Hom(M, Mc).natural_map() + sage: L = phi.image(); L + Simple module with highest weight Lambda[1] + 2*Lambda[2] of + Lie algebra of ['B', 2] in the Chevalley basis + sage: psi = Hom(M, L).natural_map() + sage: psi.image() + Simple module with highest weight Lambda[1] + 2*Lambda[2] of + Lie algebra of ['B', 2] in the Chevalley basis + """ + C = self.codomain() + if not bool(self._scalar): + return C.submodule([]) + + if isinstance(C, VermaModule): + if self.domain() == C: + return C + raise NotImplementedError("submodules of Verma modules not yet implemented") + + from sage.algebras.lie_algebras.bgg_dual_module import BGGDualModule, SimpleModule + if isinstance(C, BGGDualModule) and isinstance(C._module, VermaModule): + return SimpleModule(C.lie_algebra(), C.highest_weight(), prefix=C._indices.prefix(), + basis_key=C._module._basis_key) + + if isinstance(self.codomain(), SimpleModule): + return self.codomain() + class VermaModuleHomset(Homset): @@ -1214,6 +1297,20 @@ def highest_weight_image(self): r""" Return the image of the highest weight vector of the domain in the codomain. + + EXAMPLES:: + + sage: g = LieAlgebra(QQ, cartan_type=['C', 3]) + sage: La = g.cartan_type().root_system().weight_lattice().fundamental_weights() + sage: M = g.verma_module(La[1]+2*La[3]) + sage: Mc = M.dual() + sage: H = Hom(M, Mc) + sage: H.highest_weight_image() + v[Lambda[1] + 2*Lambda[3]]^* + sage: L = H.natural_map().image() + sage: Hp = Hom(M, L) + sage: Hp.highest_weight_image() + u[Lambda[1] + 2*Lambda[3]] """ C = self.codomain() if isinstance(C, VermaModule): @@ -1530,45 +1627,3 @@ def basis(self): return Family([self.natural_map()]) Element = VermaModuleMorphism - - -def _convert_wt_to_root(wt): - r""" - Helper function to express ``wt`` as a linear combination - of simple roots. - - INPUT: - - - ``wt`` -- an element of a weight lattice realization - - OUTPUT: - - A vector over `\QQ` representing ``wt`` as a linear combination - of simple roots. - - EXAMPLES:: - - sage: from sage.algebras.lie_algebras.verma_module import _convert_wt_to_root - sage: P = RootSystem(['A',3]).weight_lattice() - sage: La = P.fundamental_weights() - sage: [_convert_wt_to_root(al) for al in P.simple_roots()] - [(1, 0, 0), (0, 1, 0), (0, 0, 1)] - sage: _convert_wt_to_root(La[1] + La[2]) - (5/4, 3/2, 3/4) - - sage: L = RootSystem(['A',3]).ambient_space() - sage: e = L.basis() - sage: _convert_wt_to_root(e[0] + 3*e[3]) - sage: _convert_wt_to_root(e[0] - e[1]) - (1, 0, 0) - sage: _convert_wt_to_root(e[0] + 2*e[1] - 3*e[2]) - (1, 3, 0) - """ - v = wt.to_vector().change_ring(QQ) - al = [a.to_vector() for a in wt.parent().simple_roots()] - b = v.parent().linear_dependence([v] + al) - if len(b) != 1 or b[0] == 0: - return None - b = b[0] # Get the actual vector that gives the linear dependency - # Get v as a linear combination of the simple roots - return vector(QQ, [-x / b[0] for x in b[1:]]) diff --git a/src/sage/categories/coxeter_groups.py b/src/sage/categories/coxeter_groups.py index 3d62d98272b..a85cd275532 100644 --- a/src/sage/categories/coxeter_groups.py +++ b/src/sage/categories/coxeter_groups.py @@ -2717,7 +2717,7 @@ def bruhat_le(self, other): @cached_in_parent_method def weak_le(self, other, side='right'): - """ + r""" Perform the comparison between ``self`` and ``other`` in weak (Bruhat) order. diff --git a/src/sage/categories/triangular_kac_moody_algebras.py b/src/sage/categories/triangular_kac_moody_algebras.py index 543f97533b5..40c382c8a9b 100644 --- a/src/sage/categories/triangular_kac_moody_algebras.py +++ b/src/sage/categories/triangular_kac_moody_algebras.py @@ -256,6 +256,49 @@ def verma_module(self, la, basis_key=None, **kwds): from sage.algebras.lie_algebras.verma_module import VermaModule return VermaModule(self, la, basis_key=basis_key, **kwds) + def simple_module(self, la, basis_key=None, **kwds): + r""" + Return the simple module with highest weight ``la`` + over ``self``. + + INPUT: + + - ``la`` -- the weight + - ``basis_key`` -- (optional) a key function for the indexing + set of the basis elements of ``self`` + + OUTPUT: + + If ``la`` is :meth:`Verma antidominant + `, + then this returns the + :class:`~sage.algebras.lie_algebras.verma_module.VermaModule` + of highest weight ``la`` (which is simple and more efficient). + Otherwise this returns a + :class:`~sage.algebras.lie_algebras.bgg_dual_module.SimpleModule`. + + EXAMPLES:: + + sage: # needs sage.combinat sage.modules + sage: g = lie_algebras.sl(QQ, 3) + sage: P = g.cartan_type().root_system().weight_lattice() + sage: La = P.fundamental_weights() + sage: L = g.simple_module(La[1] + La[2]) + sage: L + Simple module with highest weight Lambda[1] + Lambda[2] + of Lie algebra of ['A', 2] in the Chevalley basis + sage: L = g.simple_module(-La[1] - La[2]) + sage: L + Verma module with highest weight -Lambda[1] - Lambda[2] + of Lie algebra of ['A', 2] in the Chevalley basis + """ + if la.is_verma_dominant(positive=False): + from sage.algebras.lie_algebras.verma_module import VermaModule + return VermaModule(self, la, basis_key=basis_key, **kwds) + + from sage.algebras.lie_algebras.bgg_dual_module import SimpleModule + return SimpleModule(self, la, basis_key=basis_key, **kwds) + class ElementMethods: def part(self): """ diff --git a/src/sage/combinat/root_system/root_lattice_realizations.py b/src/sage/combinat/root_system/root_lattice_realizations.py index 7539a5a85bb..ab63dadf135 100644 --- a/src/sage/combinat/root_system/root_lattice_realizations.py +++ b/src/sage/combinat/root_system/root_lattice_realizations.py @@ -3912,6 +3912,51 @@ def is_dominant_weight(self): # Or is_dominant_integral_weight? return all(self.inner_product(alphacheck[i]) in NN for i in self.parent().index_set()) + def is_verma_dominant(self, positive=True): + r""" + Return if ``self`` is Verma dominant. + + A weight `\lambda` is *Verma dominant* if + + .. MATH:: + + \langle \lambda + \rho, \alpha^{\vee} \rangle \notin \ZZ_{<0} + + for all positive roots `\alpha`. Note that this does *not* + imply that `\langle \lambda + \rho, \alpha^{\vee} \rangle \geq 0` + for any positive root `\alpha`. This is used to determine if + a Verma module is simple or projective. + + INPUT: + + - ``positive`` -- boolean (default: ``True``); if ``False``, then + this checks if the weight is Verma anti-dominant, where + `\ZZ_{<0}` is replaced with `\ZZ_{>0}` in the definition. + + EXAMPLES:: + + sage: P = RootSystem(['A', 3]).weight_space() + sage: La = P.fundamental_weights() + sage: (La[1] + 2*La[2]).is_verma_dominant() + True + sage: (La[1] - 3/2*La[3]).is_verma_dominant() + True + sage: (La[1] - 3/2*La[3]).is_verma_dominant(positive=False) + True + sage: (1/2*La[1] - 3/2*La[3]).is_verma_dominant() + False + sage: alphacheck = P.coroot_lattice().positive_roots() + sage: [(1/2*La[1] - 3/2*La[3]).scalar(coroot) for coroot in alphacheck] + [1/2, 0, -3/2, 1/2, -3/2, -1] + sage: (1/2*La[1] - 3/2*La[3]).is_verma_dominant(positive=False) + True + """ + alphacheck = self.parent().coroot_lattice().positive_roots() + wt = self + self.parent().rho() + if positive: + return not any((c := wt.scalar(ac)) in ZZ and c < 0 for ac in alphacheck) + return not any((c := wt.scalar(ac)) in ZZ and c > 0 for ac in alphacheck) + ########################################################################## # weak order ########################################################################## diff --git a/src/sage/combinat/root_system/weight_lattice_realizations.py b/src/sage/combinat/root_system/weight_lattice_realizations.py index 8859b2135b5..801b4da79b7 100644 --- a/src/sage/combinat/root_system/weight_lattice_realizations.py +++ b/src/sage/combinat/root_system/weight_lattice_realizations.py @@ -25,6 +25,7 @@ from sage.categories.category_types import Category_over_base_ring from sage.sets.family import Family from .root_lattice_realizations import RootLatticeRealizations +from sage.rings.rational_field import QQ class WeightLatticeRealizations(Category_over_base_ring): @@ -908,6 +909,25 @@ def weyl_dimension(self, highest_weight): d = prod((rho.scalar(x) for x in pr), Integer(1)) return Integer(n/d) + @lazy_attribute + def _inverse_cartan_matrix(self): + r""" + Return the inverse Cartan matrix defining ``self``. + + EXAMPLES:: + + sage: RootSystem(['A', 3]).ambient_lattice()._inverse_cartan_matrix + [3/4 1/2 1/4] + [1/2 1 1/2] + [1/4 1/2 3/4] + sage: RootSystem(['G', 2]).weight_lattice()._inverse_cartan_matrix + [2 3] + [1 2] + """ + ret = self.cartan_type().cartan_matrix().inverse() + ret.set_immutable() + return ret + @lazy_attribute def _symmetric_form_matrix(self): r""" @@ -960,7 +980,7 @@ def _symmetric_form_matrix(self): cm = ct.cartan_matrix() if cm.det() != 0: diag = matrix.diagonal(cm.symmetrizer()) - return cm.inverse().transpose() * diag + return self._inverse_cartan_matrix.transpose() * diag if not ct.is_affine(): raise ValueError("only implemented for affine types when the" @@ -1131,4 +1151,37 @@ def to_weight_space(self, base_ring=None): if base_ring is None: base_ring = L.base_ring() - return L.root_system.weight_space(base_ring).sum_of_terms([i, base_ring(self.scalar(L.simple_coroot(i)))] for i in L.cartan_type().index_set()) + wt_space = L.root_system.weight_space(base_ring) + simple_coroots = L.simple_coroots() + return wt_space.sum_of_terms(((i, base_ring(self.scalar(ac))) + for i, ac in simple_coroots.items()), + distinct=True) + + @cached_method + def _to_root_vector(self): + r""" + Helper method to express ``self`` as a linear combination + of simple roots. + + OUTPUT: + + A list with entries in `\QQ` representing ``self`` as a linear + combination of simple roots. + + EXAMPLES:: + + sage: L = RootSystem(['A', 3]).ambient_space() + sage: e = L.basis() + sage: (e[0] + 3*e[3])._to_root_vector() # not in the root space + sage: (e[0] - e[1])._to_root_vector() + (1, 0, 0) + sage: (e[0] + 2*e[1] - 3*e[2])._to_root_vector() + (1, 3, 0) + """ + v = self.to_vector().change_ring(QQ) + al = [a.to_vector() for a in self.parent().simple_roots()] + b = v.parent().linear_dependence([v] + al) + if len(b) != 1 or b[0] == 0: + return None + b = b[0] # Get the actual vector that gives the linear dependency + return b[1:].change_ring(QQ) / -b[0] diff --git a/src/sage/combinat/root_system/weight_space.py b/src/sage/combinat/root_system/weight_space.py index 3df5449c7bd..fc30553fdec 100644 --- a/src/sage/combinat/root_system/weight_space.py +++ b/src/sage/combinat/root_system/weight_space.py @@ -515,9 +515,9 @@ def scalar(self, lambdacheck): return sum( (self[i]*c for (i,c) in lambdacheck), zero) def is_dominant(self): - """ - Checks whether an element in the weight space lies in the positive cone spanned - by the basis elements (fundamental weights). + r""" + Checks whether an element in the weight space lies in the positive + cone spanned by the basis elements (fundamental weights). EXAMPLES:: @@ -532,7 +532,7 @@ def is_dominant(self): In the extended affine weight lattice, 'delta' is orthogonal to the positive coroots, so adding or subtracting it should not - affect dominance :: + affect dominance:: sage: P = RootSystem(['A',2,1]).weight_lattice(extended=true) sage: Lambda = P.fundamental_weights() @@ -540,9 +540,43 @@ def is_dominant(self): sage: w = Lambda[1] - delta # needs sage.graphs sage: w.is_dominant() # needs sage.graphs True + """ + index_set = set(self.parent().index_set()) + return all(c >= 0 for i, c in self._monomial_coefficients.items() if i in index_set) + + def is_dominant_weight(self): + r""" + Checks whether an element in the weight space lies in the positive + `\ZZ`-lattice cone spanned by the basis elements (fundamental weights). + + EXAMPLES:: + + sage: W = RootSystem(['A',3]).weight_space() + sage: Lambda = W.basis() + sage: w = Lambda[1] + Lambda[3] + sage: w.is_dominant_weight() + True + sage: w = Lambda[1] + 2/3*Lambda[3] + sage: w.is_dominant_weight() + False + sage: w = Lambda[1] - Lambda[2] + sage: w.is_dominant_weight() + False + + In the extended affine weight lattice, 'delta' is orthogonal to + the positive coroots, so adding or subtracting it should not + affect dominance:: + sage: P = RootSystem(['A',2,1]).weight_lattice(extended=true) + sage: Lambda = P.fundamental_weights() + sage: delta = P.null_root() # needs sage.graphs + sage: w = Lambda[1] - delta # needs sage.graphs + sage: w.is_dominant_weight() # needs sage.graphs + True """ - return all(self.coefficient(i) >= 0 for i in self.parent().index_set()) + index_set = set(self.parent().index_set()) + from sage.rings.integer_ring import ZZ + return all(c in ZZ and c >= 0 for i, c in self._monomial_coefficients.items() if i in index_set) def to_ambient(self): r""" @@ -580,5 +614,27 @@ def to_weight_space(self): """ return self + @cached_method + def _to_root_vector(self): + r""" + Helper method to express ``self`` as a linear combination + of simple roots. + + OUTPUT: + + A vector with entries in `\QQ` representing ``self`` as a linear + combination of simple roots. + + EXAMPLES:: + + sage: P = RootSystem(['A',3]).weight_lattice() + sage: La = P.fundamental_weights() + sage: [al._to_root_vector() for al in P.simple_roots()] + [(1, 0, 0), (0, 1, 0), (0, 0, 1)] + sage: (La[1] + La[2])._to_root_vector() + (5/4, 3/2, 3/4) + """ + return self.parent()._inverse_cartan_matrix * self.to_vector() + WeightSpace.Element = WeightSpaceElement diff --git a/src/sage/monoids/indexed_free_monoid.py b/src/sage/monoids/indexed_free_monoid.py index ef82ef41705..5ec7e0777eb 100644 --- a/src/sage/monoids/indexed_free_monoid.py +++ b/src/sage/monoids/indexed_free_monoid.py @@ -963,6 +963,11 @@ class IndexedFreeAbelianMonoid(IndexedMonoid): sage: F = FreeAbelianMonoid(index_set=Partitions(), prefix='A', bracket=False, scalar_mult='%') sage: F.gen([3,1,1]) * F.gen([2,2]) A[2, 2]%A[3, 1, 1] + + .. TODO:: + + Implement a subclass when the index sets is finite that utilizes + vectors or the polydict monomials with the index order is fixed. """ def _repr_(self): """ From 700ba4e951d1125312407d5b8dcb77208b21d8bc Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Sun, 11 Feb 2024 21:37:29 +0900 Subject: [PATCH 067/231] Adding BGG resolution. --- .../en/reference/algebras/lie_algebras.rst | 2 + src/doc/en/reference/references/index.rst | 4 + .../algebras/lie_algebras/bgg_dual_module.py | 51 +++- .../algebras/lie_algebras/bgg_resolution.py | 228 ++++++++++++++++++ 4 files changed, 280 insertions(+), 5 deletions(-) create mode 100644 src/sage/algebras/lie_algebras/bgg_resolution.py diff --git a/src/doc/en/reference/algebras/lie_algebras.rst b/src/doc/en/reference/algebras/lie_algebras.rst index 03f66f4da88..4fefbe909f5 100644 --- a/src/doc/en/reference/algebras/lie_algebras.rst +++ b/src/doc/en/reference/algebras/lie_algebras.rst @@ -7,6 +7,8 @@ Lie Algebras sage/algebras/lie_algebras/abelian sage/algebras/lie_algebras/affine_lie_algebra sage/algebras/lie_algebras/bch + sage/algebras/lie_algebras/bgg_resolution + sage/algebras/lie_algebras/bgg_dual_module sage/algebras/lie_algebras/center_uea sage/algebras/lie_algebras/classical_lie_algebra sage/algebras/lie_algebras/examples diff --git a/src/doc/en/reference/references/index.rst b/src/doc/en/reference/references/index.rst index 3d314f9c466..73af30fe5a8 100644 --- a/src/doc/en/reference/references/index.rst +++ b/src/doc/en/reference/references/index.rst @@ -3463,6 +3463,10 @@ REFERENCES: Trans. Am. Math. Soc. 375, No. 6, 4411-4427 (2022). :arxiv:`1906.09633`, :doi:`10.1090/tran/8606`. +.. [Humphreys08] James E. Humphreys. *Representations of Semisimple Lie + Algebras in the BGG Category* `\mathcal{O}`. + Graduate Studies in Mathematics. Amer. Math. Soc., 2008. + .. [Hutz2007] \B. Hutz. Arithmetic Dynamics on Varieties of dimension greater than one. PhD Thesis, Brown University 2007 diff --git a/src/sage/algebras/lie_algebras/bgg_dual_module.py b/src/sage/algebras/lie_algebras/bgg_dual_module.py index d7538c30018..aa3f425d592 100644 --- a/src/sage/algebras/lie_algebras/bgg_dual_module.py +++ b/src/sage/algebras/lie_algebras/bgg_dual_module.py @@ -7,7 +7,7 @@ """ #***************************************************************************** -# Copyright (C) 2023 Travis Scrimshaw +# Copyright (C) 2024 Travis Scrimshaw # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -24,7 +24,6 @@ from sage.structure.indexed_generators import IndexedGenerators from sage.monoids.indexed_free_monoid import IndexedFreeAbelianMonoid, IndexedMonoid from sage.combinat.free_module import CombinatorialFreeModule -from sage.sets.non_negative_integers import NonNegativeIntegers from sage.sets.family import Family from sage.sets.finite_enumerated_set import FiniteEnumeratedSet from sage.matrix.constructor import matrix @@ -94,6 +93,10 @@ class BGGDualModule(CombinatorialFreeModule): -6*f[-alpha[1]]^4*v[2*Lambda[1]]^*, -8*f[-alpha[1]]^5*v[2*Lambda[1]]^*, -10*f[-alpha[1]]^6*v[2*Lambda[1]]^*] + + REFERENCES: + + - [Humphreys08]_ """ def __init__(self, module): r""" @@ -424,7 +427,6 @@ def _acted_upon_(self, scalar, self_on_left=False): # This is an abuse as the monoid is not free. -# FIXME: # TODO: Rewrite this (or the indexed monoid class) to use explicit vectors # since we only want to consider ordered elements. # Note, such a rewrite would force the Lie algebra to be finite dimensional. @@ -788,6 +790,27 @@ class SimpleModule(ModulePrinting, CombinatorialFreeModule): Return the simple module `L_{\lambda}` as the image of the natural morphism `\phi \colom M_{\lambda} \to M_{\lambda}^{\vee}`. """ + @staticmethod + def __classcall_private__(cls, g, weight, *args, **kwds): + r""" + Normalize input to ensure a unique representation and return + the correct type. + + EXAMPLES:: + + sage: g = LieAlgebra(QQ, cartan_type=['E', 6]) + sage: La = g.cartan_type().root_system().weight_space().fundamental_weights() + sage: type(g.simple_module(La[1]+La[2])) + + sage: type(g.simple_module(La[1]-La[2])) + + sage: type(g.simple_module(La[1]+3/2*La[2])) + + """ + if weight.is_dominant_weight(): + return FiniteDimensionalSimpleModule(g, weight, *args, **kwds) + return super().__classcall__(cls, g, weight, *args, **kwds) + def __init__(self, g, weight, prefix='f', basis_key=None, **kwds): r""" Initialize ``self``. @@ -806,7 +829,6 @@ def __init__(self, g, weight, prefix='f', basis_key=None, **kwds): """ self._g = g self._weight = weight - coroots = g.cartan_type().root_system().root_lattice().simple_coroots() self._dom_int = weight.is_dominant_weight() self._verma = g.verma_module(weight, basis_key=basis_key) self._ambient = self._verma.dual() @@ -918,7 +940,6 @@ def retract(self, x): data = x.monomial_coefficients(copy=True) # this is destructive to data R = self.base_ring() ret = {} - wt_space_bases = self._indices._weight_space_bases for ls in supp: if ls not in data: continue @@ -1131,3 +1152,23 @@ def _acted_upon_(self, scalar, self_on_left=True): _lmul_ = _acted_upon_ _rmul_ = _acted_upon_ + +class FiniteDimensionalSimpleModule(SimpleModule): + """ + A finite dimensional simple module. + """ + def bgg_resolution(self): + """ + Return the BGG resolution of ``self``. + + EXAMPLES:: + + sage: g = LieAlgebra(QQ, cartan_type=['A', 2]) + sage: La = g.cartan_type().root_system().weight_lattice().fundamental_weights() + sage: L = g.simple_module(La[1]+La[2]) + sage: L.bgg_resolution() + BGG resolution of Simple module with highest weight Lambda[1] + Lambda[2] + of Lie algebra of ['A', 2] in the Chevalley basis + """ + from sage.algebras.lie_algebras.bgg_resolution import BGGResolution + return BGGResolution(self) diff --git a/src/sage/algebras/lie_algebras/bgg_resolution.py b/src/sage/algebras/lie_algebras/bgg_resolution.py new file mode 100644 index 00000000000..f58388ea4d1 --- /dev/null +++ b/src/sage/algebras/lie_algebras/bgg_resolution.py @@ -0,0 +1,228 @@ +r""" +BGG Resolutions + +AUTHORS: + +- Travis Scrimshaw (2024-01-07): Initial version +""" + +#***************************************************************************** +# Copyright (C) 2024 Travis Scrimshaw +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# http://www.gnu.org/licenses/ +#***************************************************************************** + +from sage.misc.cachefunc import cached_function +from sage.structure.unique_representation import UniqueRepresentation +from sage.matrix.constructor import matrix +from sage.rings.integer_ring import ZZ +from sage.homology.chain_complex import ChainComplex_class + +class BGGResolution(UniqueRepresentation, ChainComplex_class): + r""" + The BGG resolution of a simple module. + + We realize the BGG resolution as a chain complex, where the `(-1)`-th + factor corresponds to the finite dimensional simple module `L_{\lambda}` + and the `i`-th factor (`i \geq 0`) corresponds to + + .. MATH:: + + M_i := \bigoplus_{\substack{w \in W \\ \ell(w) = i}} M_{w\lambda}. + + Since the morphisms can be defined in terms of the image of the + highest weight vectors, we only encode this information as a + (finite) chain complex. We do not include the final natural projection + map `p: M_{\lambda} \to L_{\lambda}` since the highest weight vector of + weight `\lambda` only occurs in `M_{\lambda}` and `L_{\lambda}`. + + INPUT: + + - ``L`` -- a simple module + + EXAMPLES:: + + sage: g = LieAlgebra(QQ, cartan_type=['A', 2]) + sage: La = g.cartan_type().root_system().weight_lattice().fundamental_weights() + sage: L = g.simple_module(La[1]+4*La[2]) + sage: res = L.bgg_resolution() + sage: ascii_art(res) + [ 1 -1] [1] + [1 1] [-1 1] [1] + 0 <-- C_0 <------ C_1 <-------- C_2 <---- C_3 <-- 0 + + sage: g = LieAlgebra(QQ, cartan_type=['D', 4]) + sage: La = g.cartan_type().root_system().weight_lattice().fundamental_weights() + sage: L = g.simple_module(La[1]+La[2]+3*La[3]) + sage: res = L.bgg_resolution() + sage: w0 = WeylGroup(g.cartan_type(), prefix='s').long_element() + sage: all(res.differential(i) * res.differential(i+1) == 0 + ....: for i in range(w0.length())) + True + """ + def __init__(self, L): + r""" + Initialize ``self``. + + EXAMPLES:: + + sage: g = LieAlgebra(QQ, cartan_type=['B', 2]) + sage: La = g.cartan_type().root_system().weight_lattice().fundamental_weights() + sage: L = g.simple_module(La[1]+La[2]) + sage: res = L.bgg_resolution() + sage: TestSuite(res).run() + """ + from sage.combinat.root_system.weyl_group import WeylGroup + ct = L.lie_algebra().cartan_type() + self._cartan_type = ct + self._simple = L + self._W = WeylGroup(ct, prefix='s') + # finish intialization + R = self._simple.base_ring() + differentials, mod_order = build_differentials(self._W) + differentials = {deg: mat.change_ring(R) for deg, mat in differentials.items()} + for deg in differentials: + differentials[deg].set_immutable() + self._module_order = mod_order + super().__init__(ZZ, -ZZ.one(), R, differentials) + + def _repr_(self): + r""" + Return a string representation of ``self``. + + EXAMPLES:: + + sage: g = LieAlgebra(QQ, cartan_type=['B', 2]) + sage: La = g.cartan_type().root_system().weight_lattice().fundamental_weights() + sage: L = g.simple_module(La[1]) + sage: L.bgg_resolution() + BGG resolution of Simple module with highest weight Lambda[1] + of Lie algebra of ['B', 2] in the Chevalley basis + """ + return "BGG resolution of " + repr(self._simple) + + def simple_module(self): + r""" + Return the simple module `L_{\lambda}` defining ``self``. + + EXAMPLES:: + + sage: g = LieAlgebra(QQ, cartan_type=['C', 2]) + sage: La = g.cartan_type().root_system().weight_lattice().fundamental_weights() + sage: L = g.simple_module(La[1]+La[2]) + sage: res = L.bgg_resolution() + sage: res.simple_module() is L + True + """ + return self._simple + + def module_order(self, i): + r""" + Return a tuple of Weyl group elements of length ``i`` + determining the ordering of the direct sum defining the + differential matrix. + + EXAMPLES:: + + sage: g = LieAlgebra(QQ, cartan_type=['G', 2]) + sage: La = g.cartan_type().root_system().weight_lattice().fundamental_weights() + sage: L = g.simple_module(La[1]) + sage: res = L.bgg_resolution() + sage: [res.module_order(i) for i in range(7)] + [[1], + [s2, s1], + [s2*s1, s1*s2], + [s1*s2*s1, s2*s1*s2], + [s1*s2*s1*s2, s2*s1*s2*s1], + [s1*s2*s1*s2*s1, s2*s1*s2*s1*s2], + [s2*s1*s2*s1*s2*s1]] + """ + if i not in self._module_order: + return [] + return self._module_order[i] + +@cached_function +def build_differentials(W): + r""" + Construct the differentials for the BGG resolution corresponding + to the Weyl group `W`. + + ALGORITHM: + + We use the fact that (parabolic) Bruhat order is built locally + from squares, all values defining the differential are `+1` or `-1`, + and the product over the two different paths must sum to `0`. + This is outlined in Ch. 6 of [Humphreys08]_. + + This only depends on the Coxeter group `W`. There is no stabilizer + for any dominant integral weight `\lambda` undert the dot action + (i.e., the stabilizer of `\lambda + \rho` is empty). + + EXAMPLES:: + + sage: from sage.algebras.lie_algebras.bgg_dual_module import build_differentials + sage: W = WeylGroup(['B', 2], prefix='s') + sage: D, O = build_differentials(W) + sage: unicode_art(D) + {0: [], + 1: [-1 1], + 2: [1 1] + [1 1], + 3: [ 1 -1] + [-1 1], + 4: [1] + [1], + 5: []} + sage: O + {0: [1], + 1: [s2, s1], + 2: [s2*s1, s1*s2], + 3: [s2*s1*s2, s1*s2*s1], + 4: [s2*s1*s2*s1]} + """ + from itertools import combinations + w0 = W.long_element() + maxlen = w0.length() + module_order = {i: [] for i in range(maxlen+1)} + for w in W: + module_order[w.length()].append(w) + + one = ZZ.one() + # Set the initial step + prev = {w: (j, frozenset([0])) for j, w in enumerate(module_order[maxlen-1])} + prev_mat = matrix(ZZ, [[one]]*len(module_order[maxlen-1]), immutable=True) + differentials = {maxlen: prev_mat} + for i in range(maxlen-2, -1, -1): + mat = matrix.zero(ZZ, len(module_order[i]), len(prev)) + cur = {} + for j, w in enumerate(module_order[i]): + # build the data to find the squares + covers = frozenset([prev[v][0] for v in w.bruhat_upper_covers()]) + cur[w] = (j, covers) + # set the indices in each square + for v, vp in combinations(w.bruhat_upper_covers(), 2): + # get the (unique) value at the top of the square + dv = prev[v] + dvp = prev[vp] + vind = dv[0] + vpind = dvp[0] + for uind in dv[1] & dvp[1]: + # set the entires corresponding to the square + if not mat[j, vind]: + if not mat[j, vpind]: + mat[j, vpind] = one + mat[j, vind] = -mat[j, vpind] * prev_mat[vpind, uind] * prev_mat[vind, uind] + elif not mat[j, vpind]: + mat[j, vpind] = -mat[j, vind] * prev_mat[vpind, uind] * prev_mat[vind, uind] + else: + assert mat[j, vpind] * prev_mat[vpind, uind] + mat[j, vind] * prev_mat[vind, uind] == 0 + differentials[i+1] = mat + prev = cur + prev_mat = mat + differentials[0] = matrix.zero(ZZ, 0, 1) + differentials[maxlen+1] = matrix.zero(ZZ, 1, 0) + return differentials, module_order \ No newline at end of file From 3d399e905611b2ac3352f33e28fd6ae4cbc0e8a3 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Mon, 12 Feb 2024 07:01:35 +0900 Subject: [PATCH 068/231] Fixing some last doc things. --- src/sage/algebras/lie_algebras/bgg_dual_module.py | 4 ++-- src/sage/algebras/lie_algebras/verma_module.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sage/algebras/lie_algebras/bgg_dual_module.py b/src/sage/algebras/lie_algebras/bgg_dual_module.py index aa3f425d592..55c51bb7bce 100644 --- a/src/sage/algebras/lie_algebras/bgg_dual_module.py +++ b/src/sage/algebras/lie_algebras/bgg_dual_module.py @@ -265,7 +265,7 @@ def dual(self): r""" Return the dual module of ``self``. - In Category `\mathcal{O}`, we have `(M^{\vee})^{\vee} \conj M`, so + In Category `\mathcal{O}`, we have `(M^{\vee})^{\vee} \cong M`, so we return the defining module `M` of `M^{\vee}`. EXAMPLES:: @@ -788,7 +788,7 @@ def cardinality(self): class SimpleModule(ModulePrinting, CombinatorialFreeModule): r""" Return the simple module `L_{\lambda}` as the image of the natural - morphism `\phi \colom M_{\lambda} \to M_{\lambda}^{\vee}`. + morphism `\phi: M_{\lambda} \to M_{\lambda}^{\vee}`. """ @staticmethod def __classcall_private__(cls, g, weight, *args, **kwds): diff --git a/src/sage/algebras/lie_algebras/verma_module.py b/src/sage/algebras/lie_algebras/verma_module.py index ede30deeaae..1e9e73184a9 100644 --- a/src/sage/algebras/lie_algebras/verma_module.py +++ b/src/sage/algebras/lie_algebras/verma_module.py @@ -123,7 +123,7 @@ class VermaModule(ModulePrinting, CombinatorialFreeModule): where `F_{\lambda}` is the `U(\mathfrak{b})` module such that `h \in U(\mathfrak{h})` acts as multiplication by - `\langle \lambda, h \rangle` and `U\mathfrak{g}^+) F_{\lambda} = 0`. + `\langle \lambda, h \rangle` and `U(\mathfrak{g}^+) F_{\lambda} = 0`. INPUT: From 754a71120e970cded9868d88d259d28f79fbafb1 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Mon, 12 Feb 2024 09:27:30 +0900 Subject: [PATCH 069/231] Fixing all of the doctest failures. --- .../algebras/lie_algebras/bgg_resolution.py | 5 ++-- .../algebras/lie_algebras/verma_module.py | 2 +- .../root_system/root_lattice_realizations.py | 26 ++++++++++++------- src/sage/groups/indexed_free_group.py | 4 +-- 4 files changed, 21 insertions(+), 16 deletions(-) diff --git a/src/sage/algebras/lie_algebras/bgg_resolution.py b/src/sage/algebras/lie_algebras/bgg_resolution.py index f58388ea4d1..53bb9ce86da 100644 --- a/src/sage/algebras/lie_algebras/bgg_resolution.py +++ b/src/sage/algebras/lie_algebras/bgg_resolution.py @@ -145,6 +145,7 @@ def module_order(self, i): return [] return self._module_order[i] + @cached_function def build_differentials(W): r""" @@ -164,10 +165,10 @@ def build_differentials(W): EXAMPLES:: - sage: from sage.algebras.lie_algebras.bgg_dual_module import build_differentials + sage: from sage.algebras.lie_algebras.bgg_resolution import build_differentials sage: W = WeylGroup(['B', 2], prefix='s') sage: D, O = build_differentials(W) - sage: unicode_art(D) + sage: D {0: [], 1: [-1 1], 2: [1 1] diff --git a/src/sage/algebras/lie_algebras/verma_module.py b/src/sage/algebras/lie_algebras/verma_module.py index 1e9e73184a9..ac5d0ceb113 100644 --- a/src/sage/algebras/lie_algebras/verma_module.py +++ b/src/sage/algebras/lie_algebras/verma_module.py @@ -47,7 +47,7 @@ def __init__(self, vector_name='v'): sage: from sage.algebras.lie_algebras.verma_module import ModulePrinting sage: MP = ModulePrinting() - sage: TestSuite(MP).run() + sage: TestSuite(MP).run(skip="_test_pickling") """ self.__vector_name = vector_name diff --git a/src/sage/combinat/root_system/root_lattice_realizations.py b/src/sage/combinat/root_system/root_lattice_realizations.py index ab63dadf135..2687aa8b1c4 100644 --- a/src/sage/combinat/root_system/root_lattice_realizations.py +++ b/src/sage/combinat/root_system/root_lattice_realizations.py @@ -3937,22 +3937,28 @@ def is_verma_dominant(self, positive=True): sage: P = RootSystem(['A', 3]).weight_space() sage: La = P.fundamental_weights() + sage: alphacheck = P.coroot_lattice().positive_roots() + sage: rho = P.rho() sage: (La[1] + 2*La[2]).is_verma_dominant() True - sage: (La[1] - 3/2*La[3]).is_verma_dominant() - True - sage: (La[1] - 3/2*La[3]).is_verma_dominant(positive=False) + sage: la = La[1] - 3/2*La[3] - rho + sage: la.is_verma_dominant() True - sage: (1/2*La[1] - 3/2*La[3]).is_verma_dominant() + sage: la.is_verma_dominant(positive=False) False - sage: alphacheck = P.coroot_lattice().positive_roots() - sage: [(1/2*La[1] - 3/2*La[3]).scalar(coroot) for coroot in alphacheck] - [1/2, 0, -3/2, 1/2, -3/2, -1] - sage: (1/2*La[1] - 3/2*La[3]).is_verma_dominant(positive=False) + sage: [(la+rho).scalar(coroot) for coroot in alphacheck] + [1, 0, -3/2, 1, -3/2, -1/2] + sage: mu = 1/2*La[1] - 3/2*La[3] - rho + sage: mu.is_verma_dominant() + False + sage: mu.is_verma_dominant(positive=False) True + sage: [(mu+rho).scalar(coroot) for coroot in alphacheck] + [1/2, 0, -3/2, 1/2, -3/2, -1] """ - alphacheck = self.parent().coroot_lattice().positive_roots() - wt = self + self.parent().rho() + P = self.parent() + alphacheck = P.coroot_lattice().positive_roots() + wt = self + P.rho() if positive: return not any((c := wt.scalar(ac)) in ZZ and c < 0 for ac in alphacheck) return not any((c := wt.scalar(ac)) in ZZ and c > 0 for ac in alphacheck) diff --git a/src/sage/groups/indexed_free_group.py b/src/sage/groups/indexed_free_group.py index 02a4838d77c..ad484532f13 100644 --- a/src/sage/groups/indexed_free_group.py +++ b/src/sage/groups/indexed_free_group.py @@ -347,9 +347,7 @@ def _element_constructor_(self, x=None): sage: G({1: 3, -2: 12}) F[-2]^12*F[1]^3 sage: G(-5) - Traceback (most recent call last): - ... - TypeError: unable to convert -5, use gen() instead + F[-5] TESTS:: From 7f1f61013a2550aa320f5c05b995531bc9af2a57 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Thu, 20 Jun 2024 10:55:32 +0900 Subject: [PATCH 070/231] Doing reviewer suggestions. --- .../algebras/lie_algebras/bgg_dual_module.py | 32 +++++++++---------- .../algebras/lie_algebras/bgg_resolution.py | 10 +++--- .../lie_algebras/poincare_birkhoff_witt.py | 11 ++++++- .../algebras/lie_algebras/verma_module.py | 8 ++--- .../triangular_kac_moody_algebras.py | 2 +- .../root_system/root_lattice_realizations.py | 4 +-- src/sage/combinat/root_system/weight_space.py | 4 +-- src/sage/monoids/indexed_free_monoid.py | 6 ++-- 8 files changed, 43 insertions(+), 34 deletions(-) diff --git a/src/sage/algebras/lie_algebras/bgg_dual_module.py b/src/sage/algebras/lie_algebras/bgg_dual_module.py index 55c51bb7bce..01517c4e51f 100644 --- a/src/sage/algebras/lie_algebras/bgg_dual_module.py +++ b/src/sage/algebras/lie_algebras/bgg_dual_module.py @@ -106,11 +106,11 @@ def __init__(self, module): sage: g = LieAlgebra(QQ, cartan_type=['B', 2]) sage: La = g.cartan_type().root_system().weight_space().fundamental_weights() - sage: M = g.verma_module(2*La[1]+La[2]) + sage: M = g.verma_module(2*La[1] + La[2]) sage: Mc = M.dual() sage: TestSuite(Mc).run() - sage: M = g.verma_module(2/3*La[1]-3/5*La[2]) + sage: M = g.verma_module(2/3*La[1] - 3/5*La[2]) sage: Mc = M.dual() sage: TestSuite(Mc).run() """ @@ -449,7 +449,7 @@ def __classcall__(cls, simple, prefix='f', **kwds): sage: g = LieAlgebra(QQ, cartan_type=['E', 6]) sage: La = g.cartan_type().root_system().weight_lattice().fundamental_weights() - sage: L = g.simple_module(La[1]+La[3]) + sage: L = g.simple_module(La[1] + La[3]) sage: from sage.algebras.lie_algebras.bgg_dual_module import SimpleModuleIndices sage: SimpleModuleIndices(L) is L._indices True @@ -464,10 +464,10 @@ def __init__(self, simple, prefix, category=None, **kwds): sage: g = LieAlgebra(QQ, cartan_type=['A', 2]) sage: La = g.cartan_type().root_system().weight_space().fundamental_weights() - sage: I = g.simple_module(2*La[1]+La[2]).indices() + sage: I = g.simple_module(2*La[1] + La[2]).indices() sage: TestSuite(I).run() - sage: I = g.simple_module(2*La[1]-1/3*La[2]).indices() + sage: I = g.simple_module(2*La[1] - 1/3*La[2]).indices() sage: TestSuite(I).run(max_runs=150) # long time """ self._simple = simple @@ -509,7 +509,7 @@ def _an_element_(self): sage: g = LieAlgebra(QQ, cartan_type=['E', 6]) sage: La = g.cartan_type().root_system().weight_lattice().fundamental_weights() - sage: I = g.simple_module(2*La[1]+La[2]).indices() + sage: I = g.simple_module(2*La[1] + La[2]).indices() sage: I._an_element_() 1 """ @@ -679,7 +679,7 @@ def _construct_next_level(self): .. TODO:: Avoid unnecessary computations by using the corresponding - (combinastorial) crystal. + (combinatorial) crystal. EXAMPLES:: @@ -800,11 +800,11 @@ def __classcall_private__(cls, g, weight, *args, **kwds): sage: g = LieAlgebra(QQ, cartan_type=['E', 6]) sage: La = g.cartan_type().root_system().weight_space().fundamental_weights() - sage: type(g.simple_module(La[1]+La[2])) + sage: type(g.simple_module(La[1] + La[2])) - sage: type(g.simple_module(La[1]-La[2])) + sage: type(g.simple_module(La[1] - La[2])) - sage: type(g.simple_module(La[1]+3/2*La[2])) + sage: type(g.simple_module(La[1] + 3/2*La[2])) """ if weight.is_dominant_weight(): @@ -819,12 +819,12 @@ def __init__(self, g, weight, prefix='f', basis_key=None, **kwds): sage: g = LieAlgebra(QQ, cartan_type=['G', 2]) sage: La = g.cartan_type().root_system().weight_lattice().fundamental_weights() - sage: L = g.simple_module(La[1]+La[2]) + sage: L = g.simple_module(La[1] + La[2]) sage: TestSuite(L).run() sage: g = LieAlgebra(QQ, cartan_type=['A', 2]) sage: La = g.cartan_type().root_system().weight_lattice().fundamental_weights() - sage: L = g.simple_module(La[1]-La[2]) + sage: L = g.simple_module(La[1] - La[2]) sage: TestSuite(L).run() """ self._g = g @@ -988,7 +988,7 @@ def dual(self): sage: g = LieAlgebra(QQ, cartan_type=['B', 4]) sage: La = g.cartan_type().root_system().weight_lattice().fundamental_weights() - sage: L = g.simple_module(2*La[1]+3*La[4]) + sage: L = g.simple_module(2*La[1] + 3*La[4]) sage: L.dual() is L True """ @@ -1064,7 +1064,7 @@ def homogeneous_component_basis(self, mu): sage: g = LieAlgebra(QQ, cartan_type=['A', 2]) sage: P = g.cartan_type().root_system().weight_lattice() sage: La = P.fundamental_weights() - sage: la = La[1]+La[2] + sage: la = La[1] + La[2] sage: L = g.simple_module(la) sage: from itertools import product sage: al = P.simple_roots() @@ -1118,7 +1118,7 @@ def _acted_upon_(self, scalar, self_on_left=True): sage: g = LieAlgebra(QQ, cartan_type=['A', 2]) sage: La = g.cartan_type().root_system().weight_lattice().fundamental_weights() - sage: L = g.simple_module(La[1]+La[2]) + sage: L = g.simple_module(La[1] + La[2]) sage: v = L.highest_weight_vector(); v u[Lambda[1] + Lambda[2]] sage: f1, f2 = g.pbw_basis().f() @@ -1165,7 +1165,7 @@ def bgg_resolution(self): sage: g = LieAlgebra(QQ, cartan_type=['A', 2]) sage: La = g.cartan_type().root_system().weight_lattice().fundamental_weights() - sage: L = g.simple_module(La[1]+La[2]) + sage: L = g.simple_module(La[1] + La[2]) sage: L.bgg_resolution() BGG resolution of Simple module with highest weight Lambda[1] + Lambda[2] of Lie algebra of ['A', 2] in the Chevalley basis diff --git a/src/sage/algebras/lie_algebras/bgg_resolution.py b/src/sage/algebras/lie_algebras/bgg_resolution.py index 53bb9ce86da..89ccb3d2079 100644 --- a/src/sage/algebras/lie_algebras/bgg_resolution.py +++ b/src/sage/algebras/lie_algebras/bgg_resolution.py @@ -48,7 +48,7 @@ class BGGResolution(UniqueRepresentation, ChainComplex_class): sage: g = LieAlgebra(QQ, cartan_type=['A', 2]) sage: La = g.cartan_type().root_system().weight_lattice().fundamental_weights() - sage: L = g.simple_module(La[1]+4*La[2]) + sage: L = g.simple_module(La[1] + 4*La[2]) sage: res = L.bgg_resolution() sage: ascii_art(res) [ 1 -1] [1] @@ -57,7 +57,7 @@ class BGGResolution(UniqueRepresentation, ChainComplex_class): sage: g = LieAlgebra(QQ, cartan_type=['D', 4]) sage: La = g.cartan_type().root_system().weight_lattice().fundamental_weights() - sage: L = g.simple_module(La[1]+La[2]+3*La[3]) + sage: L = g.simple_module(La[1] + La[2] + 3*La[3]) sage: res = L.bgg_resolution() sage: w0 = WeylGroup(g.cartan_type(), prefix='s').long_element() sage: all(res.differential(i) * res.differential(i+1) == 0 @@ -72,7 +72,7 @@ def __init__(self, L): sage: g = LieAlgebra(QQ, cartan_type=['B', 2]) sage: La = g.cartan_type().root_system().weight_lattice().fundamental_weights() - sage: L = g.simple_module(La[1]+La[2]) + sage: L = g.simple_module(La[1] + La[2]) sage: res = L.bgg_resolution() sage: TestSuite(res).run() """ @@ -113,7 +113,7 @@ def simple_module(self): sage: g = LieAlgebra(QQ, cartan_type=['C', 2]) sage: La = g.cartan_type().root_system().weight_lattice().fundamental_weights() - sage: L = g.simple_module(La[1]+La[2]) + sage: L = g.simple_module(La[1] + La[2]) sage: res = L.bgg_resolution() sage: res.simple_module() is L True @@ -226,4 +226,4 @@ def build_differentials(W): prev_mat = mat differentials[0] = matrix.zero(ZZ, 0, 1) differentials[maxlen+1] = matrix.zero(ZZ, 1, 0) - return differentials, module_order \ No newline at end of file + return differentials, module_order diff --git a/src/sage/algebras/lie_algebras/poincare_birkhoff_witt.py b/src/sage/algebras/lie_algebras/poincare_birkhoff_witt.py index 56be8304681..813a5a45293 100644 --- a/src/sage/algebras/lie_algebras/poincare_birkhoff_witt.py +++ b/src/sage/algebras/lie_algebras/poincare_birkhoff_witt.py @@ -657,7 +657,7 @@ def __init__(self, g, basis_key=None, *args, **kwds): sage: PBW = L.pbw_basis() sage: E, F, H = PBW.algebra_generators() sage: TestSuite(PBW).run(elements=[E, F, H]) - sage: TestSuite(PBW).run(elements=[E, F, H, E*F + H]) # long time + sage: TestSuite(PBW).run(elements=[E, F, H, E*F + H]) # long time """ super().__init__(g, basis_key, *args, **kwds) if self._basis_key == self._g._triangular_key: @@ -801,5 +801,14 @@ def transpose(self): EXAMPLES:: sage: g = LieAlgebra(QQ, cartan_type=['D', 4]) + sage: U = g.pbw_basis() + sage: e = U.e() + sage: f = U.f() + sage: elts = [e[1], e[1]*e[2], e[3]+e[4], e[1]*e[3]*e[4] + e[2], + ....: f[1], f[1]*f[2], f[3]+f[4], e[1]*e[3]*e[4] + e[2], + ....: e[1]*f[1], f[1]*e[1], (e[2]*f[2] - f[2]*e[2])^2] + sage: all((b*bp).transpose() == bp.transpose() * b.transpose() + ....: for b in elts for bp in elts) + True """ return self.parent().transpose(self) diff --git a/src/sage/algebras/lie_algebras/verma_module.py b/src/sage/algebras/lie_algebras/verma_module.py index ac5d0ceb113..f772e8bdce6 100644 --- a/src/sage/algebras/lie_algebras/verma_module.py +++ b/src/sage/algebras/lie_algebras/verma_module.py @@ -35,7 +35,7 @@ from sage.rings.rational_field import QQ -class ModulePrinting(object): +class ModulePrinting: """ Helper mixin class for printing the module vectors. """ @@ -1158,8 +1158,8 @@ def image(self): sage: g = LieAlgebra(QQ, cartan_type=['B', 2]) sage: La = g.cartan_type().root_system().weight_lattice().fundamental_weights() - sage: M = g.verma_module(La[1]+2*La[2]) - sage: Mp = g.verma_module(La[1]+3*La[2]) + sage: M = g.verma_module(La[1] + 2*La[2]) + sage: Mp = g.verma_module(La[1] + 3*La[2]) sage: phi = Hom(M, Mp).natural_map() sage: phi.image() Free module generated by {} over Rational Field @@ -1302,7 +1302,7 @@ def highest_weight_image(self): sage: g = LieAlgebra(QQ, cartan_type=['C', 3]) sage: La = g.cartan_type().root_system().weight_lattice().fundamental_weights() - sage: M = g.verma_module(La[1]+2*La[3]) + sage: M = g.verma_module(La[1] + 2*La[3]) sage: Mc = M.dual() sage: H = Hom(M, Mc) sage: H.highest_weight_image() diff --git a/src/sage/categories/triangular_kac_moody_algebras.py b/src/sage/categories/triangular_kac_moody_algebras.py index 40c382c8a9b..677b20e06f4 100644 --- a/src/sage/categories/triangular_kac_moody_algebras.py +++ b/src/sage/categories/triangular_kac_moody_algebras.py @@ -422,7 +422,7 @@ def transpose(self): The transpose `\tau` is the map that sends the root basis elements `e_{\alpha} \leftrightarrow e_{-\alpha}` and fixes the Cartan subalgebra `h_{\alpha}`. It is an anti-involution - in the sense `[\tau(a), \tau(b)] = \tau([a, b])`. + in the sense `[\tau(a), \tau(b)] = \tau([b, a])`. EXAMPLES:: diff --git a/src/sage/combinat/root_system/root_lattice_realizations.py b/src/sage/combinat/root_system/root_lattice_realizations.py index 2687aa8b1c4..435c2fcfc65 100644 --- a/src/sage/combinat/root_system/root_lattice_realizations.py +++ b/src/sage/combinat/root_system/root_lattice_realizations.py @@ -3922,8 +3922,8 @@ def is_verma_dominant(self, positive=True): \langle \lambda + \rho, \alpha^{\vee} \rangle \notin \ZZ_{<0} - for all positive roots `\alpha`. Note that this does *not* - imply that `\langle \lambda + \rho, \alpha^{\vee} \rangle \geq 0` + for all positive roots `\alpha`. Note that begin Verma dominant does + *not* imply that `\langle \lambda+\rho, \alpha^{\vee} \rangle \geq 0` for any positive root `\alpha`. This is used to determine if a Verma module is simple or projective. diff --git a/src/sage/combinat/root_system/weight_space.py b/src/sage/combinat/root_system/weight_space.py index fc30553fdec..fce5f57f94d 100644 --- a/src/sage/combinat/root_system/weight_space.py +++ b/src/sage/combinat/root_system/weight_space.py @@ -530,7 +530,7 @@ def is_dominant(self): sage: w.is_dominant() False - In the extended affine weight lattice, 'delta' is orthogonal to + In the extended affine weight lattice, ``'delta'`` is orthogonal to the positive coroots, so adding or subtracting it should not affect dominance:: @@ -563,7 +563,7 @@ def is_dominant_weight(self): sage: w.is_dominant_weight() False - In the extended affine weight lattice, 'delta' is orthogonal to + In the extended affine weight lattice, ``'delta'`` is orthogonal to the positive coroots, so adding or subtracting it should not affect dominance:: diff --git a/src/sage/monoids/indexed_free_monoid.py b/src/sage/monoids/indexed_free_monoid.py index 5ec7e0777eb..a50aa7cdf12 100644 --- a/src/sage/monoids/indexed_free_monoid.py +++ b/src/sage/monoids/indexed_free_monoid.py @@ -291,7 +291,7 @@ def support(self): try: return sorted(supp, key=print_options['sorting_key'], reverse=print_options['sorting_reverse']) - except Exception: # Sorting the output is a plus, but if we can't, no big deal + except Exception: # Sorting the output is a plus, but if we can't, no big deal return list(supp) def leading_support(self): @@ -527,7 +527,7 @@ def _sorted_items(self): try: v.sort(key=print_options['sorting_key'], reverse=print_options['sorting_reverse']) - except Exception: # Sorting the output is a plus, but if we can't, no big deal + except Exception: # Sorting the output is a plus, but if we can't, no big deal pass return v @@ -967,7 +967,7 @@ class IndexedFreeAbelianMonoid(IndexedMonoid): .. TODO:: Implement a subclass when the index sets is finite that utilizes - vectors or the polydict monomials with the index order is fixed. + vectors or the polydict monomials with the index order fixed. """ def _repr_(self): """ From 6c28cc7abff84000cd12357897f1c36bf3e8433e Mon Sep 17 00:00:00 2001 From: Gareth Ma Date: Thu, 20 Jun 2024 03:00:37 +0100 Subject: [PATCH 071/231] lint: fix _latex_ exponent --- src/sage/schemes/affine/affine_space.py | 8 ++++---- src/sage/schemes/projective/projective_space.py | 9 ++++----- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/sage/schemes/affine/affine_space.py b/src/sage/schemes/affine/affine_space.py index 572d39bad51..848afc9bf27 100644 --- a/src/sage/schemes/affine/affine_space.py +++ b/src/sage/schemes/affine/affine_space.py @@ -332,14 +332,14 @@ def _latex_(self): EXAMPLES:: sage: print(latex(AffineSpace(1, ZZ, 'x'))) - \mathbf{A}_{\Bold{Z}}^1 + \mathbf{A}_{\Bold{Z}}^{1} TESTS:: - sage: AffineSpace(3, Zp(5), 'y')._latex_() # needs sage.rings.padics - '\\mathbf{A}_{\\Bold{Z}_{5}}^3' + sage: AffineSpace(11, Zp(5), 'y')._latex_() # needs sage.rings.padics + '\\mathbf{A}_{\\Bold{Z}_{5}}^{11}' """ - return "\\mathbf{A}_{%s}^%s" % (latex(self.base_ring()), self.dimension_relative()) + return "\\mathbf{A}_{%s}^{%s}" % (latex(self.base_ring()), self.dimension_relative()) def _morphism(self, *args, **kwds): """ diff --git a/src/sage/schemes/projective/projective_space.py b/src/sage/schemes/projective/projective_space.py index ded40bb85b5..15c68f47dcc 100644 --- a/src/sage/schemes/projective/projective_space.py +++ b/src/sage/schemes/projective/projective_space.py @@ -590,15 +590,14 @@ def _latex_(self): EXAMPLES:: sage: print(latex(ProjectiveSpace(1, ZZ, 'x'))) - {\mathbf P}_{\Bold{Z}}^1 + {\mathbf P}_{\Bold{Z}}^{1} TESTS:: - sage: ProjectiveSpace(3, Zp(5), 'y')._latex_() # needs sage.rings.padics - '{\\mathbf P}_{\\Bold{Z}_{5}}^3' + sage: ProjectiveSpace(11, Zp(5), 'y')._latex_() # needs sage.rings.padics + '{\\mathbf P}_{\\Bold{Z}_{5}}^{11}' """ - return "{\\mathbf P}_{%s}^%s" % (latex(self.base_ring()), - self.dimension_relative()) + return "{\\mathbf P}_{%s}^{%s}" % (latex(self.base_ring()), self.dimension_relative()) def _linear_system_as_kernel(self, d, pt, m): """ From 64ee93c963cacca1d564e715b17c16770f647ca8 Mon Sep 17 00:00:00 2001 From: Gareth Ma Date: Thu, 20 Jun 2024 03:23:54 +0100 Subject: [PATCH 072/231] lint: fix ignored doctest --- src/sage/rings/number_field/number_field_rel.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/sage/rings/number_field/number_field_rel.py b/src/sage/rings/number_field/number_field_rel.py index ba4ab4ec5f3..055b0997e9f 100644 --- a/src/sage/rings/number_field/number_field_rel.py +++ b/src/sage/rings/number_field/number_field_rel.py @@ -2474,8 +2474,9 @@ def order(self, *gens, **kwds): EXAMPLES:: - sage: P. = QQ[2^(1/2), 2^(1/3), 3^(1/2)] # needs sage.symbolic - sage: R = P.order([a,b,c]); R # not tested (83s, 2GB memory), needs sage.symbolic + sage: # needs sage.symbolic + sage: P3. = QQ[2^(1/2), 2^(1/3), 3^(1/2)] + sage: R = P3.order([a,b,c]); R # not tested (83s, 2GB memory) Relative Order generated by [((-36372*sqrt3 + 371270)*a^2 + (-89082*sqrt3 + 384161)*a - 422504*sqrt3 - 46595)*sqrt2 + (303148*sqrt3 - 89080)*a^2 + (313664*sqrt3 - 218211)*a - 38053*sqrt3 - 1034933, ((-65954*sqrt3 + 323491)*a^2 + (-110591*sqrt3 + 350011)*a - 351557*sqrt3 + 77507)*sqrt2 + (264138*sqrt3 - 161552)*a^2 + (285784*sqrt3 - 270906)*a + 63287*sqrt3 - 861151, @@ -2484,15 +2485,20 @@ def order(self, *gens, **kwds): ((-73815*sqrt3 + 257278)*a^2 + (-102896*sqrt3 + 298046)*a - 277080*sqrt3 + 123726)*sqrt2 + (210072*sqrt3 - 180812)*a^2 + (243357*sqrt3 - 252052)*a + 101026*sqrt3 - 678718] in Number Field in sqrt2 with defining polynomial x^2 - 2 over its base field - The base ring of an order in a relative extension is still `\ZZ`.:: + sage: P2. = QQ[2^(1/2), 2^(1/3)] # needs sage.symbolic + sage: R = P2.order([a,b]); R # needs sage.symbolic + Relative Order generated by [(6*a^2 - a - 1)*sqrt2 + 4*a^2 - 6*a - 9, sqrt2 - a] + in Number Field in sqrt2 with defining polynomial x^2 - 2 over its base field + + The base ring of an order in a relative extension is still `\ZZ`:: - sage: R.base_ring() # long time, needs sage.symbolic + sage: R.base_ring() # needs sage.symbolic Integer Ring One must give enough generators to generate a ring of finite index in the maximal order:: - sage: P.order([a, b]) # long time, needs sage.symbolic + sage: P3.order([a, b]) # needs sage.symbolic Traceback (most recent call last): ... ValueError: the rank of the span of gens is wrong From efd15c9e45261a6f90096be96a9addd5f78ef60f Mon Sep 17 00:00:00 2001 From: Gareth Ma Date: Thu, 20 Jun 2024 04:51:21 +0100 Subject: [PATCH 073/231] lint: fix doctests --- src/sage/rings/number_field/number_field_rel.py | 4 ++-- src/sage/rings/tate_algebra_ideal.pyx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sage/rings/number_field/number_field_rel.py b/src/sage/rings/number_field/number_field_rel.py index 055b0997e9f..5ab20ddce48 100644 --- a/src/sage/rings/number_field/number_field_rel.py +++ b/src/sage/rings/number_field/number_field_rel.py @@ -2485,8 +2485,8 @@ def order(self, *gens, **kwds): ((-73815*sqrt3 + 257278)*a^2 + (-102896*sqrt3 + 298046)*a - 277080*sqrt3 + 123726)*sqrt2 + (210072*sqrt3 - 180812)*a^2 + (243357*sqrt3 - 252052)*a + 101026*sqrt3 - 678718] in Number Field in sqrt2 with defining polynomial x^2 - 2 over its base field - sage: P2. = QQ[2^(1/2), 2^(1/3)] # needs sage.symbolic - sage: R = P2.order([a,b]); R # needs sage.symbolic + sage: P2. = QQ[2^(1/2), 2^(1/3)] # needs sage.symbolic + sage: R = P2.order([u,v]); R # needs sage.symbolic Relative Order generated by [(6*a^2 - a - 1)*sqrt2 + 4*a^2 - 6*a - 9, sqrt2 - a] in Number Field in sqrt2 with defining polynomial x^2 - 2 over its base field diff --git a/src/sage/rings/tate_algebra_ideal.pyx b/src/sage/rings/tate_algebra_ideal.pyx index d5a0598f40c..acad1be5fd3 100644 --- a/src/sage/rings/tate_algebra_ideal.pyx +++ b/src/sage/rings/tate_algebra_ideal.pyx @@ -617,7 +617,7 @@ cdef TateAlgebraElement regular_reduce(sgb, TateAlgebraTerm s, TateAlgebraElemen TESTS:: - sage: cython( # long time (6.5s), needs sage.misc.cython + sage: cython( # needs sage.misc.cython ....: ''' ....: from sage.rings.tate_algebra_ideal cimport regular_reduce ....: def python_regular_reduce(gb, s, v, stopval): From 9c8d7cf5017f154ca4fe2097c9cb4637e5c7d386 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Thu, 20 Jun 2024 12:52:10 +0900 Subject: [PATCH 074/231] Fixing linter issues. --- src/sage/algebras/lie_algebras/verma_module.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/sage/algebras/lie_algebras/verma_module.py b/src/sage/algebras/lie_algebras/verma_module.py index f772e8bdce6..71f2ff58a85 100644 --- a/src/sage/algebras/lie_algebras/verma_module.py +++ b/src/sage/algebras/lie_algebras/verma_module.py @@ -1191,7 +1191,6 @@ def image(self): return self.codomain() - class VermaModuleHomset(Homset): r""" The set of morphisms from a Verma module to another module in From e509fbc680141767c2dba98f6147a7e8d38e0233 Mon Sep 17 00:00:00 2001 From: Gareth Ma Date: Thu, 20 Jun 2024 05:13:11 +0100 Subject: [PATCH 075/231] lint: fix doctest --- src/sage/schemes/generic/algebraic_scheme.py | 8 ++++---- src/sage/schemes/product_projective/space.py | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/sage/schemes/generic/algebraic_scheme.py b/src/sage/schemes/generic/algebraic_scheme.py index f442ff309b3..0767992cc7f 100644 --- a/src/sage/schemes/generic/algebraic_scheme.py +++ b/src/sage/schemes/generic/algebraic_scheme.py @@ -248,7 +248,7 @@ def _latex_(self): sage: S = AlgebraicScheme(P); S Subscheme of Projective Space of dimension 3 over Integer Ring sage: S._latex_() - '\\text{Subscheme of ${\\mathbf P}_{\\Bold{Z}}^3$}' + '\\text{Subscheme of ${\\mathbf P}_{\\Bold{Z}}^{3}$}' """ return r"\text{{Subscheme of ${}$}}".format(latex(self.__A)) @@ -675,7 +675,7 @@ def _latex_(self): x - y sage: U._latex_() '\\text{Quasi-projective subscheme } - (X\\setminus Y)\\subset {\\mathbf P}_{\\Bold{Z}}^2,\\text{ where } + (X\\setminus Y)\\subset {\\mathbf P}_{\\Bold{Z}}^{2},\\text{ where } X \\text{ is defined by }\\text{no polynomials},\\text{ and } Y \\text{ is defined by } x - y.' """ @@ -1047,13 +1047,13 @@ def _latex_(self): Closed subscheme of Projective Space of dimension 2 over Finite Field of size 11 defined by: x^2 - y*z sage: S._latex_() - '\\text{Closed subscheme of } {\\mathbf P}_{\\Bold{F}_{11}}^2 \\text{ defined by } x^{2} - y z' + '\\text{Closed subscheme of } {\\mathbf P}_{\\Bold{F}_{11}}^{2} \\text{ defined by } x^{2} - y z' sage: S = P.subscheme([x^2 - y*z, x^5]); S Closed subscheme of Projective Space of dimension 2 over Finite Field of size 11 defined by: x^2 - y*z, x^5 sage: S._latex_() - '\\text{Closed subscheme of } {\\mathbf P}_{\\Bold{F}_{11}}^2 \\text{ defined by } x^{2} - y z, x^{5}' + '\\text{Closed subscheme of } {\\mathbf P}_{\\Bold{F}_{11}}^{2} \\text{ defined by } x^{2} - y z, x^{5}' """ polynomials = ', '.join(latex(f) for f in self.defining_polynomials()) if not polynomials: diff --git a/src/sage/schemes/product_projective/space.py b/src/sage/schemes/product_projective/space.py index ea99ea00559..56df71b3896 100644 --- a/src/sage/schemes/product_projective/space.py +++ b/src/sage/schemes/product_projective/space.py @@ -293,8 +293,8 @@ def _latex_(self): EXAMPLES:: sage: latex(ProductProjectiveSpaces([1, 2, 3], ZZ, 'x')) - {\mathbf P}_{\Bold{Z}}^1 \times {\mathbf P}_{\Bold{Z}}^2 \times {\mathbf - P}_{\Bold{Z}}^3 + {\mathbf P}_{\Bold{Z}}^{1} \times {\mathbf P}_{\Bold{Z}}^{2} \times + {\mathbf P}_{\Bold{Z}}^{3} """ return " \\times ".join(PS._latex_() for PS in self) From 24f235642055d62fe84076e2bfe68db57054af20 Mon Sep 17 00:00:00 2001 From: grhkm21 <83517584+grhkm21@users.noreply.github.com> Date: Thu, 20 Jun 2024 05:37:20 +0100 Subject: [PATCH 076/231] Update src/sage/algebras/fusion_rings/f_matrix.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Matthias Köppe --- src/sage/algebras/fusion_rings/f_matrix.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/algebras/fusion_rings/f_matrix.py b/src/sage/algebras/fusion_rings/f_matrix.py index cac9f3a3b05..6ec533af939 100644 --- a/src/sage/algebras/fusion_rings/f_matrix.py +++ b/src/sage/algebras/fusion_rings/f_matrix.py @@ -2427,7 +2427,7 @@ def certify_pentagons(self, use_mp=True, verbose=False): Partitioned 6 equations into 6 components of size: [1, 1, 1, 1, 1, 1] Computing appropriate NumberField... - sage: f.certify_pentagons() is None # not tested, long time (~1.5s), cypari issue in doctesting framework + sage: f.certify_pentagons() is None # not tested (cypari issue in doctesting framework), long time (~1.5s) True """ fvars_copy = deepcopy(self._fvars) From 4f804124b0ea820e0b28282b5257902ca2542218 Mon Sep 17 00:00:00 2001 From: grhkm21 <83517584+grhkm21@users.noreply.github.com> Date: Thu, 20 Jun 2024 05:37:37 +0100 Subject: [PATCH 077/231] Update src/sage/combinat/root_system/root_lattice_realization_algebras.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Matthias Köppe --- .../combinat/root_system/root_lattice_realization_algebras.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/combinat/root_system/root_lattice_realization_algebras.py b/src/sage/combinat/root_system/root_lattice_realization_algebras.py index e1aabcf7f06..f4d48b8efc1 100644 --- a/src/sage/combinat/root_system/root_lattice_realization_algebras.py +++ b/src/sage/combinat/root_system/root_lattice_realization_algebras.py @@ -566,7 +566,7 @@ def demazure_lusztig_operators(self, q1, q2, convention="antidominant"): sage: K = QQ['q1,q2'] sage: q1, q2 = K.gens() - sage: for cartan_type in CartanType.samples(crystallographic=True): # long time (12s) + sage: for cartan_type in CartanType.samples(crystallographic=True): # long time (12s) ....: L = RootSystem(cartan_type).root_lattice() ....: KL = L.algebra(K) ....: T = KL.demazure_lusztig_operators(q1,q2) From b00a44c8a02683880aa505899b65ddc149e0cde2 Mon Sep 17 00:00:00 2001 From: grhkm21 <83517584+grhkm21@users.noreply.github.com> Date: Thu, 20 Jun 2024 05:37:48 +0100 Subject: [PATCH 078/231] Update src/sage/rings/polynomial/polynomial_quotient_ring_element.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Matthias Köppe --- src/sage/rings/polynomial/polynomial_quotient_ring_element.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/sage/rings/polynomial/polynomial_quotient_ring_element.py b/src/sage/rings/polynomial/polynomial_quotient_ring_element.py index 1fc95c248b4..97534f3aa22 100644 --- a/src/sage/rings/polynomial/polynomial_quotient_ring_element.py +++ b/src/sage/rings/polynomial/polynomial_quotient_ring_element.py @@ -721,8 +721,7 @@ def minpoly(self): We make sure that the previous example works on random examples:: - sage: # long time - sage: # needs sage.rings.finite_rings + sage: # long time, needs sage.rings.finite_rings sage: p = random_prime(50) sage: K. = GF((p, randrange(1,20))) sage: L. = K.extension(randrange(2,20)) From 450b22d0872adc571daced1bbe2a2b2501af7d36 Mon Sep 17 00:00:00 2001 From: grhkm21 <83517584+grhkm21@users.noreply.github.com> Date: Thu, 20 Jun 2024 05:50:44 +0100 Subject: [PATCH 079/231] Update src/sage/combinat/root_system/root_lattice_realization_algebras.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Matthias Köppe --- .../combinat/root_system/root_lattice_realization_algebras.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/combinat/root_system/root_lattice_realization_algebras.py b/src/sage/combinat/root_system/root_lattice_realization_algebras.py index f4d48b8efc1..e4569459ce0 100644 --- a/src/sage/combinat/root_system/root_lattice_realization_algebras.py +++ b/src/sage/combinat/root_system/root_lattice_realization_algebras.py @@ -1103,7 +1103,7 @@ def twisted_demazure_lusztig_operators(self, q1, q2, convention="antidominant"): sage: K = QQ['q1,q2'].fraction_field() sage: q1, q2 = K.gens() - sage: for cartan_type in CartanType.samples(affine=True, crystallographic=True): # long time (12s) + sage: for cartan_type in CartanType.samples(affine=True, crystallographic=True): # long time (12s) ....: if cartan_type.rank() > 4: continue ....: if cartan_type.type() == 'BC': continue ....: KL = RootSystem(cartan_type).weight_lattice().algebra(K) From e9c360e1c6172531886a59821dc34e7e36499080 Mon Sep 17 00:00:00 2001 From: grhkm21 <83517584+grhkm21@users.noreply.github.com> Date: Thu, 20 Jun 2024 05:50:49 +0100 Subject: [PATCH 080/231] Update src/sage/combinat/root_system/root_lattice_realization_algebras.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Matthias Köppe --- .../combinat/root_system/root_lattice_realization_algebras.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/combinat/root_system/root_lattice_realization_algebras.py b/src/sage/combinat/root_system/root_lattice_realization_algebras.py index e4569459ce0..60b27183426 100644 --- a/src/sage/combinat/root_system/root_lattice_realization_algebras.py +++ b/src/sage/combinat/root_system/root_lattice_realization_algebras.py @@ -572,7 +572,7 @@ def demazure_lusztig_operators(self, q1, q2, convention="antidominant"): ....: T = KL.demazure_lusztig_operators(q1,q2) ....: T._test_relations() - sage: for cartan_type in CartanType.samples(crystallographic=True): # long time (12s) + sage: for cartan_type in CartanType.samples(crystallographic=True): # long time (12s) ....: L = RootSystem(cartan_type).weight_lattice() ....: KL = L.algebra(K) ....: T = KL.demazure_lusztig_operators(q1,q2) From f570e7a1d49dbb76a9fba2642991aa95e6ea06fa Mon Sep 17 00:00:00 2001 From: grhkm21 <83517584+grhkm21@users.noreply.github.com> Date: Thu, 20 Jun 2024 05:50:55 +0100 Subject: [PATCH 081/231] Update src/sage/combinat/root_system/root_lattice_realization_algebras.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Matthias Köppe --- .../combinat/root_system/root_lattice_realization_algebras.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/combinat/root_system/root_lattice_realization_algebras.py b/src/sage/combinat/root_system/root_lattice_realization_algebras.py index 60b27183426..db3811b820d 100644 --- a/src/sage/combinat/root_system/root_lattice_realization_algebras.py +++ b/src/sage/combinat/root_system/root_lattice_realization_algebras.py @@ -584,7 +584,7 @@ def demazure_lusztig_operators(self, q1, q2, convention="antidominant"): to specify explicitly the elements on which to run the tests:: - sage: for cartan_type in CartanType.samples(crystallographic=True): # long time (12s) + sage: for cartan_type in CartanType.samples(crystallographic=True): # long time (12s) ....: L = RootSystem(cartan_type).ambient_space() ....: KL = L.algebra(K) ....: weight_lattice = RootSystem(cartan_type).weight_lattice(extended=L.is_extended()) From 641e8353ce57d76f4c77e936d3368fa2aaaeb42f Mon Sep 17 00:00:00 2001 From: Gareth Ma Date: Thu, 20 Jun 2024 08:12:25 +0100 Subject: [PATCH 082/231] lint --- src/sage/schemes/affine/affine_space.py | 2 +- src/sage/schemes/projective/projective_space.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/schemes/affine/affine_space.py b/src/sage/schemes/affine/affine_space.py index 848afc9bf27..f9b572b9527 100644 --- a/src/sage/schemes/affine/affine_space.py +++ b/src/sage/schemes/affine/affine_space.py @@ -336,7 +336,7 @@ def _latex_(self): TESTS:: - sage: AffineSpace(11, Zp(5), 'y')._latex_() # needs sage.rings.padics + sage: AffineSpace(11, Zp(5), 'y')._latex_() # needs sage.rings.padics '\\mathbf{A}_{\\Bold{Z}_{5}}^{11}' """ return "\\mathbf{A}_{%s}^{%s}" % (latex(self.base_ring()), self.dimension_relative()) diff --git a/src/sage/schemes/projective/projective_space.py b/src/sage/schemes/projective/projective_space.py index 15c68f47dcc..89126d4e6ce 100644 --- a/src/sage/schemes/projective/projective_space.py +++ b/src/sage/schemes/projective/projective_space.py @@ -594,7 +594,7 @@ def _latex_(self): TESTS:: - sage: ProjectiveSpace(11, Zp(5), 'y')._latex_() # needs sage.rings.padics + sage: ProjectiveSpace(11, Zp(5), 'y')._latex_() # needs sage.rings.padics '{\\mathbf P}_{\\Bold{Z}_{5}}^{11}' """ return "{\\mathbf P}_{%s}^{%s}" % (latex(self.base_ring()), self.dimension_relative()) From 3c1de04cadd43983ef8630c07b747eb2c752eae2 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 20 Jun 2024 17:30:56 -0700 Subject: [PATCH 083/231] .ci/write-dockerfile.sh, docker/Dockerfile: Fix Docker warning FromAsCasing: 'as' and 'FROM' keywords' casing do not match --- .ci/write-dockerfile.sh | 18 +++++++++--------- docker/Dockerfile | 32 ++++++++++++++++---------------- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/.ci/write-dockerfile.sh b/.ci/write-dockerfile.sh index 3a4ae5b152d..602da1382a9 100755 --- a/.ci/write-dockerfile.sh +++ b/.ci/write-dockerfile.sh @@ -55,7 +55,7 @@ ADD="ADD $__CHOWN" RUN=RUN cat <> /etc/sudoers.d/01-sage \ && chmod 0440 /etc/sudoers.d/01-sage -# Run everything from now on as the sage user in sage's home +# Run everything from now on AS the sage user in sage's home USER sage ENV HOME $HOME WORKDIR $HOME @@ -108,7 +108,7 @@ WORKDIR $HOME # Image containing everything so that a make in a clone of the Sage repository # # completes without errors # ################################################################################ -FROM run-time-dependencies as build-time-dependencies +FROM run-time-dependencies AS build-time-dependencies # Install the build time dependencies & git & rdfind RUN sudo apt-get -qq update \ && sudo apt-get -qq install -y wget build-essential automake m4 dpkg-dev python3 libssl-dev git rdfind \ @@ -118,7 +118,7 @@ RUN sudo apt-get -qq update \ ################################################################################ # Image with an empty git repository in $SAGE_ROOT. # ################################################################################ -FROM build-time-dependencies as source-clean +FROM build-time-dependencies AS source-clean ARG SAGE_ROOT=/home/sage/sage RUN mkdir -p "$SAGE_ROOT" WORKDIR $SAGE_ROOT @@ -135,7 +135,7 @@ RUN git remote add upstream https://github.com/sagemath/sage.git # build is not going to use the build-time-dependencies target but rely on # # whatever tools are installed in ARTIFACT_BASE. # ################################################################################ -FROM $ARTIFACT_BASE as source-from-context +FROM $ARTIFACT_BASE AS source-from-context WORKDIR $HOME COPY --chown=sage:sage . sage-context # Checkout the commit that is checked out in $HOME/sage-context @@ -183,7 +183,7 @@ RUN patch -p1 < "$HOME"/sage-context.patch ################################################################################ # Image with a built sage but without sage's documentation. # ################################################################################ -FROM source-from-context as make-build +FROM source-from-context AS make-build # Make sure that the result runs on most CPUs. ENV SAGE_FAT_BINARY yes # Just to be sure Sage doesn't try to build its own GCC (even though @@ -204,7 +204,7 @@ RUN make build ################################################################################ # Image with a full build of sage and its documentation. # ################################################################################ -FROM $MAKE_BUILD as make-all +FROM $MAKE_BUILD AS make-all # The docbuild needs quite some RAM (as of May 2018). It sometimes calls # os.fork() to spawn an external program which then exceeds easily the # overcommit limit of the system (no RAM is actually used, but this limit is @@ -218,7 +218,7 @@ RUN make ################################################################################ # Image with a full build of sage, ready to release. # ################################################################################ -FROM make-all as make-release +FROM make-all AS make-release RUN make micro_release ################################################################################ @@ -226,7 +226,7 @@ RUN make micro_release # temporary build artifacts which is set up to start the command line # # interface if no parameters are passed in. # ################################################################################ -FROM run-time-dependencies as sagemath +FROM run-time-dependencies AS sagemath ARG HOME=/home/sage ARG SAGE_ROOT=/home/sage/sage COPY --chown=sage:sage --from=make-release $SAGE_ROOT/ $SAGE_ROOT/ @@ -244,7 +244,7 @@ CMD ["sage"] # Image with a full build of sage and its documentation but everything # # stripped that can be quickly rebuild by make. # ################################################################################ -FROM make-all as make-fast-rebuild-clean +FROM make-all AS make-fast-rebuild-clean # Of course, without site-packages/sage, sage does not start but copying/compiling # them from build/pkgs/sagelib/src/build is very fast. RUN make fast-rebuild-clean; \ @@ -255,7 +255,7 @@ RUN make fast-rebuild-clean; \ # identical to make-fast-rebuild-clean or contains a "patch" which can be used # # to upgrade ARTIFACT_BASE to make-fast-rebuild-clean. # ################################################################################ -FROM make-fast-rebuild-clean as sagemath-dev-patch +FROM make-fast-rebuild-clean AS sagemath-dev-patch ARG ARTIFACT_BASE=source-clean ARG SAGE_ROOT=/home/sage/sage # Build a patch containing of a tar file which contains all the modified files @@ -277,13 +277,13 @@ RUN if [ x"$ARTIFACT_BASE" != x"source-clean" ]; then \ # the build artifacts intact so developers can make changes and rebuild # # quickly # ################################################################################ -FROM $ARTIFACT_BASE as sagemath-dev +FROM $ARTIFACT_BASE AS sagemath-dev ARG SAGE_ROOT=/home/sage/sage # If docker is backed by aufs, then the following command adds the size of # ARTIFACT_BASE to the image size. As of mid 2018 this is notably the case with # the docker instances provided by setup_remote_docker on CircleCI. As a -# result, the sagemath-dev images that are "build-from-latest" are twice as big -# as the ones that are build on GitLab: +# result, the sagemath-dev images that are "build-from-latest" are twice AS big +# AS the ones that are build on GitLab: # https://github.com/moby/moby/issues/6119#issuecomment-268870519 COPY --chown=sage:sage --from=sagemath-dev-patch $SAGE_ROOT $SAGE_ROOT ARG ARTIFACT_BASE=source-clean From de74fbd90054f6ef4f783ece1b193addd7790926 Mon Sep 17 00:00:00 2001 From: Cyril Bouvier Date: Fri, 21 Jun 2024 13:10:38 +0200 Subject: [PATCH 084/231] graphs: fix lex_BFS for DiGraph --- src/sage/graphs/traversals.pyx | 35 +++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/src/sage/graphs/traversals.pyx b/src/sage/graphs/traversals.pyx index 13fc1c2775a..93fdaa8e73f 100644 --- a/src/sage/graphs/traversals.pyx +++ b/src/sage/graphs/traversals.pyx @@ -76,8 +76,19 @@ def _is_valid_lex_BFS_order(G, L): sage: G = DiGraph("I?O@??A?CCA?A??C??") sage: _is_valid_lex_BFS_order(G, [0, 7, 1, 2, 3, 4, 5, 8, 6, 9]) + False + sage: _is_valid_lex_BFS_order(G, G.lex_BFS()) + True + sage: H = G.to_undirected() + sage: _is_valid_lex_BFS_order(H, G.lex_BFS()) + True + sage: _is_valid_lex_BFS_order(G, H.lex_BFS()) True """ + # Convert G to a simple undirected graph + if G.has_loops() or G.has_multiple_edges() or G.is_directed(): + G = G.to_simple(immutable=False, to_undirected=True) + cdef int n = G.order() if set(L) != set(G): @@ -86,11 +97,9 @@ def _is_valid_lex_BFS_order(G, L): cdef dict L_inv = {u: i for i, u in enumerate(L)} cdef int pos_a, pos_b, pos_c - neighbors = G.neighbor_in_iterator if G.is_directed() else G.neighbor_iterator - for pos_a in range(n - 1, -1, -1): a = L[pos_a] - for c in neighbors(a): + for c in G.neighbor_iterator(a): pos_c = L_inv[c] if pos_c > pos_a: continue @@ -99,7 +108,7 @@ def _is_valid_lex_BFS_order(G, L): if G.has_edge(c, b): continue if any(L_inv[d] < pos_c and not G.has_edge(d, a) - for d in neighbors(b)): + for d in G.neighbor_iterator(b)): # The condition is satisfied for a < b < c continue return False @@ -258,6 +267,9 @@ def lex_BFS(G, reverse=False, tree=False, initial_vertex=None, algorithm="fast") algorithm is in `O(n + m)`, and our implementation follows that complexity. See [HMPV2000]_ and next section for more details. + Loops and multiple edges are ignored during the computation of lex_BFS and + directed graphs are converted to undirected graphs. + ALGORITHM: The ``"fast"`` algorithm is the `O(n + m)` time algorithm proposed in @@ -314,10 +326,11 @@ def lex_BFS(G, reverse=False, tree=False, initial_vertex=None, algorithm="fast") The method also works for directed graphs:: sage: G = DiGraph([(1, 2), (2, 3), (1, 3)]) - sage: G.lex_BFS(initial_vertex=2, algorithm="slow") - [2, 3, 1] - sage: G.lex_BFS(initial_vertex=2, algorithm="fast") - [2, 3, 1] + sage: correct_anwsers = [[2, 1, 3], [2, 3, 1]] + sage: G.lex_BFS(initial_vertex=2, algorithm="slow") in correct_anwsers + True + sage: G.lex_BFS(initial_vertex=2, algorithm="fast") in correct_anwsers + True For a Chordal Graph, a reversed Lex BFS is a Perfect Elimination Order:: @@ -407,9 +420,9 @@ def lex_BFS(G, reverse=False, tree=False, initial_vertex=None, algorithm="fast") if tree: from sage.graphs.digraph import DiGraph - # Loops and multiple edges are not needed in Lex BFS - if G.has_loops() or G.has_multiple_edges(): - G = G.to_simple(immutable=False) + # Convert G to a simple undirected graph + if G.has_loops() or G.has_multiple_edges() or G.is_directed(): + G = G.to_simple(immutable=False, to_undirected=True) cdef size_t n = G.order() if not n: From b61a9f4e065f642439989c93c40b0c59f76d505b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20K=C3=B6ppe?= Date: Fri, 21 Jun 2024 10:56:57 -0700 Subject: [PATCH 085/231] Undo unintended changes Co-authored-by: Sebastian Oehms <47305845+soehms@users.noreply.github.com> --- .ci/write-dockerfile.sh | 2 +- docker/Dockerfile | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.ci/write-dockerfile.sh b/.ci/write-dockerfile.sh index 602da1382a9..ec25f88da23 100755 --- a/.ci/write-dockerfile.sh +++ b/.ci/write-dockerfile.sh @@ -77,7 +77,7 @@ case $SYSTEM in *) # # The Ubuntu Docker images are "minimized", meaning that some large - # bits such AS documentation has been removed. We have to unminimize + # bits such as documentation has been removed. We have to unminimize # once (which reinstalls the full versions of some minimized packages), # or e.g. the maxima documentation (which we depend on for correct operation) # will be missing. diff --git a/docker/Dockerfile b/docker/Dockerfile index 1a695d3d7b0..a97664b2292 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -93,13 +93,13 @@ RUN apt-get -qq update \ && apt-get -qq install -y --no-install-recommends gfortran gcc g++ libstdc++-10-dev sudo openssl \ && apt-get -qq clean \ && rm -r /var/lib/apt/lists/* -# Sage refuses to build AS root, so we add a "sage" user that can sudo without a password. -# We also want this user at runtime AS some commands in sage know about the user that was used during build. +# Sage refuses to build as root, so we add a "sage" user that can sudo without a password. +# We also want this user at runtime as some commands in sage know about the user that was used during build. ARG HOME=/home/sage RUN adduser --quiet --shell /bin/bash --gecos "Sage user,101,," --disabled-password --home "$HOME" sage \ && echo "sage ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers.d/01-sage \ && chmod 0440 /etc/sudoers.d/01-sage -# Run everything from now on AS the sage user in sage's home +# Run everything from now on as the sage user in sage's home USER sage ENV HOME $HOME WORKDIR $HOME @@ -283,7 +283,7 @@ ARG SAGE_ROOT=/home/sage/sage # ARTIFACT_BASE to the image size. As of mid 2018 this is notably the case with # the docker instances provided by setup_remote_docker on CircleCI. As a # result, the sagemath-dev images that are "build-from-latest" are twice AS big -# AS the ones that are build on GitLab: +# as the ones that are build on GitLab: # https://github.com/moby/moby/issues/6119#issuecomment-268870519 COPY --chown=sage:sage --from=sagemath-dev-patch $SAGE_ROOT $SAGE_ROOT ARG ARTIFACT_BASE=source-clean From e74fb37940440452fc34ec758d2bbf4e13901178 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sat, 22 Jun 2024 13:54:27 +0200 Subject: [PATCH 086/231] some pep8 cleanup in four crystal files --- src/sage/combinat/crystals/alcove_path.py | 288 +++++++++--------- src/sage/combinat/crystals/bkk_crystals.py | 18 +- .../crystals/generalized_young_walls.py | 103 +++---- .../combinat/crystals/kirillov_reshetikhin.py | 250 ++++++++------- 4 files changed, 333 insertions(+), 326 deletions(-) diff --git a/src/sage/combinat/crystals/alcove_path.py b/src/sage/combinat/crystals/alcove_path.py index 27222de68c7..9c5ac8d53f5 100644 --- a/src/sage/combinat/crystals/alcove_path.py +++ b/src/sage/combinat/crystals/alcove_path.py @@ -250,7 +250,7 @@ def __classcall_private__(cls, starting_weight, cartan_type=None, sage: B1 is B2 True """ - if isinstance(cartan_type, bool): # new style signature, optional arguments leak over + if isinstance(cartan_type, bool): # new style signature, optional arguments leak over highest_weight_crystal = cartan_type elif isinstance(cartan_type, (list, tuple)): # old style signature # switch positional arguments @@ -270,9 +270,10 @@ def __classcall_private__(cls, starting_weight, cartan_type=None, P = R.weight_space(extended=extended) Lambda = P.basis() offset = R.index_set()[Integer(0)] - starting_weight = P.sum(starting_weight[j-offset]*Lambda[j] for j in R.index_set()) + starting_weight = P.sum(starting_weight[j - offset] * Lambda[j] + for j in R.index_set()) - #set defaults + # set defaults if highest_weight_crystal is None: highest_weight_crystal = True @@ -334,9 +335,9 @@ def __init__(self, starting_weight, highest_weight_crystal): self._R = RootsWithHeight(starting_weight) self._finite_cartan_type = False - self.module_generators = ( self.element_class(self, ()), ) + self.module_generators = (self.element_class(self, ()),) - def _repr_(self): + def _repr_(self) -> str: """ Return a string representation of ``self``. @@ -367,7 +368,7 @@ def _element_constructor_(self, data): return self.element_class(self, data) elif isinstance(data, list): lambda_chain = self._R.lambda_chain() - #data starts indexing at 0 + # data starts indexing at 0 return self.element_class(self, tuple(sorted([lambda_chain[i] for i in data]))) def vertices(self): @@ -420,12 +421,12 @@ def vertices(self): # lst contains ordered pairs (w,l) l= list of positions that get # you to the word, it needs to be refreshed - #initialization + # initialization lst = [] for i in range(len_lambda_chain): associated_reflection = lambda_chain[i].root.associated_reflection() if len(associated_reflection) == 1: - lst.append( (prod([ s[j] for j in associated_reflection ]), [i]) ) + lst.append((prod([s[j] for j in associated_reflection]), [i])) l = copy(lst) @@ -435,16 +436,16 @@ def vertices(self): suc = getattr(x[0], successors)() for j in range(x[1][-1]+1, len_lambda_chain): temp = x[0] * prod( - [ s[k] for k in lambda_chain[j].root.associated_reflection() ]) + [s[k] for k in lambda_chain[j].root.associated_reflection()]) if temp in suc: - lst2.append((temp,x[1]+[j])) - l.append((temp,x[1]+[j])) + lst2.append((temp, x[1]+[j])) + l.append((temp, x[1]+[j])) if lst2 == []: break else: lst = lst2 - return [ [] ] + [i[1] for i in l] + return [[]] + [i[1] for i in l] class CrystalOfAlcovePathsElement(ElementWrapper): @@ -612,8 +613,7 @@ def phi(self, i): raise NotImplementedError # I think the M below should still work in this case - M = Integer(m)/2 - Integer(1)/2 - return M + return Integer(m) / 2 - Integer(1) / 2 def epsilon(self, i): r""" @@ -627,7 +627,7 @@ def epsilon(self, i): sage: [c.epsilon(2) for c in C] [0, 0, 1, 2, 1, 1, 0, 0] """ - #crude but functional + # crude but functional j = 0 temp = self temp = temp.e(i) @@ -682,19 +682,16 @@ def weight(self): WLR = self.parent().weight_lattice_realization() if self.cartan_type().is_affine() and self.parent()._highest_weight_crystal: # We assume that WLR is the (extended) weight lattice - wt = WLR._from_dict({i: Integer(c) for i,c in -weight}, + wt = WLR._from_dict({i: Integer(c) for i, c in -weight}, remove_zeros=False) return wt La = WLR.fundamental_weights() - wt = WLR.sum(Integer(c) * La[i] for i,c in -weight) + wt = WLR.sum(Integer(c) * La[i] for i, c in -weight) if self.cartan_type().is_affine(): assert not self.parent()._highest_weight_crystal wt -= La[0] * wt.level() return wt - #def __repr__(self): - #return str(self.integer_sequence()) - def plot(self): r""" Return a plot ``self``. @@ -716,7 +713,7 @@ def plot(self): for i in integer_sequence: foldings[i] = True affine_ambient_space = RootSystem(ct.affine()).ambient_space() - return affine_ambient_space.plot() + affine_ambient_space.plot_alcove_walk( word, foldings=foldings, labels=False) + return affine_ambient_space.plot() + affine_ambient_space.plot_alcove_walk(word, foldings=foldings, labels=False) def _richcmp_(self, other, op): r""" @@ -855,11 +852,11 @@ def _folding_data(self, i): for k in range(int(c1), int(c2)): - x = R( sign_Beta * Beta , k) + x = R(sign_Beta * Beta, k) if ( - ( j < len(J) - 1 and J[j] < x <= J[j+1] ) or - ( j == len(J) - 1 and J[j] < x) + (j < len(J) - 1 and J[j] < x <= J[j+1]) or + (j == len(J) - 1 and J[j] < x) ): signs[x] = sign_Beta @@ -912,12 +909,13 @@ def e(self, i): # If m_index == 0 then M >=1 guarantees this ###################################################################### - if ( (not finite_cartan_type or i != 0) and m_index < len(gi)-1 # alpha_i is a simple root + if ((not finite_cartan_type or i != 0) and m_index < len(gi) - 1 # alpha_i is a simple root ) or KR_test: J.remove(positions[m_index]) - if m_index+1 < len(positions): # if m_index+1 != 'infinity' - # i.e. positions[m_index+1] makes sense + if m_index + 1 < len(positions): + # if m_index+1 != 'infinity' + # i.e. positions[m_index+1] makes sense J.append(positions[m_index + 1]) return_value = Parent(tuple(sorted(J))) @@ -981,13 +979,15 @@ def _gi(self, i): if not positions: return (positions, [signs['infinity']]) - gi = [ signs[ positions[0] ] ] - for j in range(1,len(positions)): + gi = [signs[positions[0]]] + for j in range(1, len(positions)): gi.append( - gi[j-1] + - signs[positions[j-1]]*self._eps(positions[j-1]) + signs[positions[j]] ) - gi.append( gi[-1] + - signs[positions[-1]]*self._eps(positions[-1]) + signs['infinity'] ) + gi[j-1] + + signs[positions[j-1]] * self._eps(positions[j-1]) + + signs[positions[j]]) + gi.append(gi[-1] + + signs[positions[-1]] * self._eps(positions[-1]) + + signs['infinity']) return (positions, gi) @@ -1040,12 +1040,13 @@ def f(self, i): # # otherwise if m_index - 1 > 0 then (C2) is enough - if ( (not finite_cartan_type or i != 0) and M > 0 # alpha_i is a simple root - ) or KR_test :# KR case + if ((not finite_cartan_type or i != 0) and M > 0 # alpha_i is a simple root + ) or KR_test: # KR case J.append(positions[m_index-1]) - if m_index < len(positions): # if m_index != 'infinity' - # thus positions[m_index] makes sense + if m_index < len(positions): + # if m_index != 'infinity' + # thus positions[m_index] makes sense J.remove(positions[m_index]) return_value = Parent(tuple(sorted(J))) @@ -1124,7 +1125,7 @@ def path(self): W = WeylGroup(self.parent()._R._cartan_type, prefix='s') s = W.simple_reflections() - #start at the identity + # start at the identity w = W.one() ret = [w] for i in self: @@ -1170,9 +1171,9 @@ def __init__(self, cartan_type): self._cartan_type = cartan_type Parent.__init__(self, category=HighestWeightCrystals().Infinite()) - self.module_generators = ( self.element_class(self, (), 0), ) + self.module_generators = (self.element_class(self, (), 0),) - def _repr_(self): + def _repr_(self) -> str: """ Return a string representation of ``self``. @@ -1231,7 +1232,7 @@ def e(self, i): A = CrystalOfAlcovePaths(self.parent()._cartan_type, [shift]*n) try: y = A(tuple([A._R(rt.root, rt.height - s(rt.root)) for rt in y.value])) - except ValueError: # Invalid height (and not admissible) + except ValueError: # Invalid height (and not admissible) break shift += 1 return type(self)(self.parent(), @@ -1271,7 +1272,7 @@ def f(self, i): shift = self._shift + 1 n = self.parent()._cartan_type.rank() A = CrystalOfAlcovePaths(self.parent()._cartan_type, [shift]*n) - y = A(tuple([A._R(rt, h + shift*s(rt)) for rt,h in self.value])).f(i) + y = A(tuple([A._R(rt, h + shift*s(rt)) for rt, h in self.value])).f(i) return type(self)(self.parent(), tuple([(rt.root, rt.height - shift*s(rt.root)) for rt in y.value]), @@ -1391,8 +1392,8 @@ def projection(self, k=None): return None s = lambda rt: int(sum(rt.associated_coroot().coefficients())) n = self.parent()._cartan_type.rank() - A = CrystalOfAlcovePaths(self.parent()._cartan_type, [k]*n) - return A(tuple([A._R(rt, h + k*s(rt)) for rt,h in self.value])) + A = CrystalOfAlcovePaths(self.parent()._cartan_type, [k] * n) + return A(tuple([A._R(rt, h + k*s(rt)) for rt, h in self.value])) class RootsWithHeight(UniqueRepresentation, Parent): @@ -1475,7 +1476,7 @@ def __init__(self, weight): sage: R = RootsWithHeight(['A',2],[3,2]) sage: TestSuite(R).run() """ - Parent.__init__(self, category=Sets() ) + Parent.__init__(self, category=Sets()) cartan_type = weight.parent().cartan_type() self._cartan_type = cartan_type @@ -1535,7 +1536,7 @@ def word(self): cartan_type = self._root_system.cartan_type() if not cartan_type.is_finite(): raise NotImplementedError - lambda_chain = [ x.root for x in self.lambda_chain() ] + lambda_chain = [x.root for x in self.lambda_chain()] coroot_lattice = RootSystem(cartan_type).coroot_lattice() cohighest_root = coroot_lattice.highest_root() @@ -1545,11 +1546,11 @@ def word(self): beta = lambda_chain[i] for j in reversed(range(i)): beta = beta.reflection(lambda_chain[j]) - #beta is now a simple root or the highest root + # beta is now a simple root or the highest root coroot = beta.associated_coroot() - support = coroot.support() # the path is in dual affine space - if len(support) == 1: # beta is a simple root + support = coroot.support() # the path is in dual affine space + if len(support) == 1: # beta is a simple root word.append(support[0]) elif coroot == -cohighest_root: word.append(0) @@ -1576,10 +1577,8 @@ def lambda_chain(self): if not self._root_lattice.cartan_type().is_finite(): raise ValueError("Cartan type {0} is not finite".format(self._root_lattice.cartan_type())) - l = [] - for i in self._root_lattice.positive_roots(): - for j in range(self._max_height(i)): - l.append(self(i,j)) + l = (self(i, j) for i in self._root_lattice.positive_roots() + for j in range(self._max_height(i))) return sorted(l) @@ -1611,7 +1610,7 @@ def _an_element_(self): sage: R._an_element_() (alpha[1], 0) """ - return self( self._root_lattice.from_vector(vector([1])), 0 ) + return self(self._root_lattice.from_vector(vector([1])), 0) class RootsWithHeightElement(Element): @@ -1660,8 +1659,8 @@ def __init__(self, parent, root, height): raise ValueError("%d out of allowed range [%d,%d)" % (height, 0, max_height)) v = [height/max_height] - v.extend( [ x/max_height for x in root.associated_coroot().to_vector() ] ) - #v.insert(0, height/max_height) + v.extend(x/max_height for x in root.associated_coroot().to_vector()) + # v.insert(0, height/max_height) # the map from (root, height) --> _cmp_v is injective @@ -1744,8 +1743,8 @@ def _richcmp_(self, other, op): # I suspect that if you redefine this method to produce a # different (valid) `\lambda`-chain the rest of the # code should still work. - #todo: check if self and other have the same parent ? - #assert self.parent() is other.parent(), "elements have different parents" + # todo: check if self and other have the same parent ? + # assert self.parent() is other.parent(), "elements have different parents" return richcmp(self._cmp_v, other._cmp_v, op) @@ -1771,24 +1770,24 @@ def _test_some_specific_examples(clss=CrystalOfAlcovePaths): True """ # This appears in Lenart. - C = clss(['G',2],[0,1]) + C = clss(['G', 2], [0, 1]) G = C.digraph() GT = DiGraph({ - () : {(0) : 2 }, - (0) : {(0,8) : 1 }, - (0,1) : {(0,1,7) : 2 }, - (0,1,2) : {(0,1,2,9) : 1 }, - (0,1,2,3) : {(0,1,2,3,4) : 2 }, - (0,1,2,6) : {(0,1,2,3) : 1 }, - (0,1,2,9) : {(0,1,2,6) : 1 }, - (0,1,7) : {(0,1,2) : 2 }, - (0,1,7,9) : {(0,1,2,9) : 2 }, - (0,5) : {(0,1) : 1, (0,5,7) : 2 }, - (0,5,7) : {(0,5,7,9) : 1 }, - (0,5,7,9) : {(0,1,7,9) : 1 }, - (0,8) : {(0,5) : 1 } - }) + (): {(0): 2}, + (0): {(0, 8): 1}, + (0, 1): {(0, 1, 7): 2}, + (0, 1, 2): {(0, 1, 2, 9): 1}, + (0, 1, 2, 3): {(0, 1, 2, 3, 4): 2}, + (0, 1, 2, 6): {(0, 1, 2, 3): 1}, + (0, 1, 2, 9): {(0, 1, 2, 6): 1}, + (0, 1, 7): {(0, 1, 2): 2}, + (0, 1, 7, 9): {(0, 1, 2, 9): 2}, + (0, 5): {(0, 1): 1, (0, 5, 7): 2}, + (0, 5, 7): {(0, 5, 7, 9): 1}, + (0, 5, 7, 9): {(0, 1, 7, 9): 1}, + (0, 8): {(0, 5): 1} + }) if not G.is_isomorphic(GT): return False @@ -1798,23 +1797,23 @@ def _test_some_specific_examples(clss=CrystalOfAlcovePaths): # Some examples from Hong--Kang: # type C, ex. 8.3.5, pg. 189 - C = clss(['C',3],[0,0,1]) + C = clss(['C', 3], [0, 0, 1]) G = C.digraph() GT = DiGraph({ - ():{ (0): 3}, - (0):{ (0, 6): 2}, - (0, 1):{ (0, 1, 3): 3, (0, 1, 7): 1}, - (0, 1, 2):{ (0, 1, 2, 3): 3}, - (0, 1, 2, 3):{ (0, 1, 2, 3, 8): 2}, - (0, 1, 2, 3, 4):{ (0, 1, 2, 3, 4, 5): 3}, - (0, 1, 2, 3, 8):{ (0, 1, 2, 3, 4): 2}, - (0, 1, 3):{ (0, 1, 3, 7): 1}, - (0, 1, 3, 7):{ (0, 1, 2, 3): 1, (0, 1, 3, 7, 8): 2}, - (0, 1, 3, 7, 8):{ (0, 1, 2, 3, 8): 1}, - (0, 1, 7):{ (0, 1, 2): 1, (0, 1, 3, 7): 3}, - (0, 6):{ (0, 1): 2, (0, 6, 7): 1}, - (0, 6, 7):{ (0, 1, 7): 2} - }) + (): {(0): 3}, + (0): {(0, 6): 2}, + (0, 1): {(0, 1, 3): 3, (0, 1, 7): 1}, + (0, 1, 2): {(0, 1, 2, 3): 3}, + (0, 1, 2, 3): {(0, 1, 2, 3, 8): 2}, + (0, 1, 2, 3, 4): {(0, 1, 2, 3, 4, 5): 3}, + (0, 1, 2, 3, 8): {(0, 1, 2, 3, 4): 2}, + (0, 1, 3): {(0, 1, 3, 7): 1}, + (0, 1, 3, 7): {(0, 1, 2, 3): 1, (0, 1, 3, 7, 8): 2}, + (0, 1, 3, 7, 8): {(0, 1, 2, 3, 8): 1}, + (0, 1, 7): {(0, 1, 2): 1, (0, 1, 3, 7): 3}, + (0, 6): {(0, 1): 2, (0, 6, 7): 1}, + (0, 6, 7): {(0, 1, 7): 2} + }) if not G.is_isomorphic(GT): return False @@ -1822,68 +1821,68 @@ def _test_some_specific_examples(clss=CrystalOfAlcovePaths): print("C3 example passed.") # type B, fig. 8.1 pg. 172 - C = clss(['B',3],[2,0,0]) + C = clss(['B', 3], [2, 0, 0]) G = C.digraph() GT = DiGraph({ - ():{ (6): 1}, - (0):{ (0, 7): 2}, - (0, 1):{ (0, 1, 11): 3}, - (0, 1, 2):{ (0, 1, 2, 9): 2}, - (0, 1, 2, 3):{ (0, 1, 2, 3, 10): 1}, - (0, 1, 2, 3, 10):{ (0, 1, 2, 3, 4): 1}, - (0, 1, 2, 9):{ (0, 1, 2, 3): 2, (0, 1, 2, 9, 10): 1}, - (0, 1, 2, 9, 10):{ (0, 1, 2, 3, 10): 2}, - (0, 1, 5):{ (0, 1, 2): 3, (0, 1, 5, 9): 2}, - (0, 1, 5, 9):{ (0, 1, 2, 9): 3, (0, 1, 5, 9, 10): 1}, - (0, 1, 5, 9, 10):{ (0, 1, 2, 9, 10): 3}, - (0, 1, 8):{ (0, 1, 5): 3}, - (0, 1, 8, 9):{ (0, 1, 5, 9): 3, (0, 1, 8, 9, 10): 1}, - (0, 1, 8, 9, 10):{ (0, 1, 5, 9, 10): 3}, - (0, 1, 11):{ (0, 1, 8): 3}, - (0, 7):{ (0, 1): 2, (0, 7, 11): 3}, - (0, 7, 8):{ (0, 7, 8, 9): 2}, - (0, 7, 8, 9):{ (0, 1, 8, 9): 2}, - (0, 7, 8, 9, 10):{ (0, 1, 8, 9, 10): 2}, - (0, 7, 11):{ (0, 1, 11): 2, (0, 7, 8): 3}, - (6):{ (0): 1, (6, 7): 2}, - (6, 7):{ (0, 7): 1, (6, 7, 11): 3}, - (6, 7, 8):{ (0, 7, 8): 1, (6, 7, 8, 9): 2}, - (6, 7, 8, 9):{ (6, 7, 8, 9, 10): 1}, - (6, 7, 8, 9, 10):{ (0, 7, 8, 9, 10): 1}, - (6, 7, 11):{ (0, 7, 11): 1, (6, 7, 8): 3} - }) + (): {(6): 1}, + (0): {(0, 7): 2}, + (0, 1): {(0, 1, 11): 3}, + (0, 1, 2): {(0, 1, 2, 9): 2}, + (0, 1, 2, 3): {(0, 1, 2, 3, 10): 1}, + (0, 1, 2, 3, 10): {(0, 1, 2, 3, 4): 1}, + (0, 1, 2, 9): {(0, 1, 2, 3): 2, (0, 1, 2, 9, 10): 1}, + (0, 1, 2, 9, 10): {(0, 1, 2, 3, 10): 2}, + (0, 1, 5): {(0, 1, 2): 3, (0, 1, 5, 9): 2}, + (0, 1, 5, 9): {(0, 1, 2, 9): 3, (0, 1, 5, 9, 10): 1}, + (0, 1, 5, 9, 10): {(0, 1, 2, 9, 10): 3}, + (0, 1, 8): {(0, 1, 5): 3}, + (0, 1, 8, 9): {(0, 1, 5, 9): 3, (0, 1, 8, 9, 10): 1}, + (0, 1, 8, 9, 10): {(0, 1, 5, 9, 10): 3}, + (0, 1, 11): {(0, 1, 8): 3}, + (0, 7): {(0, 1): 2, (0, 7, 11): 3}, + (0, 7, 8): {(0, 7, 8, 9): 2}, + (0, 7, 8, 9): {(0, 1, 8, 9): 2}, + (0, 7, 8, 9, 10): {(0, 1, 8, 9, 10): 2}, + (0, 7, 11): {(0, 1, 11): 2, (0, 7, 8): 3}, + (6): {(0): 1, (6, 7): 2}, + (6, 7): {(0, 7): 1, (6, 7, 11): 3}, + (6, 7, 8): {(0, 7, 8): 1, (6, 7, 8, 9): 2}, + (6, 7, 8, 9): {(6, 7, 8, 9, 10): 1}, + (6, 7, 8, 9, 10): {(0, 7, 8, 9, 10): 1}, + (6, 7, 11): {(0, 7, 11): 1, (6, 7, 8): 3} + }) if not G.is_isomorphic(GT): return False else: print("B3 example 1 passed.") - C = clss(['B',3],[0,1,0]) + C = clss(['B', 3], [0, 1, 0]) G = C.digraph() GT = DiGraph({ - ():{ (0): 2}, - (0):{ (0, 1): 1, (0, 7): 3}, - (0, 1):{ (0, 1, 7): 3}, - (0, 1, 2):{ (0, 1, 2, 8): 2}, - (0, 1, 2, 3):{ (0, 1, 2, 3, 5): 1, (0, 1, 2, 3, 9): 3}, - (0, 1, 2, 3, 4):{ (0, 1, 2, 3, 4, 5): 1}, - (0, 1, 2, 3, 4, 5):{ (0, 1, 2, 3, 4, 5, 6): 2}, - (0, 1, 2, 3, 5):{ (0, 1, 2, 3, 5, 9): 3}, - (0, 1, 2, 3, 5, 9):{ (0, 1, 2, 3, 4, 5): 3}, - (0, 1, 2, 3, 9):{ (0, 1, 2, 3, 4): 3, (0, 1, 2, 3, 5, 9): 1}, - (0, 1, 2, 5):{ (0, 1, 2, 3, 5): 2}, - (0, 1, 2, 8):{ (0, 1, 2, 3): 2}, - (0, 1, 2, 8, 9):{ (0, 1, 2, 3, 9): 2}, - (0, 1, 7):{ (0, 1, 2): 3, (0, 1, 7, 8): 2}, - (0, 1, 7, 8):{ (0, 1, 7, 8, 9): 3}, - (0, 1, 7, 8, 9):{ (0, 1, 2, 8, 9): 3}, - (0, 2):{ (0, 1, 2): 1, (0, 2, 5): 2}, - (0, 2, 5):{ (0, 2, 5, 8): 1}, - (0, 2, 5, 8):{ (0, 1, 2, 5): 1}, - (0, 7):{ (0, 1, 7): 1, (0, 2): 3} - }) + (): {(0): 2}, + (0): {(0, 1): 1, (0, 7): 3}, + (0, 1): {(0, 1, 7): 3}, + (0, 1, 2): {(0, 1, 2, 8): 2}, + (0, 1, 2, 3): {(0, 1, 2, 3, 5): 1, (0, 1, 2, 3, 9): 3}, + (0, 1, 2, 3, 4): {(0, 1, 2, 3, 4, 5): 1}, + (0, 1, 2, 3, 4, 5): {(0, 1, 2, 3, 4, 5, 6): 2}, + (0, 1, 2, 3, 5): {(0, 1, 2, 3, 5, 9): 3}, + (0, 1, 2, 3, 5, 9): {(0, 1, 2, 3, 4, 5): 3}, + (0, 1, 2, 3, 9): {(0, 1, 2, 3, 4): 3, (0, 1, 2, 3, 5, 9): 1}, + (0, 1, 2, 5): {(0, 1, 2, 3, 5): 2}, + (0, 1, 2, 8): {(0, 1, 2, 3): 2}, + (0, 1, 2, 8, 9): {(0, 1, 2, 3, 9): 2}, + (0, 1, 7): {(0, 1, 2): 3, (0, 1, 7, 8): 2}, + (0, 1, 7, 8): {(0, 1, 7, 8, 9): 3}, + (0, 1, 7, 8, 9): {(0, 1, 2, 8, 9): 3}, + (0, 2): {(0, 1, 2): 1, (0, 2, 5): 2}, + (0, 2, 5): {(0, 2, 5, 8): 1}, + (0, 2, 5, 8): {(0, 1, 2, 5): 1}, + (0, 7): {(0, 1, 7): 1, (0, 2): 3} + }) if not G.is_isomorphic(GT): return False @@ -1919,9 +1918,9 @@ def compare_graphs(g1, g2, node1, node2): sage: compare_graphs(G1, G2, C( () ), G2.vertices(sort=True)[0]) True """ - for out_edge in g1.outgoing_edges( node1 ): + for out_edge in g1.outgoing_edges(node1): matched = False - for o2 in g2.outgoing_edges( node2 ): + for o2 in g2.outgoing_edges(node2): if o2[2] == out_edge[2]: if matched: print("ERROR: Two edges with the same label for ", out_edge, " exist.") @@ -1965,16 +1964,17 @@ def _test_against_tableaux(R, N, k, clss=CrystalOfAlcovePaths): T = CrystalOfTableaux(R, shape=shape) ct = len(T.list()) print(" T has ", ct, " nodes.") - #T.digraph().show(edge_labels=True) + # T.digraph().show(edge_labels=True) H = T.digraph() weight = T.module_generators[0].weight() - w = [ weight.scalar(RootSystem(R).ambient_space().simple_coroot(i)) for i in range(1,N+1) ] + w = [weight.scalar(RootSystem(R).ambient_space().simple_coroot(i)) + for i in range(1, N + 1)] print(" C weight ", w) - C = clss(R , w) + C = clss(R, w) cc = len(C.list()) - #C.digraph().show(edge_labels=True) + # C.digraph().show(edge_labels=True) G = C.digraph() print(" C has ", cc, " nodes.") if cc != ct: diff --git a/src/sage/combinat/crystals/bkk_crystals.py b/src/sage/combinat/crystals/bkk_crystals.py index b3658fd28a4..785f3fc7619 100644 --- a/src/sage/combinat/crystals/bkk_crystals.py +++ b/src/sage/combinat/crystals/bkk_crystals.py @@ -3,7 +3,7 @@ Benkart-Kang-Kashiwara crystals for the general-linear Lie superalgebra """ -#***************************************************************************** +# **************************************************************************** # Copyright (C) 2017 Franco Saliola # 2017 Travis Scrimshaw # 2017 Anne Schilling @@ -12,8 +12,8 @@ # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. -# http://www.gnu.org/licenses/ -#***************************************************************************** +# https://www.gnu.org/licenses/ +# **************************************************************************** from sage.structure.parent import Parent from sage.categories.regular_supercrystals import RegularSuperCrystals @@ -60,7 +60,7 @@ def __classcall_private__(cls, ct, shape): """ ct = CartanType(ct) shape = _Partitions(shape) - if len(shape) > ct.m + 1 and shape[ct.m+1] > ct.n + 1: + if len(shape) > ct.m + 1 and shape[ct.m + 1] > ct.n + 1: raise ValueError("invalid hook shape") return super().__classcall__(cls, ct, shape) @@ -80,16 +80,14 @@ def __init__(self, ct, shape): C = CrystalOfBKKLetters(ct) tr = shape.conjugate() mg = [] - for i,col_len in enumerate(tr): - for j in range(col_len - m): - mg.append(C(i+1)) - for j in range(max(0, m - col_len), m): - mg.append(C(-j-1)) + for i, col_len in enumerate(tr, start=1): + mg.extend(C(i) for j in range(col_len - m)) + mg.extend(C(-j - 1) for j in range(max(0, m - col_len), m)) mg = list(reversed(mg)) Parent.__init__(self, category=RegularSuperCrystals()) self.module_generators = (self.element_class(self, mg),) - def _repr_(self): + def _repr_(self) -> str: """ Return a string representation of ``self``. diff --git a/src/sage/combinat/crystals/generalized_young_walls.py b/src/sage/combinat/crystals/generalized_young_walls.py index 12ab091f6cd..8dc22fbc992 100644 --- a/src/sage/combinat/crystals/generalized_young_walls.py +++ b/src/sage/combinat/crystals/generalized_young_walls.py @@ -20,7 +20,7 @@ - [KS2010]_ """ -#****************************************************************************** +# ***************************************************************************** # Copyright (C) 2013 # # Lucas David-Roesler (roesler at lvc dot edu) @@ -28,8 +28,8 @@ # Travis Scrimshaw (tscrim at ucdavis dot edu) # # Distributed under the terms of the GNU General Public License (GPL) -# http://www.gnu.org/licenses/ -#****************************************************************************** +# https://www.gnu.org/licenses/ +# ***************************************************************************** import re from copy import deepcopy @@ -69,7 +69,7 @@ def __init__(self, parent, data): sage: mg = Y.module_generators[0] sage: TestSuite(mg).run() """ - i = len(data)-1 + i = len(data) - 1 while i >= 0 and not data[i]: data.pop() i -= 1 @@ -118,7 +118,7 @@ def _repr_diagram(self): wall += '|' if row == []: wall += '|' - ret += wall.rjust(2*self.cols+1) + "\n" + ret += wall.rjust(2 * self.cols + 1) + "\n" return ret def _ascii_art_(self): @@ -175,9 +175,9 @@ def _unicode_art_(self): import unicodedata v = unicodedata.lookup('BOX DRAWINGS LIGHT VERTICAL') vl = unicodedata.lookup('BOX DRAWINGS LIGHT VERTICAL AND LEFT') - table = [[None]*(self.cols-len(row)) + row for row in reversed(self)] + table = [[None] * (self.cols - len(row)) + row for row in reversed(self)] ret = [] - for i,row in enumerate(ascii_art_table(table, use_unicode=True).splitlines()): + for i, row in enumerate(ascii_art_table(table, use_unicode=True).splitlines()): if row[-1] == " ": if i % 2 == 0: ret.append(row[:-1] + vl) @@ -228,19 +228,19 @@ def raw_signature(self, i): [['-', 3, 6], ['-', 1, 4], ['-', 6, 1]] """ sig = [] - rank = self.parent().cartan_type().rank() # n+1 + rank = self.parent().cartan_type().rank() # n+1 for row in range(self.rows): - if self.data[row] == [] and i == ( row % rank ): + if self.data[row] == [] and i == (row % rank): sig.append(['+', row, 0]) elif self.data[row] == []: continue - elif self.data[row][-1] == ( (i+1) % rank ): - sig.append(['+', row, len(self.data[row])+1]) + elif self.data[row][-1] == ((i + 1) % rank): + sig.append(['+', row, len(self.data[row]) + 1]) elif self.data[row][-1] == i: sig.append(['-', row, len(self.data[row])]) return sorted(sig, key=self._sig_sort) - def _sig_sort(self,a): + def _sig_sort(self, a): r""" Internal command used to appropriately sort the output from :meth:`raw_signature()`. @@ -256,7 +256,7 @@ def _sig_sort(self,a): sage: hw._sig_sort(['+',1,0]) (0, 1) """ - return (-a[2],a[1]) + return (-a[2], a[1]) def generate_signature(self, i): r""" @@ -273,20 +273,20 @@ def generate_signature(self, i): sig = [] rank = self.parent().cartan_type().classical().rank() for row in range(self.rows): - if self.data[row] == [] and i == ( row % (rank+1) ): + if self.data[row] == [] and i == (row % (rank + 1)): sig.append(['+', row, 0]) elif self.data[row] == []: continue - elif self.data[row][-1] == ( (i+1) % (rank+1) ): - sig.append(['+', row, len(self.data[row])+1]) + elif self.data[row][-1] == ((i + 1) % (rank + 1)): + sig.append(['+', row, len(self.data[row]) + 1]) elif self.data[row][-1] == i: sig.append(['-', row, len(self.data[row])]) sig = sorted(sig, key=self._sig_sort) - strsig = ''.join( x[0] for x in sig) + strsig = ''.join(x[0] for x in sig) reducedsig = strsig - while re.search(r"\+\s*-",reducedsig): - reducedsig = re.sub(r"\+\s*-", lambda match : ''.ljust(len(match.group(0))) , reducedsig) - return (sig,reducedsig) + while re.search(r"\+\s*-", reducedsig): + reducedsig = re.sub(r"\+\s*-", lambda match: ''.ljust(len(match.group(0))), reducedsig) + return (sig, reducedsig) def signature(self, i): r""" @@ -385,7 +385,7 @@ def number_of_parts(self): sage: y.number_of_parts() 8 """ - n = self.parent().cartan_type().rank()-1 + n = self.parent().cartan_type().rank() - 1 new = self.data[:] i = 0 while i < len(new): @@ -394,7 +394,7 @@ def number_of_parts(self): new.pop(i) elif r[0] == n and len(r) % (n+1) == 0: for j in range(n+1): - temp = [k % (n+1) for k in range(j+len(r)/(n+1)-1,j-1,-1)] + temp = [k % (n+1) for k in range(j+len(r)/(n+1)-1, j-1, -1)] if temp not in new: new.insert(i+1, temp) new.pop(i) @@ -461,11 +461,11 @@ def e(self, i): newdata.append(list(self.data[r][:-1])) else: newdata.append(list(self.data[r])) - return self.__class__(self.parent(),newdata) + return self.__class__(self.parent(), newdata) else: return None - def f(self,i): + def f(self, i): r""" Return the application of the Kashiwara lowering operator `f_i` on ``self``. @@ -514,7 +514,7 @@ def latex_large(self): s += "\\emptyset" else: s += "\\begin{tikzpicture}[baseline=5,scale=.45] \n \\foreach \\x [count=\\s from 0] in \n" - s += "{" + ','.join("{" + ','.join( str(i) for i in r ) + "}" for r in self.data ) + "} \n" + s += "{" + ','.join("{" + ','.join(str(i) for i in r) + "}" for r in self.data) + "} \n" s += "{\\foreach \\y [count=\\t from 0] in \\x { \\node[font=\\scriptsize] at (-\\t,\\s) {$\\y$}; \n \\draw (-\\t+.5,\\s+.5) to (-\\t-.5,\\s+.5); \n \\draw (-\\t+.5,\\s-.5) to (-\\t-.5,\\s-.5); \n \\draw (-\\t-.5,\\s-.5) to (-\\t-.5,\\s+.5); } \n \\draw[-,thick] (.5,\\s+1) to (.5,-.5) to (-\\t-1,-.5); } \n \\end{tikzpicture} \n" return s @@ -530,10 +530,10 @@ def _latex_(self): """ s = "" if self.data == []: - s += "\\emptyset" + s += "\\emptyset" else: s += "\\begin{tikzpicture}[baseline=5,scale=.25] \\foreach \\x [count=\\s from 0] in \n" - s += "{" + ','.join("{" + ','.join( str(i) for i in r ) + "}" for r in self.data ) + "} \n" + s += "{" + ','.join("{" + ','.join(str(i) for i in r) + "}" for r in self.data) + "} \n" s += "{\\foreach \\y [count=\\t from 0] in \\x { \\node[font=\\tiny] at (-\\t,\\s) {$\\y$}; \n \\draw (-\\t+.5,\\s+.5) to (-\\t-.5,\\s+.5); \n \\draw (-\\t+.5,\\s-.5) to (-\\t-.5,\\s-.5); \n \\draw (-\\t-.5,\\s-.5) to (-\\t-.5,\\s+.5); } \n \\draw[-] (.5,\\s+1) to (.5,-.5) to (-\\t-1,-.5); } \n \\end{tikzpicture} \n" return s @@ -554,13 +554,10 @@ def weight(self, root_lattice=False): sage: x.weight(root_lattice=True) -2*alpha[0] - 3*alpha[1] - 5*alpha[2] - 3*alpha[3] """ - W = [] E = self.cartan_type().root_system().weight_lattice(extended=True) L = self.cartan_type().root_system().root_lattice() alpha = L.simple_roots() - for r in self.data: - for i in r: - W.append(-1*alpha[i]) + W = [-1*alpha[i] for r in self.data for i in r] if not root_lattice: return E(sum(W)) return L(sum(W)) @@ -659,7 +656,7 @@ def column(self, k): C.append(None) return C - def a(self,i,k): + def a(self, i, k): r""" Return the number `a_i(k)` of `i`-colored boxes in the ``k``-th column of ``self``. @@ -674,13 +671,11 @@ def a(self,i,k): sage: y.a(3,2) 0 """ - A = [] - for c in range(len(self.column(k))): - if self.column(k)[c] == i: - A.append(self.column(k)[c]) + A = [1 for c in range(len(self.column(k))) + if self.column(k)[c] == i] return len(A) - def in_highest_weight_crystal(self,La): + def in_highest_weight_crystal(self, La): r""" Return a boolean indicating if the generalized Young wall element is in the highest weight crystal cut out by the given highest weight @@ -718,14 +713,14 @@ def in_highest_weight_crystal(self,La): ac = self.parent().weight_lattice_realization().simple_coroots() n = self.cartan_type().classical().rank() index_set = self.index_set() - for k in range(1,self.cols+1): + for k in range(1, self.cols+1): for j in index_set: - if self.a(j,k) - self.a( (j-1) % (n+1) ,k) <= 0: + if self.a(j, k) - self.a((j-1) % (n+1), k) <= 0: continue else: p_not_found = True for p in index_set: - if (j+k) % (n+1) == (p+1) % (n+1) and self.a(j,k) - self.a( (j-1) % (n+1) ,k) <= La.scalar(ac[p]): + if (j+k) % (n+1) == (p+1) % (n+1) and self.a(j, k) - self.a((j-1) % (n+1), k) <= La.scalar(ac[p]): p_not_found = False continue else: @@ -836,7 +831,7 @@ def __classcall_private__(cls, n, category=None): sage: Yinf is Yinf2 True """ - return super().__classcall__(cls,n,category) + return super().__classcall__(cls, n, category) def __init__(self, n, category): r""" @@ -845,15 +840,15 @@ def __init__(self, n, category): sage: Yinf = crystals.infinity.GeneralizedYoungWalls(3) sage: TestSuite(Yinf).run() """ - self._cartan_type = CartanType(['A',n,1]) + self._cartan_type = CartanType(['A', n, 1]) if category is None: category = (HighestWeightCrystals(), InfiniteEnumeratedSets()) Parent.__init__(self, category=category) - self.module_generators = (self.element_class(self,[]),) + self.module_generators = (self.element_class(self, []),) Element = GeneralizedYoungWall - def _element_constructor_(self,data): + def _element_constructor_(self, data): r""" Construct an element of ``self`` from ``data``. @@ -868,7 +863,7 @@ def _element_constructor_(self,data): sage: y [[], [1, 0], [2, 1]] """ - return self.element_class(self,data) + return self.element_class(self, data) def _repr_(self): r""" @@ -882,7 +877,7 @@ def _repr_(self): ######################## -## Highest weight GYW ## +# Highest weight GYW # ######################## class CrystalOfGeneralizedYoungWallsElement(GeneralizedYoungWall): @@ -890,7 +885,7 @@ class CrystalOfGeneralizedYoungWallsElement(GeneralizedYoungWall): Element of the highest weight crystal of generalized Young walls. """ - def e(self,i): + def e(self, i): r""" Compute the action of `e_i` restricted to the highest weight crystal. @@ -907,10 +902,10 @@ def e(self,i): if ret is None: return None if ret.in_highest_weight_crystal(self.parent().hw): - return self.__class__(self.parent(),ret.data) + return self.__class__(self.parent(), ret.data) return None - def f(self,i): + def f(self, i): r""" Compute the action of `f_i` restricted to the highest weight crystal. @@ -926,7 +921,7 @@ def f(self,i): """ ret = GeneralizedYoungWall.f(self, i) if ret.in_highest_weight_crystal(self.parent().hw): - return self.__class__(self.parent(),ret.data) + return self.__class__(self.parent(), ret.data) return None def weight(self): @@ -943,7 +938,7 @@ def weight(self): """ return self.parent().weight_lattice_realization()(self.parent().hw + GeneralizedYoungWall.weight(self)) - def phi(self,i): + def phi(self, i): r""" Return the value `\varepsilon_i(Y) + \langle h_i, \mathrm{wt}(Y)\rangle`, where `h_i` is the `i`-th simple @@ -1029,7 +1024,7 @@ def __classcall_private__(cls, n, La): sage: Y is Y1 True """ - La = RootSystem(['A',n,1]).weight_lattice(extended=True)(La) + La = RootSystem(['A', n, 1]).weight_lattice(extended=True)(La) return super().__classcall__(cls, n, La) def __init__(self, n, La): @@ -1043,8 +1038,8 @@ def __init__(self, n, La): sage: TestSuite(YLa).run(skip=["_test_enumerated_set_contains","_test_stembridge_local_axioms"]) # long time """ - InfinityCrystalOfGeneralizedYoungWalls.__init__( self, n, - category=(RegularCrystals(), HighestWeightCrystals(), InfiniteEnumeratedSets()) ) + InfinityCrystalOfGeneralizedYoungWalls.__init__(self, n, + category=(RegularCrystals(), HighestWeightCrystals(), InfiniteEnumeratedSets())) self.hw = La Element = CrystalOfGeneralizedYoungWallsElement diff --git a/src/sage/combinat/crystals/kirillov_reshetikhin.py b/src/sage/combinat/crystals/kirillov_reshetikhin.py index 411725aa0ea..103cf4e4701 100644 --- a/src/sage/combinat/crystals/kirillov_reshetikhin.py +++ b/src/sage/combinat/crystals/kirillov_reshetikhin.py @@ -330,7 +330,7 @@ def KirillovReshetikhinCrystal(cartan_type, r, s, model='KN'): return KirillovReshetikhinTableaux(cartan_type, r, s) if model in ['RC', 'RiggedConfigurations']: from sage.combinat.rigged_configurations.rigged_configurations import RiggedConfigurations - return RiggedConfigurations(cartan_type, [[r,s]]) + return RiggedConfigurations(cartan_type, [[r, s]]) if model == 'LSPaths': return KirillovReshetikhinCrystalFromLSPaths(cartan_type, r, s) @@ -378,7 +378,7 @@ def KashiwaraNakashimaTableaux(cartan_type, r, s): elif ct.type() == 'D': if r < ct.rank()-2: return KR_type_vertical(ct, r, s) - elif r in {ct.rank()-2,ct.rank()-1}: + elif r in {ct.rank()-2, ct.rank()-1}: return KR_type_spin(ct, r, s) else: raise ValueError("wrong range of parameters") @@ -396,9 +396,9 @@ def KashiwaraNakashimaTableaux(cartan_type, r, s): return KR_type_Cn(ct, r, s) else: raise ValueError("wrong range of parameters") - elif ct == CartanType(['E',6,1]) and r in [1,6,2]: + elif ct == CartanType(['E', 6, 1]) and r in [1, 6, 2]: return KR_type_E6(ct, r, s) - elif ct == CartanType(['E',7,1]) and r in [7]: + elif ct == CartanType(['E', 7, 1]) and r in [7]: return KR_type_E7(ct, r, s) else: raise NotImplementedError @@ -482,7 +482,7 @@ def _element_constructor_(self, *args, **options): elt = args[0] # Check to make sure it can be converted if elt.cartan_type() != self.cartan_type() \ - or elt.parent().r() != self._r or elt.parent().s() != self._s: + or elt.parent().r() != self._r or elt.parent().s() != self._s: raise ValueError("the Kirillov-Reshetikhin tableau must have the same Cartan type and shape") to_hw = elt.to_classical_highest_weight() @@ -758,9 +758,10 @@ def promotion(self): [[1, 3], [2, 4]] """ T = self.classical_crystal + ct = self._cartan_type[1] return CrystalDiagramAutomorphism(T, - lambda x: T(x.to_tableau().promotion(self._cartan_type[1])), - cache=False) + lambda x: T(x.to_tableau().promotion(ct)), + cache=False) @cached_method def promotion_inverse(self): @@ -782,9 +783,10 @@ def promotion_inverse(self): [[1, 2], [3, 3]] """ T = self.classical_crystal + ct = self._cartan_type[1] return CrystalDiagramAutomorphism(T, - lambda x: T(x.to_tableau().promotion_inverse(self._cartan_type[1])), - cache=False) + lambda x: T(x.to_tableau().promotion_inverse(ct)), + cache=False) def dynkin_diagram_automorphism(self, i): r""" @@ -973,7 +975,7 @@ def from_highest_weight_vector_to_pm_diagram(self, b): True """ n = self.cartan_type().rank() - 1 - inner = Partition([Integer(b.weight()[i]) for i in range(1,n+1)]) + inner = Partition([Integer(b.weight()[i]) for i in range(1, n+1)]) inter = Partition([len([i for i in r if i > 0]) for r in b.to_tableau()]) outer = b.to_tableau().shape() return PMDiagram([self.r(), self.s(), outer, inter, inner], from_shapes=True) @@ -1002,11 +1004,11 @@ def from_pm_diagram_to_highest_weight_vector(self, pm): ulist += list(range(1, h + 1)) for h in pm.heights_of_minus(): if ct_type == 'D': - ulist += list(range(1,rank+1)) + [rank-2-k for k in range(rank-1-h)] + ulist += list(range(1, rank+1)) + [rank-2-k for k in range(rank-1-h)] elif ct_type == 'B': - ulist += list(range(1,rank+1)) + [rank-k for k in range(rank+1-h)] + ulist += list(range(1, rank+1)) + [rank-k for k in range(rank+1-h)] else: - ulist += list(range(1,rank+1)) + [rank-1-k for k in range(rank-h)] + ulist += list(range(1, rank+1)) + [rank-1-k for k in range(rank-h)] for i in reversed(ulist): u = u.f(i) return u @@ -1079,7 +1081,7 @@ def classical_decomposition(self): (Finite dimensional highest weight crystal of type ['E', 6] and highest weight 2*Lambda[1],) """ La = self.cartan_type().classical().root_system().weight_lattice().fundamental_weights() - if self.r() in [1,6]: + if self.r() in [1, 6]: dw = [self.s() * La[self.r()]] elif self.r() == 2: dw = [k*La[2] for k in range(self.s()+1)] @@ -1103,7 +1105,7 @@ def dynkin_diagram_automorphism(self, i): sage: [K.dynkin_diagram_automorphism(i) for i in K.index_set()] [1, 6, 3, 5, 4, 2, 0] """ - aut = [1,6,3,5,4,2,0] + aut = [1, 6, 3, 5, 4, 2, 0] return aut[i] def affine_weight(self, b): @@ -1133,9 +1135,11 @@ def affine_weight(self, b): cl = self.cartan_type().classical() simple_roots = cl.root_system().ambient_space().simple_roots() index_set = cl.index_set() - weight = [Integer(b.weight().scalar( simple_roots[i] )) for i in index_set] + weight = [Integer(b.weight().scalar(simple_roots[i])) + for i in index_set] E6_coeffs = [1, 2, 2, 3, 2, 1] - return tuple([-sum(weight[i] * coeff for i,coeff in enumerate(E6_coeffs))] + weight) + return tuple([-sum(weight[i] * coeff + for i, coeff in enumerate(E6_coeffs))] + weight) @cached_method def hw_auxiliary(self): @@ -1241,11 +1245,11 @@ def promotion_on_highest_weight_vectors(self): dic = self.highest_weight_dict() dic_inv = self.highest_weight_dict_inv() dic_weight = {} - for (weight, i) in dic.values(): + for weight, i in dic.values(): dic_weight[weight] = dic_weight.get(weight, []) + [i] map_index = lambda i_list: max(i_list[1]) + min(i_list[1]) - i_list[0] - map_element = lambda x: ( self.automorphism_on_affine_weight(dic[x][0]), - map_index((dic[x][1], dic_weight[dic[x][0]])) ) + map_element = lambda x: (self.automorphism_on_affine_weight(dic[x][0]), + map_index((dic[x][1], dic_weight[dic[x][0]]))) return {x: dic_inv[map_element(x)] for x in dic} @cached_method @@ -1281,7 +1285,7 @@ def promotion(self): True """ T = self.classical_decomposition() - ind = [1,2,3,4,5] + ind = [1, 2, 3, 4, 5] return CrystalDiagramAutomorphism(T, self.promotion_on_highest_weight_vectors(), ind, automorphism=self.dynkin_diagram_automorphism) @@ -1300,7 +1304,7 @@ def promotion_inverse(self): True """ p = self.promotion() - #return lambda x : p(p(x)) + # return lambda x : p(p(x)) return p * p @@ -1353,7 +1357,7 @@ def ambient_crystal(self): sage: K.ambient_crystal() Kirillov-Reshetikhin crystal of type ['B', 4, 1]^* with (r,s)=(2,3) """ - return KashiwaraNakashimaTableaux(['A',2*self.cartan_type().classical().rank()+1,2], + return KashiwaraNakashimaTableaux(['A', 2*self.cartan_type().classical().rank()+1, 2], self.r(), self.s()) @cached_method @@ -1378,13 +1382,12 @@ def ambient_dict_pm_diagrams(self): [3, 1]: [[0, 0], [1, 1], [1]], [3, 3]: [[0, 0], [0, 0], [3]]} """ - ulist = [] s = self.s() r = self.r() m = s // 2 - for i in range(m+1): - for la in IntegerVectors(m-i, min_length=r, max_length=r): - ulist.append(PMDiagram([[j,j] for j in la]+[[s-2*m+2*i]])) + ulist = (PMDiagram([[j, j] for j in la]+[[s-2*m+2*i]]) + for i in range(m + 1) + for la in IntegerVectors(m-i, min_length=r, max_length=r)) return {x.inner_shape(): x for x in ulist} @cached_method @@ -1618,7 +1621,7 @@ def module_generator(self): s = self.s() weight = s*Lambda[r] - s*Lambda[0] if r == self.cartan_type().rank() - 1: - weight += s*Lambda[r] # Special case for r == n + weight += s*Lambda[r] # Special case for r == n return [b for b in self.module_generators if b.weight() == weight][0] def classical_decomposition(self): @@ -1641,7 +1644,7 @@ def classical_decomposition(self): The crystal of tableaux of type ['B', 2] and shape(s) [[], [2], [2, 2]] """ return CrystalOfTableaux(['B', self.cartan_type().rank()-1], - shapes=horizontal_dominoes_removed(self.r(),self.s())) + shapes=horizontal_dominoes_removed(self.r(), self.s())) def ambient_crystal(self): r""" @@ -1681,13 +1684,12 @@ def ambient_dict_pm_diagrams(self): [2]: [[0, 0], [1, 1], [0]], [2, 2]: [[0, 0], [0, 0], [2]]} """ - ulist = [] s = self.s() r = self.r() m = s // 2 - for i in range(m+1): - for la in IntegerVectors(m-i, min_length=r, max_length=r): - ulist.append(PMDiagram([[j,j] for j in la]+[[s-2*m+2*i]])) + ulist = (PMDiagram([[j, j] for j in la] + [[s-2*m+2*i]]) + for i in range(m + 1) + for la in IntegerVectors(m-i, min_length=r, max_length=r)) return {x.inner_shape(): x for x in ulist} @cached_method @@ -1897,7 +1899,7 @@ def __init__(self, cartan_type, r, s): Kirillov-Reshetikhin crystal of type ['C', 3, 1]^* with (r,s)=(1,1) sage: TestSuite(K).run() """ - KirillovReshetikhinGenericCrystal.__init__(self, cartan_type, r ,s) + KirillovReshetikhinGenericCrystal.__init__(self, cartan_type, r, s) AffineCrystalFromClassical.__init__(self, cartan_type, self.classical_decomposition(), KirillovReshetikhinCrystals()) @@ -1921,7 +1923,7 @@ def classical_decomposition(self): The crystal of tableaux of type ['B', 3] and shape(s) [[], [1], [2], [1, 1], [3], [2, 1], [3, 1], [2, 2], [3, 2], [3, 3]] """ return CrystalOfTableaux(self.cartan_type().classical(), - shapes=partitions_in_box(self.r(),self.s())) + shapes=partitions_in_box(self.r(), self.s())) def ambient_crystal(self): r""" @@ -1938,7 +1940,7 @@ def ambient_crystal(self): """ # calling KR_type_C instead of KirillovReshetikhin(['C',n,1],r,s) has the advantage that # that this also works for r=n for A_{2n}^{(2)}. - return KR_type_C(['C', self.cartan_type().classical().rank(),1], self.r(), 2*self.s()) + return KR_type_C(['C', self.cartan_type().classical().rank(), 1], self.r(), 2*self.s()) @cached_method def highest_weight_dict(self): @@ -2017,10 +2019,10 @@ def to_ambient_crystal(self): ahwd = self.ambient_highest_weight_dict() pdict = {hwd[key]: ahwd[key] for key in hwd} classical = self.cartan_type().classical() - return self.crystal_morphism( pdict, codomain=self.ambient_crystal(), - index_set=classical.index_set(), - scaling_factors=self.similarity_factor(), - cartan_type=classical, check=False ) + return self.crystal_morphism(pdict, codomain=self.ambient_crystal(), + index_set=classical.index_set(), + scaling_factors=self.similarity_factor(), + cartan_type=classical, check=False) @cached_method def from_ambient_crystal(self): @@ -2045,9 +2047,9 @@ def from_ambient_crystal(self): hwd = self.highest_weight_dict() ahwd = self.ambient_highest_weight_dict() pdict_inv = {ahwd[key]: hwd[key] for key in hwd} - return AmbientRetractMap( self, self.ambient_crystal(), pdict_inv, - index_set=self.cartan_type().classical().index_set(), - similarity_factor_domain=self.similarity_factor() ) + return AmbientRetractMap(self, self.ambient_crystal(), pdict_inv, + index_set=self.cartan_type().classical().index_set(), + similarity_factor_domain=self.similarity_factor()) class KR_type_boxElement(KirillovReshetikhinGenericCrystalElement): @@ -2173,7 +2175,7 @@ def _element_constructor_(self, *args, **options): elt = args[0] # Check to make sure it can be converted if elt.cartan_type() != self.cartan_type() \ - or elt.parent().r() != self._r or elt.parent().s() != self._s: + or elt.parent().r() != self._r or elt.parent().s() != self._s: raise ValueError("the Kirillov-Reshetikhin tableau must have the same Cartan type and shape") to_hw = elt.to_classical_highest_weight() @@ -2227,7 +2229,7 @@ def ambient_crystal(self): sage: K.ambient_crystal() Kirillov-Reshetikhin crystal of type ['B', 3, 1]^* with (r,s)=(3,2) """ - return KashiwaraNakashimaTableaux(['A', 2*self.cartan_type().classical().rank()-1,2], + return KashiwaraNakashimaTableaux(['A', 2*self.cartan_type().classical().rank()-1, 2], self.r(), self.s()) @cached_method @@ -2281,7 +2283,7 @@ def similarity_factor(self): {1: 2, 2: 2, 3: 1} """ C = self.cartan_type().classical() - p = {i:2 for i in C.index_set()} + p = {i: 2 for i in C.index_set()} p[C.rank()] = 1 return p @@ -2301,10 +2303,10 @@ def to_ambient_crystal(self): ahwd = self.ambient_highest_weight_dict() pdict = {hwd[key]: ahwd[key] for key in hwd} classical = self.cartan_type().classical() - return self.crystal_morphism( pdict, codomain=self.ambient_crystal(), - index_set=classical.index_set(), - scaling_factors=self.similarity_factor(), - cartan_type=classical, check=False ) + return self.crystal_morphism(pdict, codomain=self.ambient_crystal(), + index_set=classical.index_set(), + scaling_factors=self.similarity_factor(), + cartan_type=classical, check=False) @cached_method def from_ambient_crystal(self): @@ -2327,9 +2329,9 @@ def from_ambient_crystal(self): hwd = self.highest_weight_dict() ahwd = self.ambient_highest_weight_dict() pdict_inv = {ahwd[key]: hwd[key] for key in hwd} - return AmbientRetractMap( self, self.ambient_crystal(), pdict_inv, - index_set=self.cartan_type().classical().index_set(), - similarity_factor_domain=self.similarity_factor() ) + return AmbientRetractMap(self, self.ambient_crystal(), pdict_inv, + index_set=self.cartan_type().classical().index_set(), + similarity_factor_domain=self.similarity_factor()) class KR_type_BnElement(KirillovReshetikhinGenericCrystalElement): @@ -2356,7 +2358,7 @@ def e0(self): sage: b.e(0) # indirect doctest [--+, []] """ - b = self.parent().to_ambient_crystal()(self).e_string([0,0]) + b = self.parent().to_ambient_crystal()(self).e_string([0, 0]) if b is None: return None return self.parent().from_ambient_crystal()(b) @@ -2373,7 +2375,7 @@ def f0(self): sage: b.f(0) # indirect doctest """ - b = self.parent().to_ambient_crystal()(self).f_string([0,0]) + b = self.parent().to_ambient_crystal()(self).f_string([0, 0]) if b is None: return None return self.parent().from_ambient_crystal()(b) @@ -2444,7 +2446,8 @@ def classical_decomposition(self): sage: K.classical_decomposition() The crystal of tableaux of type ['C', 3] and shape(s) [[2, 2, 2]] """ - return CrystalOfTableaux(self.cartan_type().classical(), shape=[self.s()]*self.r() ) + return CrystalOfTableaux(self.cartan_type().classical(), + shape=[self.s()] * self.r()) def from_highest_weight_vector_to_pm_diagram(self, b): r""" @@ -2469,7 +2472,7 @@ def from_highest_weight_vector_to_pm_diagram(self, b): True """ n = self.cartan_type().rank()-1 - inner = Partition([Integer(b.weight()[i]) for i in range(1,n+1)]) + inner = Partition([Integer(b.weight()[i]) for i in range(1, n+1)]) inter = Partition([len([i for i in r if i > 0]) for r in b.to_tableau()]) outer = b.to_tableau().shape() return PMDiagram([self.r(), self.s(), outer, inter, inner], from_shapes=True) @@ -2496,7 +2499,7 @@ def from_pm_diagram_to_highest_weight_vector(self, pm): for h in pm.heights_of_addable_plus(): ulist += list(range(1, h + 1)) for h in pm.heights_of_minus(): - ulist += list(range(1,rank+1))+[rank-1-k for k in range(rank-h)] + ulist += list(range(1, rank+1))+[rank-1-k for k in range(rank-h)] for i in reversed(ulist): u = u.f(i) return u @@ -2535,12 +2538,12 @@ def e0(self): [[3, -3], [-3, -2], [-1, -1]] """ n = self.parent().cartan_type().n - [b,l] = self.lift().to_highest_weight(index_set=list(range(2, n + 1))) + b, l = self.lift().to_highest_weight(index_set=list(range(2, n + 1))) pm = self.parent().from_highest_weight_vector_to_pm_diagram(b) - [l1,l2] = pm.pm_diagram[n-1] + l1, l2 = pm.pm_diagram[n-1] if l1 == 0: return None - pm.pm_diagram[n-1] = [l1-1,l2+1] + pm.pm_diagram[n-1] = [l1-1, l2+1] pm = PMDiagram(pm.pm_diagram) b = self.parent().from_pm_diagram_to_highest_weight_vector(pm) b = b.f_string(reversed(l)) @@ -2560,12 +2563,12 @@ def f0(self): sage: b.f(0) # indirect doctest """ n = self.parent().cartan_type().n - [b,l] = self.lift().to_highest_weight(index_set=list(range(2, n + 1))) + b, l = self.lift().to_highest_weight(index_set=list(range(2, n + 1))) pm = self.parent().from_highest_weight_vector_to_pm_diagram(b) - [l1,l2] = pm.pm_diagram[n-1] + l1, l2 = pm.pm_diagram[n-1] if l2 == 0: return None - pm.pm_diagram[n-1] = [l1+1,l2-1] + pm.pm_diagram[n-1] = [l1+1, l2-1] pm = PMDiagram(pm.pm_diagram) b = self.parent().from_pm_diagram_to_highest_weight_vector(pm) b = b.f_string(reversed(l)) @@ -2577,7 +2580,7 @@ def epsilon0(self): EXAMPLES:: - sage: K=crystals.KirillovReshetikhin(['C',3,1],3,1) + sage: K = crystals.KirillovReshetikhin(['C',3,1],3,1) sage: b = K.module_generators[0] sage: b.epsilon(0) # indirect doctest 1 @@ -2585,7 +2588,7 @@ def epsilon0(self): n = self.parent().cartan_type().n b = self.lift().to_highest_weight(index_set=list(range(2, n + 1)))[0] pm = self.parent().from_highest_weight_vector_to_pm_diagram(b) - [l1,l2] = pm.pm_diagram[n-1] + l1, l2 = pm.pm_diagram[n-1] return l1 def phi0(self): @@ -2602,7 +2605,7 @@ def phi0(self): n = self.parent().cartan_type().n b = self.lift().to_highest_weight(index_set=list(range(2, n + 1)))[0] pm = self.parent().from_highest_weight_vector_to_pm_diagram(b) - [l1,l2] = pm.pm_diagram[n-1] + l1, l2 = pm.pm_diagram[n-1] return l2 @@ -2644,7 +2647,7 @@ def _element_constructor_(self, *args, **options): elt = args[0] # Check to make sure it can be converted if elt.cartan_type() != self.cartan_type() \ - or elt.parent().r() != self._r or elt.parent().s() != self._s: + or elt.parent().r() != self._r or elt.parent().s() != self._s: raise ValueError("the Kirillov-Reshetikhin tableau must have" " the same Cartan type and shape") @@ -2679,7 +2682,8 @@ def classical_decomposition(self): s = s // 2 else: s = s / 2 - return CrystalOfTableaux(self.cartan_type().classical(), shape=[s]*self.r() ) + return CrystalOfTableaux(self.cartan_type().classical(), + shape=[s]*self.r()) def from_highest_weight_vector_to_pm_diagram(self, b): r""" @@ -2741,9 +2745,12 @@ def from_highest_weight_vector_to_pm_diagram(self, b): b = b[1] else: t = b.parent()(rows=[]) - inner = [Integer(2*b.weight()[i]+2*t.weight()[i]) for i in range(1,n+1)] - inter1 = Partition([len([i for i in r if i > 0]) for r in b.to_tableau()]) - inter = Partition([len([i for i in r if i >= 0]) for r in b.to_tableau()]) + inner = [Integer(2*b.weight()[i]+2*t.weight()[i]) + for i in range(1, n+1)] + inter1 = Partition([len([1 for i in r if i > 0]) + for r in b.to_tableau()]) + inter = Partition([len([1 for i in r if i >= 0]) + for r in b.to_tableau()]) if inter != inter1: inner[n-1] += 2 inner = Partition(inner) @@ -2784,7 +2791,7 @@ def from_pm_diagram_to_highest_weight_vector(self, pm): minus = pm.heights_of_minus() l = len([i for i in plus if i == rank-1]) a = (len(plus) + l) // 2 - ulist += sum(([i]*a for i in range(1,rank+1)),[]) + ulist += sum(([i]*a for i in range(1, rank+1)), []) a = (len(minus)-l) // 2 ulist += (list(range(1, rank + 1)) + [rank]) * a for i in reversed(ulist): @@ -2820,9 +2827,9 @@ def e0(self): """ n = self.parent().cartan_type().rank()-1 s = self.parent().s() - [b,l] = self.lift().to_highest_weight(index_set=list(range(2, n + 1))) + b, l = self.lift().to_highest_weight(index_set=list(range(2, n + 1))) pm = self.parent().from_highest_weight_vector_to_pm_diagram(b) - [l1,l2] = pm.pm_diagram[n-1] + l1, l2 = pm.pm_diagram[n-1] l3 = pm.pm_diagram[n-2][0] if l1+l2+l3 == s and l1 == 0: return None @@ -2855,9 +2862,9 @@ def f0(self): """ n = self.parent().cartan_type().rank()-1 s = self.parent().s() - [b,l] = self.lift().to_highest_weight(index_set=list(range(2, n + 1))) + b, l = self.lift().to_highest_weight(index_set=list(range(2, n + 1))) pm = self.parent().from_highest_weight_vector_to_pm_diagram(b) - [l1,l2] = pm.pm_diagram[n-1] + l1, l2 = pm.pm_diagram[n-1] l3 = pm.pm_diagram[n-2][0] if l1+l2+l3 == s and l2 == 0: return None @@ -2902,7 +2909,7 @@ def epsilon0(self): True """ n = self.parent().cartan_type().rank() - 1 - [b,l] = self.lift().to_highest_weight(index_set=list(range(2, n + 1))) + b, l = self.lift().to_highest_weight(index_set=list(range(2, n + 1))) pm = self.parent().from_highest_weight_vector_to_pm_diagram(b) l1 = pm.pm_diagram[n-1][0] l4 = pm.pm_diagram[n][0] @@ -3031,7 +3038,7 @@ def _element_constructor_(self, *args, **options): elt = args[0] # Check to make sure it can be converted if elt.cartan_type() != self.cartan_type() \ - or elt.parent().r() != self._r or elt.parent().s() != self._s: + or elt.parent().r() != self._r or elt.parent().s() != self._s: raise ValueError("the Kirillov-Reshetikhin tableau must have the same Cartan type and shape") to_hw = elt.to_classical_highest_weight() @@ -3269,7 +3276,8 @@ def from_coordinates(self, coords): [[2, 2, 3, 0, -1]] """ C = self.classical_decomposition() - if not sum(coords): # Special empty element (i.e. the unique element of B(0)) + if not sum(coords): + # Special empty element (i.e. the unique element of B(0)) return self.element_class(self, C.module_generators[0]) l = C.letters @@ -3300,7 +3308,7 @@ def _element_constructor_(self, *args, **options): elt = args[0] # Check to make sure it can be converted if elt.cartan_type() != self.cartan_type() \ - or elt.parent().r() != self._r or elt.parent().s() != self._s: + or elt.parent().r() != self._r or elt.parent().s() != self._s: raise ValueError("the Kirillov-Reshetikhin tableau must have the same Cartan type and shape") to_hw = elt.to_classical_highest_weight() @@ -3330,10 +3338,10 @@ def coordinates(self): """ letters = self.parent().classical_decomposition().letters l = list(self.value) - return ( l.count(letters(1)), l.count(letters(2)), - 2*l.count(letters(3)) + l.count(letters(0)), - 2*l.count(letters(-3)) + l.count(letters(0)), - l.count(letters(-2)), l.count(letters(-1)) ) + return (l.count(letters(1)), l.count(letters(2)), + 2*l.count(letters(3)) + l.count(letters(0)), + 2*l.count(letters(-3)) + l.count(letters(0)), + l.count(letters(-2)), l.count(letters(-1))) @lazy_attribute def _A(self): @@ -3550,11 +3558,15 @@ def A7_decomposition(self): """ from sage.geometry.polyhedron.constructor import Polyhedron # variables are m_4, m_5, m_6, m_7 - P = Polyhedron(ieqs=[[0,1,0,0,0],[0,0,1,0,0],[0,0,0,1,0],[0,0,0,0,1],[0,-1,-1,0,1]], - eqns=[[-self._s,1,1,1,1]]) + P = Polyhedron(ieqs=[[0, 1, 0, 0, 0], + [0, 0, 1, 0, 0], + [0, 0, 0, 1, 0], + [0, 0, 0, 0, 1], + [0, -1, -1, 0, 1]], + eqns=[[-self._s, 1, 1, 1, 1]]) shapes = [Partition([6]*(p[3]-p[1]-p[0])+[4]*p[1]+[2]*p[2]).conjugate() for p in P.integral_points()] - return CrystalOfTableaux(['A',7], shapes=shapes) + return CrystalOfTableaux(['A', 7], shapes=shapes) @lazy_attribute def _highest_weight_to_A7_elements(self): @@ -3583,18 +3595,18 @@ def _highest_weight_to_A7_elements(self): d = {} A7 = self.A7_decomposition() for b in self: - if not b.is_highest_weight([1,3,4,5,6,7]): + if not b.is_highest_weight([1, 3, 4, 5, 6, 7]): continue - wt = [b.phi(i) for i in [7,6,5,4,3,1]] + wt = [b.phi(i) for i in [7, 6, 5, 4, 3, 1]] la = Partition([6]*(wt[4]+wt[5])+[4]*(wt[2]+wt[3])+[2]*(wt[0]+wt[1])).conjugate() - #mu = Partition(sum(([6-i]*m for i,m in enumerate(wt)), [])).conjugate() + # mu = Partition(sum(([6-i]*m for i,m in enumerate(wt)), [])).conjugate() x = A7.module_generator(la) for i in range(wt[0]): - x = x.f_string([2,3,4,5,6,7]) + x = x.f_string([2, 3, 4, 5, 6, 7]) for i in range(wt[2]): - x = x.f_string([4,5,6,7]) + x = x.f_string([4, 5, 6, 7]) for i in range(wt[4]): - x = x.f_string([6,7]) + x = x.f_string([6, 7]) d[b] = x return d @@ -3615,8 +3627,10 @@ def to_A7_crystal(self): Defn: ... """ d = self._highest_weight_to_A7_elements - return self.crystal_morphism(d, automorphism={1:6,3:5,4:4,5:3,6:2,7:1}, - index_set=[1,3,4,5,6,7], check=False) + return self.crystal_morphism(d, automorphism={1: 6, 3: 5, 4: 4, + 5: 3, 6: 2, 7: 1}, + index_set=[1, 3, 4, 5, 6, 7], + check=False) @cached_method def from_A7_crystal(self): @@ -3637,8 +3651,10 @@ def from_A7_crystal(self): A7 = self.A7_decomposition() d = self._highest_weight_to_A7_elements d_inv = {d[b]: b for b in d} - return A7.crystal_morphism(d_inv, automorphism={6:1,5:3,4:4,3:5,2:6,1:7}, - index_set=[1,2,3,4,5,6], check=False) + return A7.crystal_morphism(d_inv, automorphism={6: 1, 5: 3, 4: 4, + 3: 5, 2: 6, 1: 7}, + index_set=[1, 2, 3, 4, 5, 6], + check=False) class Element(KirillovReshetikhinGenericCrystalElement): def e0(self): @@ -3793,12 +3809,11 @@ def _repr_diagram(self): sage: pm = PMDiagram([[0,2], [0,0], [0]]) sage: print(pm._repr_diagram()) """ - t = [] ish = self.inner_shape() + [0] * self.n msh = self.intermediate_shape() + [0] * self.n osh = self.outer_shape() + [0] * self.n - for i in range(self.n): - t.append(['.']*ish[i]+['+']*(msh[i]-ish[i])+['-']*(osh[i]-msh[i])) + t = (['.'] * ish[i] + ['+'] * (msh[i]-ish[i]) + ['-'] * (osh[i]-msh[i]) + for i in range(self.n)) t = [i for i in t if i] return Tableau(t)._repr_diagram() if t else '' @@ -3837,10 +3852,8 @@ def inner_shape(self): sage: pm.inner_shape() [10, 7, 5, 3, 1] """ - t = [] ll = self._list - for i in range(self.n): - t.append(sum(ll[0:2*i+1])) + t = [sum(ll[0:2*i+1]) for i in range(self.n)] return Partition(list(reversed(t))) def outer_shape(self): @@ -3893,9 +3906,9 @@ def intermediate_shape(self): [1] """ p = self.inner_shape() - p = p + [0 for i in range(self.n)] + p = p + [0 for _ in range(self.n)] ll = list(reversed(self._list)) - p = [ p[i]+ll[2*i+1] for i in range(self.n) ] + p = [p[i] + ll[2*i+1] for i in range(self.n)] return Partition(p) def heights_of_minus(self): @@ -3933,7 +3946,7 @@ def heights_of_addable_plus(self): [1, 2, 3, 4] """ heights = [] - for i in range(1,self.n+1): + for i in range(1, self.n+1): heights += [i]*self.sigma().pm_diagram[i][0] return heights @@ -3953,11 +3966,11 @@ def sigma(self): return PMDiagram([list(reversed(a)) for a in pm]) -##################################################################################### +####################################################################### def partitions_in_box(r, s): """ - Returns all partitions in a box of width s and height r. + Return all partitions in a box of width s and height r. EXAMPLES:: @@ -3965,12 +3978,13 @@ def partitions_in_box(r, s): [[], [1], [2], [1, 1], [2, 1], [1, 1, 1], [2, 2], [2, 1, 1], [2, 2, 1], [2, 2, 2]] """ - return [x for n in range(r*s+1) for x in Partitions(n,max_part=s,max_length=r)] + return [x for n in range(r*s+1) + for x in Partitions(n, max_part=s, max_length=r)] def vertical_dominoes_removed(r, s): """ - Returns all partitions obtained from a rectangle of width s and height r by removing + Return all partitions obtained from a rectangle of width s and height r by removing vertical dominoes. EXAMPLES:: @@ -3982,12 +3996,12 @@ def vertical_dominoes_removed(r, s): sage: sage.combinat.crystals.kirillov_reshetikhin.vertical_dominoes_removed(4,2) [[], [1, 1], [1, 1, 1, 1], [2, 2], [2, 2, 1, 1], [2, 2, 2, 2]] """ - return [x.conjugate() for x in horizontal_dominoes_removed(s,r)] + return [x.conjugate() for x in horizontal_dominoes_removed(s, r)] def horizontal_dominoes_removed(r, s): """ - Returns all partitions obtained from a rectangle of width s and height r by removing + Return all partitions obtained from a rectangle of width s and height r by removing horizontal dominoes. EXAMPLES:: @@ -3998,11 +4012,11 @@ def horizontal_dominoes_removed(r, s): [[], [2], [2, 2], [2, 2, 2]] """ ulist = [list(x) + [0]*(r-x.length()) for x in partitions_in_box(r, s//2)] - two = lambda x : 2 * (x - s // 2) + s + two = lambda x: 2 * (x - s // 2) + s return [Partition([two(y) for y in x]) for x in ulist] ##################################################################### -## Morphisms +# Morphisms class AmbientRetractMap(Map): @@ -4030,7 +4044,7 @@ def __init__(self, base, ambient, pdict_inv, index_set, Map.__init__(self, Hom(ambient, base, SetsWithPartialMaps())) if similarity_factor_domain is None: - similarity_factor_domain = {i:1 for i in index_set} + similarity_factor_domain = {i: 1 for i in index_set} if automorphism is None: automorphism = lambda i: i @@ -4071,7 +4085,7 @@ def _call_(self, x): if c is not None: d = self(c).f(automorphism(i)) assert d is not None - #now we know that x is hw + # now we know that x is hw return d return self._pdict_inv[x] @@ -4150,7 +4164,7 @@ def _call_(self, x): cur = n break - if n is None: # We're at a I-highest weight element + if n is None: # We're at a I-highest weight element break if cur in self._cache: From 6effe6e04d3ba4aa67afd27622b02f312f511bc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sat, 22 Jun 2024 17:48:23 +0200 Subject: [PATCH 087/231] a few other details, as suggested --- src/sage/combinat/crystals/alcove_path.py | 35 +++++++------ .../crystals/generalized_young_walls.py | 52 +++++++++---------- .../combinat/crystals/kirillov_reshetikhin.py | 29 +++++------ 3 files changed, 57 insertions(+), 59 deletions(-) diff --git a/src/sage/combinat/crystals/alcove_path.py b/src/sage/combinat/crystals/alcove_path.py index 9c5ac8d53f5..0395dfca198 100644 --- a/src/sage/combinat/crystals/alcove_path.py +++ b/src/sage/combinat/crystals/alcove_path.py @@ -394,10 +394,10 @@ def vertices(self): EXAMPLES:: - sage: C = crystals.AlcovePaths(['C',2],[1,0]) + sage: C = crystals.AlcovePaths(['C', 2], [1, 0]) sage: C.vertices() [[], [0], [0, 1], [0, 1, 2]] - sage: C = crystals.AlcovePaths(['C',2,1],[2,1],False) + sage: C = crystals.AlcovePaths(['C', 2, 1], [2, 1], False) sage: len(C.vertices()) 80 @@ -434,13 +434,13 @@ def vertices(self): lst2 = [] for x in lst: suc = getattr(x[0], successors)() - for j in range(x[1][-1]+1, len_lambda_chain): + for j in range(x[1][-1] + 1, len_lambda_chain): temp = x[0] * prod( [s[k] for k in lambda_chain[j].root.associated_reflection()]) if temp in suc: - lst2.append((temp, x[1]+[j])) - l.append((temp, x[1]+[j])) - if lst2 == []: + lst2.append((temp, x[1] + [j])) + l.append((temp, x[1] + [j])) + if not lst2: break else: lst = lst2 @@ -677,7 +677,7 @@ def weight(self): weight = -self.parent().weight for i in self.value[::-1]: root = root_space(i.root) - weight = -i.height*root + weight.reflection(root) + weight = -i.height * root + weight.reflection(root) WLR = self.parent().weight_lattice_realization() if self.cartan_type().is_affine() and self.parent()._highest_weight_crystal: @@ -855,7 +855,7 @@ def _folding_data(self, i): x = R(sign_Beta * Beta, k) if ( - (j < len(J) - 1 and J[j] < x <= J[j+1]) or + (j < len(J) - 1 and J[j] < x <= J[j + 1]) or (j == len(J) - 1 and J[j] < x) ): signs[x] = sign_Beta @@ -902,15 +902,15 @@ def e(self, i): KR_test = finite_cartan_type and i == 0 and m_index < len(gi) - 1 KR_test = KR_test and M >= 1 - ###################################################################### + ################################################################### # NOTE: # In the KR_case we want to insure that positions[m_index] is in J # If m_index > 0 then it's always true # If m_index == 0 then M >=1 guarantees this - ###################################################################### + ################################################################### - if ((not finite_cartan_type or i != 0) and m_index < len(gi) - 1 # alpha_i is a simple root - ) or KR_test: + if ((not finite_cartan_type or i != 0) and m_index < len(gi) - 1) or KR_test: + # first condition above means that alpha_i is a simple root J.remove(positions[m_index]) if m_index + 1 < len(positions): @@ -1040,10 +1040,10 @@ def f(self, i): # # otherwise if m_index - 1 > 0 then (C2) is enough - if ((not finite_cartan_type or i != 0) and M > 0 # alpha_i is a simple root - ) or KR_test: # KR case + if ((not finite_cartan_type or i != 0) and M > 0) or KR_test: + # first condition above means that alpha_i is a simple root - J.append(positions[m_index-1]) + J.append(positions[m_index - 1]) if m_index < len(positions): # if m_index != 'infinity' # thus positions[m_index] makes sense @@ -1658,8 +1658,9 @@ def __init__(self, parent, root, height): if not 0 <= height < max_height: raise ValueError("%d out of allowed range [%d,%d)" % (height, 0, max_height)) - v = [height/max_height] - v.extend(x/max_height for x in root.associated_coroot().to_vector()) + v = [height / max_height] + v.extend(x / max_height + for x in root.associated_coroot().to_vector()) # v.insert(0, height/max_height) # the map from (root, height) --> _cmp_v is injective diff --git a/src/sage/combinat/crystals/generalized_young_walls.py b/src/sage/combinat/crystals/generalized_young_walls.py index 8dc22fbc992..d88a200eaf0 100644 --- a/src/sage/combinat/crystals/generalized_young_walls.py +++ b/src/sage/combinat/crystals/generalized_young_walls.py @@ -390,13 +390,14 @@ def number_of_parts(self): i = 0 while i < len(new): r = new[i] - if r == [] or r in new[i+1:]: + if not r or r in new[i + 1:]: new.pop(i) - elif r[0] == n and len(r) % (n+1) == 0: - for j in range(n+1): - temp = [k % (n+1) for k in range(j+len(r)/(n+1)-1, j-1, -1)] + elif r[0] == n and not len(r) % (n + 1): + for j in range(n + 1): + temp = [k % (n + 1) + for k in range(j + len(r) // (n + 1) - 1, j - 1, -1)] if temp not in new: - new.insert(i+1, temp) + new.insert(i + 1, temp) new.pop(i) else: i += 1 @@ -425,7 +426,7 @@ def sum_of_weighted_row_lengths(self): 15 """ n = self.parent().cartan_type().rank() - 1 - m = lambda i: len([1 for r in self.data if r and r[0] == (i-1) % (n+1)]) + m = lambda i: len([1 for r in self.data if r and r[0] == (i - 1) % (n + 1)]) for r in self.data: if r and r[0] == n: raise ValueError('Statistic only valid for generalized Young walls in Y_0') @@ -510,11 +511,12 @@ def latex_large(self): '\\begin{tikzpicture}[baseline=5,scale=.45] \n \\foreach \\x [count=\\s from 0] in \n{{},{1,0,3,2},{2,1},{3,2,1,0,3,2},{},{},{2}} \n{\\foreach \\y [count=\\t from 0] in \\x { \\node[font=\\scriptsize] at (-\\t,\\s) {$\\y$}; \n \\draw (-\\t+.5,\\s+.5) to (-\\t-.5,\\s+.5); \n \\draw (-\\t+.5,\\s-.5) to (-\\t-.5,\\s-.5); \n \\draw (-\\t-.5,\\s-.5) to (-\\t-.5,\\s+.5); } \n \\draw[-,thick] (.5,\\s+1) to (.5,-.5) to (-\\t-1,-.5); } \n \\end{tikzpicture} \n' """ s = "" - if self.data == []: + if not self.data: s += "\\emptyset" else: s += "\\begin{tikzpicture}[baseline=5,scale=.45] \n \\foreach \\x [count=\\s from 0] in \n" - s += "{" + ','.join("{" + ','.join(str(i) for i in r) + "}" for r in self.data) + "} \n" + s += "{" + ','.join("{" + ','.join(str(i) for i in r) + "}" + for r in self.data) + "} \n" s += "{\\foreach \\y [count=\\t from 0] in \\x { \\node[font=\\scriptsize] at (-\\t,\\s) {$\\y$}; \n \\draw (-\\t+.5,\\s+.5) to (-\\t-.5,\\s+.5); \n \\draw (-\\t+.5,\\s-.5) to (-\\t-.5,\\s-.5); \n \\draw (-\\t-.5,\\s-.5) to (-\\t-.5,\\s+.5); } \n \\draw[-,thick] (.5,\\s+1) to (.5,-.5) to (-\\t-1,-.5); } \n \\end{tikzpicture} \n" return s @@ -529,11 +531,12 @@ def _latex_(self): '\\begin{tikzpicture}[baseline=5,scale=.25] \\foreach \\x [count=\\s from 0] in \n{{},{1,0,3,2},{2,1},{3,2,1,0,3,2},{},{},{2}} \n{\\foreach \\y [count=\\t from 0] in \\x { \\node[font=\\tiny] at (-\\t,\\s) {$\\y$}; \n \\draw (-\\t+.5,\\s+.5) to (-\\t-.5,\\s+.5); \n \\draw (-\\t+.5,\\s-.5) to (-\\t-.5,\\s-.5); \n \\draw (-\\t-.5,\\s-.5) to (-\\t-.5,\\s+.5); } \n \\draw[-] (.5,\\s+1) to (.5,-.5) to (-\\t-1,-.5); } \n \\end{tikzpicture} \n' """ s = "" - if self.data == []: + if not self.data: s += "\\emptyset" else: s += "\\begin{tikzpicture}[baseline=5,scale=.25] \\foreach \\x [count=\\s from 0] in \n" - s += "{" + ','.join("{" + ','.join(str(i) for i in r) + "}" for r in self.data) + "} \n" + s += "{" + ','.join("{" + ','.join(str(i) for i in r) + "}" + for r in self.data) + "} \n" s += "{\\foreach \\y [count=\\t from 0] in \\x { \\node[font=\\tiny] at (-\\t,\\s) {$\\y$}; \n \\draw (-\\t+.5,\\s+.5) to (-\\t-.5,\\s+.5); \n \\draw (-\\t+.5,\\s-.5) to (-\\t-.5,\\s-.5); \n \\draw (-\\t-.5,\\s-.5) to (-\\t-.5,\\s+.5); } \n \\draw[-] (.5,\\s+1) to (.5,-.5) to (-\\t-1,-.5); } \n \\end{tikzpicture} \n" return s @@ -554,13 +557,13 @@ def weight(self, root_lattice=False): sage: x.weight(root_lattice=True) -2*alpha[0] - 3*alpha[1] - 5*alpha[2] - 3*alpha[3] """ - E = self.cartan_type().root_system().weight_lattice(extended=True) L = self.cartan_type().root_system().root_lattice() alpha = L.simple_roots() - W = [-1*alpha[i] for r in self.data for i in r] + W = sum(-1 * alpha[i] for r in self.data for i in r) if not root_lattice: - return E(sum(W)) - return L(sum(W)) + E = self.cartan_type().root_system().weight_lattice(extended=True) + return E(W) + return L(W) def epsilon(self, i): r""" @@ -584,7 +587,7 @@ def epsilon(self, i): self = self.e(i) if self is None: break - eps = eps+1 + eps += 1 return eps def Epsilon(self): @@ -598,7 +601,7 @@ def Epsilon(self): Lambda[0] + 3*Lambda[2] """ La = self.cartan_type().root_system().weight_lattice().fundamental_weights() - return sum(self.epsilon(i)*La[i] for i in self.index_set()) + return sum(self.epsilon(i) * La[i] for i in self.index_set()) def phi(self, i): r""" @@ -632,7 +635,7 @@ def Phi(self): 2*Lambda[0] + Lambda[1] - Lambda[2] + Lambda[3] """ La = self.cartan_type().root_system().weight_lattice(extended=True).fundamental_weights() - return sum(self.phi(i)*La[i] for i in self.index_set()) + return sum(self.phi(i) * La[i] for i in self.index_set()) def column(self, k): r""" @@ -648,13 +651,8 @@ def column(self, k): sage: hw.column(1) [] """ - C = [] - for row in self.data: - if k-1 < len(row): - C.append(row[k-1]) - else: - C.append(None) - return C + return [row[k - 1] if k - 1 < len(row) else None + for row in self.data] def a(self, i, k): r""" @@ -713,14 +711,14 @@ def in_highest_weight_crystal(self, La): ac = self.parent().weight_lattice_realization().simple_coroots() n = self.cartan_type().classical().rank() index_set = self.index_set() - for k in range(1, self.cols+1): + for k in range(1, self.cols + 1): for j in index_set: - if self.a(j, k) - self.a((j-1) % (n+1), k) <= 0: + if self.a(j, k) - self.a((j - 1) % (n + 1), k) <= 0: continue else: p_not_found = True for p in index_set: - if (j+k) % (n+1) == (p+1) % (n+1) and self.a(j, k) - self.a((j-1) % (n+1), k) <= La.scalar(ac[p]): + if (j + k - p - 1) % (n + 1) == 0 and self.a(j, k) - self.a((j - 1) % (n + 1), k) <= La.scalar(ac[p]): p_not_found = False continue else: diff --git a/src/sage/combinat/crystals/kirillov_reshetikhin.py b/src/sage/combinat/crystals/kirillov_reshetikhin.py index 103cf4e4701..3f3a2eaf0a7 100644 --- a/src/sage/combinat/crystals/kirillov_reshetikhin.py +++ b/src/sage/combinat/crystals/kirillov_reshetikhin.py @@ -1481,7 +1481,7 @@ class KR_type_CElement(KirillovReshetikhinGenericCrystalElement): EXAMPLES:: - sage: K=crystals.KirillovReshetikhin(['C',3,1],1,2) + sage: K = crystals.KirillovReshetikhin(['C', 3, 1], 1, 2) sage: type(K.module_generators[0]) """ @@ -1493,7 +1493,7 @@ def e0(self): EXAMPLES:: - sage: K=crystals.KirillovReshetikhin(['C',3,1],1,2) + sage: K = crystals.KirillovReshetikhin(['C', 3, 1], 1, 2) sage: b = K(rows=[]) sage: b.e(0) # indirect doctest [[-1, -1]] @@ -1511,7 +1511,7 @@ def f0(self): EXAMPLES:: - sage: K=crystals.KirillovReshetikhin(['C',3,1],1,2) + sage: K = crystals.KirillovReshetikhin(['C', 3, 1], 1, 2) sage: b = K(rows=[]) sage: b.f(0) # indirect doctest [[1, 1]] @@ -2341,7 +2341,7 @@ class KR_type_BnElement(KirillovReshetikhinGenericCrystalElement): EXAMPLES:: - sage: K=crystals.KirillovReshetikhin(['B',3,1],3,2) + sage: K = crystals.KirillovReshetikhin(['B', 3, 1], 3, 2) sage: type(K.module_generators[0]) """ @@ -2370,10 +2370,9 @@ def f0(self): EXAMPLES:: - sage: K=crystals.KirillovReshetikhin(['B',3,1],3,1) + sage: K = crystals.KirillovReshetikhin(['B', 3, 1], 3, 1) sage: b = K.module_generators[0] sage: b.f(0) # indirect doctest - """ b = self.parent().to_ambient_crystal()(self).f_string([0, 0]) if b is None: @@ -2387,7 +2386,7 @@ def epsilon0(self): EXAMPLES:: - sage: K=crystals.KirillovReshetikhin(['B',3,1],3,1) + sage: K = crystals.KirillovReshetikhin(['B', 3, 1], 3, 1) sage: b = K.module_generators[0] sage: b.epsilon(0) # indirect doctest 1 @@ -2402,7 +2401,7 @@ def phi0(self): EXAMPLES:: - sage: K=crystals.KirillovReshetikhin(['B',3,1],3,1) + sage: K = crystals.KirillovReshetikhin(['B', 3, 1], 3, 1) sage: b = K.module_generators[0] sage: b.phi(0) # indirect doctest 0 @@ -2512,7 +2511,7 @@ class KR_type_CnElement(KirillovReshetikhinGenericCrystalElement): EXAMPLES:: - sage: K=crystals.KirillovReshetikhin(['C',3,1],3,2) + sage: K = crystals.KirillovReshetikhin(['C', 3, 1], 3, 2) sage: type(K.module_generators[0]) """ @@ -2526,7 +2525,7 @@ def e0(self): EXAMPLES:: - sage: K=crystals.KirillovReshetikhin(['C',3,1],3,2) + sage: K = crystals.KirillovReshetikhin(['C', 3, 1], 3, 2) sage: b = K.module_generators[0] sage: b.e(0) # indirect doctest [[1, 2], [2, 3], [3, -1]] @@ -2580,7 +2579,7 @@ def epsilon0(self): EXAMPLES:: - sage: K = crystals.KirillovReshetikhin(['C',3,1],3,1) + sage: K = crystals.KirillovReshetikhin(['C', 3, 1], 3, 1) sage: b = K.module_generators[0] sage: b.epsilon(0) # indirect doctest 1 @@ -2597,7 +2596,7 @@ def phi0(self): EXAMPLES:: - sage: K=crystals.KirillovReshetikhin(['C',3,1],3,1) + sage: K = crystals.KirillovReshetikhin(['C', 3, 1], 3, 1) sage: b = K.module_generators[0] sage: b.phi(0) # indirect doctest 0 @@ -2806,7 +2805,7 @@ class KR_type_Dn_twistedElement(KirillovReshetikhinGenericCrystalElement): EXAMPLES:: - sage: K=crystals.KirillovReshetikhin(['D',4,2],3,2) + sage: K = crystals.KirillovReshetikhin(['D', 4, 2], 3, 2) sage: type(K.module_generators[0]) """ @@ -2820,7 +2819,7 @@ def e0(self): EXAMPLES:: - sage: K=crystals.KirillovReshetikhin(['D',4,2],3,3) + sage: K = crystals.KirillovReshetikhin(['D', 4, 2], 3, 3) sage: b = K.module_generators[0] sage: b.e(0) # indirect doctest [+++, [[2], [3], [0]]] @@ -2888,7 +2887,7 @@ def epsilon0(self): EXAMPLES:: - sage: K=crystals.KirillovReshetikhin(['D',4,2],3,1) + sage: K = crystals.KirillovReshetikhin(['D', 4, 2], 3, 1) sage: b = K.module_generators[0] sage: b.epsilon(0) # indirect doctest 1 From 7548d20aa4cebdf98c0f9feaa66960c3ba8b9caf Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 22 Jun 2024 13:03:34 -0700 Subject: [PATCH 088/231] sage.schemes: Modularization fixes (imports) --- src/sage/schemes/affine/affine_homset.py | 6 ++-- src/sage/schemes/affine/affine_morphism.py | 5 +-- src/sage/schemes/affine/affine_point.py | 2 +- src/sage/schemes/affine/affine_subscheme.py | 7 ++-- .../schemes/berkovich/berkovich_cp_element.py | 18 +++++----- src/sage/schemes/berkovich/berkovich_space.py | 15 ++++++-- src/sage/schemes/curves/affine_curve.py | 21 +++++------ src/sage/schemes/curves/projective_curve.py | 25 ++++++------- src/sage/schemes/curves/zariski_vankampen.py | 7 ++-- .../cyclic_covers/charpoly_frobenius.py | 3 +- .../cyclic_covers/cycliccover_finite_field.py | 21 +++++------ src/sage/schemes/elliptic_curves/BSD.py | 8 +++-- src/sage/schemes/elliptic_curves/cm.py | 3 +- .../elliptic_curves/ell_curve_isogeny.py | 5 ++- .../schemes/elliptic_curves/ell_generic.py | 2 +- src/sage/schemes/elliptic_curves/ell_point.py | 10 +++--- .../elliptic_curves/ell_rational_field.py | 7 ++-- .../schemes/elliptic_curves/ell_tate_curve.py | 17 ++++----- .../elliptic_curves/gal_reps_number_field.py | 4 ++- src/sage/schemes/elliptic_curves/heegner.py | 28 +++++++-------- src/sage/schemes/elliptic_curves/height.py | 9 ++--- .../schemes/elliptic_curves/lseries_ell.py | 5 +-- .../schemes/elliptic_curves/padic_lseries.py | 8 +++-- src/sage/schemes/elliptic_curves/padics.py | 25 ++++++------- .../schemes/elliptic_curves/period_lattice.py | 15 ++++---- src/sage/schemes/elliptic_curves/sha_tate.py | 10 ++++-- src/sage/schemes/generic/algebraic_scheme.py | 17 ++++----- src/sage/schemes/generic/divisor_group.py | 4 ++- src/sage/schemes/generic/morphism.py | 5 ++- src/sage/schemes/generic/scheme.py | 3 ++ .../hyperelliptic_curves/constructor.py | 3 +- .../hyperelliptic_finite_field.py | 6 ++-- .../hyperelliptic_generic.py | 3 +- .../hyperelliptic_padic_field.py | 24 ++++++------- .../hyperelliptic_rational_field.py | 5 +-- .../jacobian_endomorphism_utils.py | 3 +- .../hyperelliptic_curves/monsky_washnitzer.py | 8 +++-- .../plane_conics/con_rational_field.py | 22 ++++++------ .../schemes/projective/proj_bdd_height.py | 21 +++++------ .../schemes/projective/projective_homset.py | 17 ++++----- .../schemes/projective/projective_morphism.py | 27 +++++++------- .../schemes/projective/projective_point.py | 34 +++++++++--------- .../projective/projective_rational_point.py | 12 ++++--- .../schemes/projective/projective_space.py | 35 +++++++++---------- .../projective/projective_subscheme.py | 22 ++++++------ .../riemann_surfaces/riemann_surface.py | 3 +- src/sage/schemes/toric/divisor.py | 4 ++- src/sage/schemes/toric/toric_subscheme.py | 3 +- src/sage/schemes/toric/variety.py | 5 ++- 49 files changed, 314 insertions(+), 258 deletions(-) diff --git a/src/sage/schemes/affine/affine_homset.py b/src/sage/schemes/affine/affine_homset.py index f90bcfffec1..9fcf0543da5 100644 --- a/src/sage/schemes/affine/affine_homset.py +++ b/src/sage/schemes/affine/affine_homset.py @@ -36,8 +36,6 @@ from sage.misc.verbose import verbose from sage.rings.integer_ring import ZZ -from sage.rings.real_mpfr import RR -from sage.rings.cc import CC from sage.rings.rational_field import RationalField from sage.categories.fields import Fields from sage.categories.number_fields import NumberFields @@ -268,6 +266,7 @@ def points(self, **kwds): if hasattr(X.base_ring(), 'precision'): numerical = True verbose("Warning: computations in the numerical fields are inexact;points may be computed partially or incorrectly.", level=0) + from sage.rings.real_mpfr import RR zero_tol = RR(kwds.pop('zero_tolerance', 10**(-10))) if zero_tol <= 0: raise ValueError("tolerance must be positive") @@ -438,7 +437,7 @@ def numerical_points(self, F=None, **kwds): """ from sage.schemes.affine.affine_space import AffineSpace_generic if F is None: - F = CC + from sage.rings.cc import CC as F if F not in Fields() or not hasattr(F, 'precision'): raise TypeError('F must be a numerical field') X = self.codomain() @@ -455,6 +454,7 @@ def numerical_points(self, F=None, **kwds): return [] # if X zero-dimensional + from sage.rings.real_mpfr import RR zero_tol = RR(kwds.pop('zero_tolerance', 10**(-10))) if zero_tol <= 0: raise ValueError("tolerance must be positive") diff --git a/src/sage/schemes/affine/affine_morphism.py b/src/sage/schemes/affine/affine_morphism.py index d99e2843410..4d0aebd69c7 100644 --- a/src/sage/schemes/affine/affine_morphism.py +++ b/src/sage/schemes/affine/affine_morphism.py @@ -49,8 +49,6 @@ import sage.rings.abc -from sage.calculus.functions import jacobian - from sage.categories.homset import Hom, End from sage.categories.fields import Fields @@ -896,6 +894,9 @@ def jacobian(self): return self.__jacobian except AttributeError: pass + + from sage.calculus.functions import jacobian + self.__jacobian = jacobian(list(self), self.domain().ambient_space().gens()) return self.__jacobian diff --git a/src/sage/schemes/affine/affine_point.py b/src/sage/schemes/affine/affine_point.py index bf6dc2258bc..4824c30d7a2 100644 --- a/src/sage/schemes/affine/affine_point.py +++ b/src/sage/schemes/affine/affine_point.py @@ -202,7 +202,7 @@ def global_height(self, prec=None): else: R = RealField(prec) H = max([self[i].abs() for i in range(self.codomain().ambient_space().dimension_relative())]) - return R(max(H,1)).log() + return R(max(H, 1)).log() if self.domain().base_ring() in _NumberFields or isinstance(self.domain().base_ring(), sage.rings.abc.Order): return max([self[i].global_height(prec) for i in range(self.codomain().ambient_space().dimension_relative())]) else: diff --git a/src/sage/schemes/affine/affine_subscheme.py b/src/sage/schemes/affine/affine_subscheme.py index 6ac0e7508d9..b3831e54d79 100644 --- a/src/sage/schemes/affine/affine_subscheme.py +++ b/src/sage/schemes/affine/affine_subscheme.py @@ -20,8 +20,6 @@ # **************************************************************************** from sage.categories.fields import Fields -from sage.interfaces.singular import singular -from sage.modules.free_module_element import vector from sage.schemes.generic.algebraic_scheme import AlgebraicScheme_subscheme from .affine_morphism import SchemeMorphism_polynomial_affine_subscheme_field @@ -418,6 +416,7 @@ def intersection_multiplicity(self, X, P): Iloc = R.ideal([f(chng_coords) for f in I.gens()]) Jloc = R.ideal([f(chng_coords) for f in J.gens()]) # compute the intersection multiplicity with Serre's Tor formula using Singular + from sage.interfaces.singular import singular singular.lib("homolog.lib") i = 0 s = 0 @@ -492,6 +491,8 @@ def multiplicity(self, P): except TypeError: raise TypeError("(=%s) is not a point on (=%s)" % (P, self)) + from sage.interfaces.singular import singular + # Apply a linear change of coordinates to self so that P is sent to the origin # and then compute the multiplicity of the local ring of the translated subscheme # corresponding to the point (0,...,0) @@ -578,6 +579,8 @@ def tangent_space(self, p): sage: _.dimension() 1 """ + from sage.modules.free_module_element import vector + A = self.ambient_space() R = A.coordinate_ring() gens = R.gens() diff --git a/src/sage/schemes/berkovich/berkovich_cp_element.py b/src/sage/schemes/berkovich/berkovich_cp_element.py index a9299e4e732..72111b32ab3 100644 --- a/src/sage/schemes/berkovich/berkovich_cp_element.py +++ b/src/sage/schemes/berkovich/berkovich_cp_element.py @@ -33,17 +33,19 @@ # https://www.gnu.org/licenses/ # ***************************************************************************** -from sage.structure.element import Element -from sage.structure.element import Expression import sage.rings.abc + +from sage.misc.lazy_import import lazy_import +from sage.rings.infinity import Infinity +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ from sage.rings.real_mpfr import RR, RealNumber -from sage.rings.padics.padic_generic_element import pAdicGenericElement -from sage.rings.padics.padic_base_generic import pAdicBaseGeneric -from sage.schemes.projective.projective_space import ProjectiveSpace from sage.schemes.projective.projective_point import SchemeMorphism_point_projective_field -from sage.rings.rational_field import QQ -from sage.rings.integer_ring import ZZ -from sage.rings.infinity import Infinity +from sage.schemes.projective.projective_space import ProjectiveSpace +from sage.structure.element import Element, Expression + +lazy_import('sage.rings.padics.padic_generic_element', 'pAdicGenericElement') +lazy_import('sage.rings.padics.padic_base_generic', 'pAdicBaseGeneric') class Berkovich_Element(Element): diff --git a/src/sage/schemes/berkovich/berkovich_space.py b/src/sage/schemes/berkovich/berkovich_space.py index 0692379530f..d566ccfa0dd 100644 --- a/src/sage/schemes/berkovich/berkovich_space.py +++ b/src/sage/schemes/berkovich/berkovich_space.py @@ -39,10 +39,21 @@ from sage.structure.unique_representation import UniqueRepresentation from sage.categories.number_fields import NumberFields import sage.rings.abc + +from sage.categories.number_fields import NumberFields +from sage.categories.topological_spaces import TopologicalSpaces +from sage.misc.lazy_import import lazy_import from sage.rings.integer_ring import ZZ from sage.rings.rational_field import QQ -from sage.rings.number_field.number_field_ideal import NumberFieldFractionalIdeal -from sage.categories.topological_spaces import TopologicalSpaces +from sage.schemes.affine.affine_space import is_AffineSpace +from sage.schemes.berkovich.berkovich_cp_element import (Berkovich_Element_Cp_Affine, + Berkovich_Element_Cp_Projective) +from sage.schemes.projective.projective_space import is_ProjectiveSpace, ProjectiveSpace +from sage.structure.parent import Parent +from sage.structure.unique_representation import UniqueRepresentation + +lazy_import('sage.rings.number_field.number_field_ideal', 'NumberFieldFractionalIdeal') + def is_Berkovich(space) -> bool: diff --git a/src/sage/schemes/curves/affine_curve.py b/src/sage/schemes/curves/affine_curve.py index dbdb2dfa4cd..c8467094001 100644 --- a/src/sage/schemes/curves/affine_curve.py +++ b/src/sage/schemes/curves/affine_curve.py @@ -124,26 +124,21 @@ # https://www.gnu.org/licenses/ # **************************************************************************** -import sage.rings.abc +from builtins import sum as add -from sage.misc.lazy_attribute import lazy_attribute -from sage.misc.cachefunc import cached_method +import sage.rings.abc from sage.arith.misc import binomial -from sage.interfaces.singular import singular -from builtins import sum as add - from sage.categories.fields import Fields from sage.categories.finite_fields import FiniteFields from sage.categories.homset import Hom, End, hom from sage.categories.number_fields import NumberFields - from sage.matrix.constructor import matrix - +from sage.misc.cachefunc import cached_method +from sage.misc.lazy_attribute import lazy_attribute from sage.misc.lazy_import import lazy_import - +from sage.rings.infinity import infinity from sage.rings.polynomial.multi_polynomial_element import degree_lowest_rational_function -from sage.rings.number_field.number_field import NumberField from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing from sage.rings.rational_field import RationalField from sage.rings.infinity import infinity @@ -152,6 +147,10 @@ from sage.schemes.affine.affine_subscheme import (AlgebraicScheme_subscheme_affine, AlgebraicScheme_subscheme_affine_field) +lazy_import('sage.interfaces.singular', 'singular') +lazy_import('sage.rings.number_field.number_field', 'NumberField') +lazy_import('sage.rings.qqbar', 'number_field_elements_from_algebraics') + from .curve import Curve_generic from .point import (AffineCurvePoint_field, @@ -164,8 +163,6 @@ from .closed_point import IntegralAffineCurveClosedPoint -lazy_import('sage.rings.qqbar', 'number_field_elements_from_algebraics') - class AffineCurve(Curve_generic, AlgebraicScheme_subscheme_affine): """ diff --git a/src/sage/schemes/curves/projective_curve.py b/src/sage/schemes/curves/projective_curve.py index 6045cc3ea70..09a86d2ae20 100644 --- a/src/sage/schemes/curves/projective_curve.py +++ b/src/sage/schemes/curves/projective_curve.py @@ -136,32 +136,30 @@ # https://www.gnu.org/licenses/ # **************************************************************************** -from sage.misc.lazy_attribute import lazy_attribute -from sage.misc.cachefunc import cached_method +from builtins import sum as add from sage.categories.fields import Fields from sage.categories.homset import hom, Hom, End from sage.categories.number_fields import NumberFields - -from sage.interfaces.singular import singular from sage.matrix.constructor import matrix -from builtins import sum as add +from sage.misc.cachefunc import cached_method +from sage.misc.lazy_attribute import lazy_attribute +from sage.misc.lazy_import import lazy_import +from sage.misc.persist import register_unpickle_override from sage.misc.sage_eval import sage_eval - -from sage.rings.polynomial.multi_polynomial_element import degree_lowest_rational_function +from sage.rings.integer import Integer from sage.rings.integer_ring import IntegerRing -from sage.rings.number_field.number_field import NumberField +from sage.rings.polynomial.multi_polynomial_element import degree_lowest_rational_function from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing -from sage.rings.qqbar import (number_field_elements_from_algebraics, - QQbar) from sage.rings.rational_field import RationalField -from sage.rings.integer import Integer - from sage.schemes.projective.projective_space import ProjectiveSpace, ProjectiveSpace_ring - from sage.schemes.projective.projective_subscheme import (AlgebraicScheme_subscheme_projective, AlgebraicScheme_subscheme_projective_field) +lazy_import('sage.interfaces.singular', 'singular') +lazy_import('sage.rings.number_field.number_field', 'NumberField') +lazy_import('sage.rings.qqbar', ['number_field_elements_from_algebraics', 'QQbar']) + from .curve import Curve_generic from .point import (ProjectiveCurvePoint_field, @@ -173,7 +171,6 @@ IntegralProjectivePlaneCurvePoint_finite_field) from .closed_point import IntegralProjectiveCurveClosedPoint -from sage.misc.persist import register_unpickle_override class ProjectiveCurve(Curve_generic, AlgebraicScheme_subscheme_projective): diff --git a/src/sage/schemes/curves/zariski_vankampen.py b/src/sage/schemes/curves/zariski_vankampen.py index 7dec97439db..5e035c3811c 100644 --- a/src/sage/schemes/curves/zariski_vankampen.py +++ b/src/sage/schemes/curves/zariski_vankampen.py @@ -42,6 +42,7 @@ # https://www.gnu.org/licenses/ # **************************************************************************** import itertools + from copy import copy from itertools import combinations @@ -53,10 +54,10 @@ from sage.groups.finitely_presented import wrap_FpGroup from sage.groups.free_group import FreeGroup from sage.groups.perm_gps.permgroup_named import SymmetricGroup -from sage.libs.braiding import leftnormalform, rightnormalform from sage.matrix.constructor import matrix from sage.misc.cachefunc import cached_function from sage.misc.flatten import flatten +from sage.misc.lazy_import import lazy_import from sage.misc.misc_c import prod from sage.parallel.decorate import parallel from sage.rings.complex_interval_field import ComplexIntervalField @@ -67,7 +68,9 @@ from sage.rings.qqbar import QQbar from sage.rings.rational_field import QQ from sage.rings.real_mpfr import RealField -from .constructor import Curve +from sage.schemes.curves.constructor import Curve + +lazy_import('sage.libs.braiding', ['leftnormalform', 'rightnormalform']) roots_interval_cache = {} diff --git a/src/sage/schemes/cyclic_covers/charpoly_frobenius.py b/src/sage/schemes/cyclic_covers/charpoly_frobenius.py index e28289e1d84..b7cf928853c 100644 --- a/src/sage/schemes/cyclic_covers/charpoly_frobenius.py +++ b/src/sage/schemes/cyclic_covers/charpoly_frobenius.py @@ -8,7 +8,8 @@ # https://www.gnu.org/licenses/ # ***************************************************************************** from sage.rings.integer_ring import ZZ -from sage.functions.log import log +from sage.misc.lazy_import import lazy_import +lazy_import("sage.functions.log", "log") def charpoly_frobenius(frob_matrix, charpoly_prec, p, weight, a=1, known_factor=[1]): diff --git a/src/sage/schemes/cyclic_covers/cycliccover_finite_field.py b/src/sage/schemes/cyclic_covers/cycliccover_finite_field.py index 6ad36e761d7..8515d7a849b 100644 --- a/src/sage/schemes/cyclic_covers/cycliccover_finite_field.py +++ b/src/sage/schemes/cyclic_covers/cycliccover_finite_field.py @@ -66,19 +66,20 @@ # https://www.gnu.org/licenses/ # ***************************************************************************** - from sage.arith.misc import euler_phi -from sage.functions.other import ceil, binomial, floor -from sage.functions.log import log -from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing -from sage.rings.power_series_ring import PowerSeriesRing -from sage.rings.padics.factory import Zp, Zq, Qq -from sage.rings.integer_ring import ZZ -from sage.rings.finite_rings.integer_mod_ring import IntegerModRing from sage.matrix.constructor import matrix, zero_matrix -from sage.modules.free_module_element import vector -from sage.schemes.hyperelliptic_curves.hypellfrob import interval_products from sage.misc.cachefunc import cached_method +from sage.misc.lazy_import import lazy_import +from sage.modules.free_module_element import vector +from sage.rings.finite_rings.integer_mod_ring import IntegerModRing +from sage.rings.integer_ring import ZZ +from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing +from sage.rings.power_series_ring import PowerSeriesRing + +lazy_import("sage.functions.log", "log") +lazy_import("sage.functions.other", ["ceil", "binomial", "floor"]) +lazy_import('sage.rings.padics.factory', ['Zp', 'Zq', 'Qq']) +lazy_import('sage.schemes.hyperelliptic_curves.hypellfrob', 'interval_products') from .charpoly_frobenius import charpoly_frobenius from . import cycliccover_generic diff --git a/src/sage/schemes/elliptic_curves/BSD.py b/src/sage/schemes/elliptic_curves/BSD.py index 755f8be2f50..7b808d8d461 100644 --- a/src/sage/schemes/elliptic_curves/BSD.py +++ b/src/sage/schemes/elliptic_curves/BSD.py @@ -1,11 +1,13 @@ "Birch and Swinnerton-Dyer formulas" from sage.arith.misc import prime_divisors +from sage.misc.lazy_import import lazy_import +from sage.rings.infinity import Infinity from sage.rings.integer_ring import ZZ from sage.rings.rational_field import QQ -from sage.rings.infinity import Infinity -from sage.rings.number_field.number_field import QuadraticField -from sage.functions.other import ceil + +lazy_import("sage.functions.other", "ceil") +lazy_import("sage.rings.number_field.number_field", "QuadraticField") class BSD_data: diff --git a/src/sage/schemes/elliptic_curves/cm.py b/src/sage/schemes/elliptic_curves/cm.py index d63589020c4..9580a90038c 100644 --- a/src/sage/schemes/elliptic_curves/cm.py +++ b/src/sage/schemes/elliptic_curves/cm.py @@ -34,12 +34,10 @@ # https://www.gnu.org/licenses/ # **************************************************************************** -from sage.interfaces.magma import magma from sage.rings.integer import Integer from sage.rings.rational_field import QQ from sage.rings.integer_ring import ZZ from sage.rings.integer_ring import IntegerRing -from sage.rings.number_field.number_field import is_fundamental_discriminant from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing from sage.misc.cachefunc import cached_function @@ -121,6 +119,7 @@ def hilbert_class_polynomial(D, algorithm=None): return sage.libs.arb.arith.hilbert_class_polynomial(D) if algorithm == "magma": + from sage.interfaces.magma import magma magma.eval("R := PolynomialRing(IntegerRing())") f = str(magma.eval("HilbertClassPolynomial(%s)" % D)) return IntegerRing()['x'](f) diff --git a/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py b/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py index 496731a6c7d..2d7291aea10 100644 --- a/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py +++ b/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py @@ -192,6 +192,7 @@ def isogeny_codomain_from_kernel(E, kernel): EXAMPLES:: + sage: # needs sage.rings.finite_rings sage: from sage.schemes.elliptic_curves.ell_curve_isogeny import isogeny_codomain_from_kernel sage: E = EllipticCurve(GF(7), [1,0,1,0,1]) sage: R. = GF(7)[] @@ -402,6 +403,7 @@ def compute_codomain_kohel(E, kernel): EXAMPLES:: + sage: # needs sage.rings.finite_rings sage: from sage.schemes.elliptic_curves.ell_curve_isogeny import compute_codomain_kohel sage: E = EllipticCurve(GF(19), [1,2,3,4,5]) sage: phi = EllipticCurveIsogeny(E, [9,1]) @@ -2903,7 +2905,7 @@ def scaling_factor(self): Check for :issue:`36638`:: - sage: phi.scaling_factor().parent() # needs sage.rings.finite_rings + sage: phi.scaling_factor().parent() # needs sage.rings.finite_rings Finite Field in z2 of size 257^2 ALGORITHM: The "inner" isogeny is normalized by construction, @@ -3718,6 +3720,7 @@ def compute_intermediate_curves(E1, E2): EXAMPLES:: + sage: # needs sage.rings.finite_rings sage: from sage.schemes.elliptic_curves.ell_curve_isogeny import compute_intermediate_curves sage: E = EllipticCurve(GF(83), [1,0,1,1,0]) sage: R. = GF(83)[]; f = x + 24 diff --git a/src/sage/schemes/elliptic_curves/ell_generic.py b/src/sage/schemes/elliptic_curves/ell_generic.py index 16347cc6a6f..64db2ddc04c 100644 --- a/src/sage/schemes/elliptic_curves/ell_generic.py +++ b/src/sage/schemes/elliptic_curves/ell_generic.py @@ -272,7 +272,7 @@ def _latex_(self): """ Internal function. Return a latex string for this elliptic curve. - Users will normally use latex() instead. + Users will normally use :func:`latex` instead. EXAMPLES:: diff --git a/src/sage/schemes/elliptic_curves/ell_point.py b/src/sage/schemes/elliptic_curves/ell_point.py index 63d50cc0b0d..2d3037733fc 100644 --- a/src/sage/schemes/elliptic_curves/ell_point.py +++ b/src/sage/schemes/elliptic_curves/ell_point.py @@ -117,20 +117,18 @@ import math -from sage.rings.padics.factory import Qp -from sage.rings.padics.precision_error import PrecisionError - +import sage.groups.generic as generic import sage.rings.abc +from sage.misc.lazy_import import lazy_import from sage.rings.infinity import Infinity as oo from sage.rings.integer import Integer from sage.rings.integer_ring import ZZ +from sage.rings.padics.precision_error import PrecisionError from sage.rings.rational_field import QQ from sage.rings.finite_rings.integer_mod import Mod from sage.rings.real_mpfr import RealField from sage.rings.real_mpfr import RR -import sage.groups.generic as generic - from sage.structure.element import AdditiveGroupElement from sage.structure.sequence import Sequence from sage.structure.richcmp import richcmp @@ -144,6 +142,8 @@ from .constructor import EllipticCurve +lazy_import('sage.rings.padics.factory', 'Qp') + try: from sage.libs.pari.all import pari, PariError from cypari2.pari_instance import prec_words_to_bits diff --git a/src/sage/schemes/elliptic_curves/ell_rational_field.py b/src/sage/schemes/elliptic_curves/ell_rational_field.py index 1dba8a94ba1..96a009b7b2c 100644 --- a/src/sage/schemes/elliptic_curves/ell_rational_field.py +++ b/src/sage/schemes/elliptic_curves/ell_rational_field.py @@ -89,16 +89,16 @@ from sage.structure.element import Element from sage.misc.misc_c import prod as mul from sage.misc.misc_c import prod -from sage.misc.lazy_import import lazy_import from sage.misc.verbose import verbose as verbose_verbose -from sage.functions.log import log +from sage.misc.lazy_import import lazy_import +lazy_import("sage.functions.log", "log") from sage.matrix.matrix_space import MatrixSpace lazy_import('sage.libs.pari.all', 'pari') lazy_import("sage.functions.gamma", "gamma_inc") from math import sqrt -from sage.interfaces.gp import gp +lazy_import('sage.interfaces.gp', 'gp') from sage.misc.cachefunc import cached_method from copy import copy @@ -106,7 +106,6 @@ C = ComplexField() R = RealField() Z = IntegerRing() -IR = RealIntervalField(20) _MAX_HEIGHT = 21 diff --git a/src/sage/schemes/elliptic_curves/ell_tate_curve.py b/src/sage/schemes/elliptic_curves/ell_tate_curve.py index 70697a4b036..4dac4b08aed 100644 --- a/src/sage/schemes/elliptic_curves/ell_tate_curve.py +++ b/src/sage/schemes/elliptic_curves/ell_tate_curve.py @@ -39,17 +39,18 @@ # # https://www.gnu.org/licenses/ ###################################################################### -from sage.rings.integer_ring import ZZ -from sage.rings.padics.factory import Qp -from sage.structure.sage_object import SageObject -from sage.structure.richcmp import richcmp, richcmp_method from sage.arith.functions import lcm as LCM +from sage.matrix.constructor import matrix +from sage.misc.functional import denominator, log +from sage.misc.lazy_import import lazy_import +from sage.misc.misc_c import prod from sage.modular.modform.constructor import EisensteinForms, CuspForms +from sage.rings.integer_ring import ZZ from sage.schemes.elliptic_curves.constructor import EllipticCurve -from sage.functions.log import log -from sage.misc.functional import denominator -from sage.misc.misc_c import prod -from sage.matrix.constructor import matrix +from sage.structure.richcmp import richcmp, richcmp_method +from sage.structure.sage_object import SageObject + +lazy_import('sage.rings.padics.factory', 'Qp') @richcmp_method diff --git a/src/sage/schemes/elliptic_curves/gal_reps_number_field.py b/src/sage/schemes/elliptic_curves/gal_reps_number_field.py index e049b72fa76..50c62f04664 100644 --- a/src/sage/schemes/elliptic_curves/gal_reps_number_field.py +++ b/src/sage/schemes/elliptic_curves/gal_reps_number_field.py @@ -47,16 +47,18 @@ from sage.arith.misc import legendre_symbol, primes from sage.misc.functional import cyclotomic_polynomial +from sage.misc.lazy_import import lazy_import from sage.modules.free_module import VectorSpace from sage.rings.finite_rings.finite_field_constructor import GF from sage.rings.infinity import Infinity from sage.rings.integer import Integer from sage.rings.integer_ring import ZZ -from sage.rings.number_field.number_field import NumberField from sage.rings.rational_field import QQ from sage.sets.set import Set from sage.structure.sage_object import SageObject +lazy_import('sage.rings.number_field.number_field', 'NumberField') + class GaloisRepresentation(SageObject): r""" diff --git a/src/sage/schemes/elliptic_curves/heegner.py b/src/sage/schemes/elliptic_curves/heegner.py index 1c4d0505af0..c5cbceb7f74 100644 --- a/src/sage/schemes/elliptic_curves/heegner.py +++ b/src/sage/schemes/elliptic_curves/heegner.py @@ -98,15 +98,6 @@ from itertools import product import sage.rings.abc -import sage.rings.number_field.number_field_element -import sage.rings.number_field.number_field as number_field -from sage.rings.number_field.number_field import NumberField -from sage.rings.number_field.number_field import QuadraticField -from sage.rings.real_mpfr import RealField -from sage.rings.complex_mpfr import ComplexField -from sage.rings.real_mpfi import RealIntervalField -from sage.rings.infinity import Infinity as infinity -from sage.rings.fast_arith import prime_range from sage.arith.functions import lcm from sage.arith.misc import (binomial, factorial, prime_divisors, @@ -115,21 +106,28 @@ from sage.matrix.matrix_space import MatrixSpace from sage.misc.cachefunc import cached_method from sage.misc.misc_c import prod +from sage.misc.lazy_import import lazy_import from sage.misc.verbose import verbose from sage.modular.modsym.p1list import P1List -from sage.rings.complex_double import CDF +from sage.quadratic_forms.binary_qf import BinaryQF, BinaryQF_reduced_representatives from sage.rings.factorint import factor_trial_division +from sage.rings.fast_arith import prime_range from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF from sage.rings.finite_rings.integer_mod_ring import IntegerModRing as Integers +from sage.rings.infinity import Infinity as infinity from sage.rings.integer_ring import ZZ -from sage.rings.rational_field import QQ -from sage.quadratic_forms.binary_qf import BinaryQF -from sage.quadratic_forms.binary_qf import BinaryQF_reduced_representatives from sage.rings.number_field.number_field_element_base import NumberFieldElement_base +from sage.rings.rational_field import QQ from sage.structure.sage_object import SageObject from sage.structure.richcmp import (richcmp_method, richcmp, richcmp_not_equal, rich_to_bool) +lazy_import('sage.rings.complex_double', 'CDF') +lazy_import('sage.rings.complex_mpfr', 'ComplexField') +lazy_import('sage.rings.number_field.number_field', ['NumberField', 'QuadraticField']) +lazy_import('sage.rings.real_mpfi', 'RealIntervalField') +lazy_import('sage.rings.real_mpfr', 'RealField') + ############################################################################### # # The exported functions, which are in most cases enough to get the @@ -527,7 +525,7 @@ def quadratic_field(self): """ D = self.__D var = 'sqrt_minus_%s' % (-D) - return number_field.QuadraticField(D,var) + return QuadraticField(D,var) @cached_method def galois_group(self, base=QQ): @@ -2232,7 +2230,7 @@ def quadratic_field(self): """ D = self.__D var = 'sqrt_minus_%s' % (-D) - return number_field.QuadraticField(D,var) + return QuadraticField(D,var) def kolyvagin_conductors(self, r=None, n=10, E=None, m=None): r""" diff --git a/src/sage/schemes/elliptic_curves/height.py b/src/sage/schemes/elliptic_curves/height.py index c382ad1eefe..82a213cd9b7 100644 --- a/src/sage/schemes/elliptic_curves/height.py +++ b/src/sage/schemes/elliptic_curves/height.py @@ -34,19 +34,20 @@ from sage.rings.integer_ring import ZZ from sage.rings.rational_field import QQ from sage.rings.infinity import infinity -from sage.rings.cif import CIF from sage.rings.cc import CC from sage.rings.complex_double import CDF from sage.rings.real_double import RDF -from sage.rings.real_mpfi import RIF from sage.rings.real_mpfr import RR from sage.misc.cachefunc import cached_method from sage.arith.functions import lcm from sage.arith.misc import factorial from sage.ext.fast_callable import fast_callable -from sage.functions.log import log, exp -from sage.symbolic.ring import SR +from sage.misc.lazy_import import lazy_import +lazy_import("sage.functions.log", ["log", "exp"]) +lazy_import("sage.rings.cif", "CIF") +lazy_import("sage.rings.real_mpfi", "RIF") +lazy_import("sage.symbolic.ring", "SR") class UnionOfIntervals: diff --git a/src/sage/schemes/elliptic_curves/lseries_ell.py b/src/sage/schemes/elliptic_curves/lseries_ell.py index 73fb8a63659..6a73953ff62 100644 --- a/src/sage/schemes/elliptic_curves/lseries_ell.py +++ b/src/sage/schemes/elliptic_curves/lseries_ell.py @@ -24,7 +24,6 @@ from sage.rings.real_mpfr import RealField from sage.rings.rational_field import RationalField from math import sqrt, log, ceil -import sage.functions.exp_integral as exp_integral from sage.misc.verbose import verbose from sage.misc.cachefunc import cached_method @@ -716,10 +715,12 @@ def deriv_at1(self, k=None, prec=None): # positive, so L'(E,1) = 0. return (R.zero(), Rerror.zero()) + from sage.functions.exp_integral import exponential_integral_1 + an = self.__E.anlist(k) # list of Sage Integers pi = R.pi() sqrtN = R(self.__E.conductor()).sqrt() - v = exp_integral.exponential_integral_1(2*pi/sqrtN, k) + v = exponential_integral_1(2*pi/sqrtN, k) # Compute series sum and accumulate floating point errors L = R.zero() diff --git a/src/sage/schemes/elliptic_curves/padic_lseries.py b/src/sage/schemes/elliptic_curves/padic_lseries.py index 73cfb5aded6..d29be405854 100644 --- a/src/sage/schemes/elliptic_curves/padic_lseries.py +++ b/src/sage/schemes/elliptic_curves/padic_lseries.py @@ -69,10 +69,9 @@ prime_divisors, kronecker as kronecker_symbol, valuation) -from sage.functions.log import log -from sage.functions.other import floor from sage.misc.cachefunc import cached_method from sage.misc.functional import denominator +from sage.misc.lazy_import import lazy_import from sage.misc.verbose import get_verbose, verbose from sage.modules.free_module_element import vector from sage.rings.finite_rings.integer_mod_ring import IntegerModRing as Integers @@ -80,13 +79,16 @@ from sage.rings.integer import Integer from sage.rings.integer_ring import ZZ from sage.rings.laurent_series_ring import LaurentSeriesRing -from sage.rings.padics.factory import Qp from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing from sage.rings.power_series_ring import PowerSeriesRing from sage.rings.rational_field import QQ from sage.structure.richcmp import richcmp_method, richcmp from sage.structure.sage_object import SageObject +lazy_import("sage.functions.log", "log") +lazy_import("sage.functions.other", "floor") +lazy_import('sage.rings.padics.factory', 'Qp') + @richcmp_method class pAdicLseries(SageObject): diff --git a/src/sage/schemes/elliptic_curves/padics.py b/src/sage/schemes/elliptic_curves/padics.py index fe3a2cbe0cb..a5e9a4e4a65 100644 --- a/src/sage/schemes/elliptic_curves/padics.py +++ b/src/sage/schemes/elliptic_curves/padics.py @@ -25,22 +25,23 @@ from sage.arith.functions import lcm as LCM from sage.arith.misc import valuation -from sage.matrix.constructor import matrix -from sage.misc.misc import newton_method_sizes -from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF -from sage.rings.padics.factory import Qp as pAdicField -from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing -import sage.schemes.hyperelliptic_curves.hypellfrob -import sage.schemes.hyperelliptic_curves.monsky_washnitzer - +from sage.matrix.constructor import Matrix as matrix from sage.misc.cachefunc import cached_method +from sage.misc.lazy_import import lazy_import +from sage.misc.misc import newton_method_sizes from sage.rings.big_oh import O +from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF from sage.rings.finite_rings.integer_mod_ring import IntegerModRing as Integers from sage.rings.integer import Integer from sage.rings.laurent_series_ring import LaurentSeriesRing -from sage.rings.padics.factory import Qp, Zp +from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing from sage.rings.power_series_ring import PowerSeriesRing from sage.rings.rational_field import RationalField +import sage.schemes.hyperelliptic_curves.hypellfrob +import sage.schemes.hyperelliptic_curves.monsky_washnitzer + +lazy_import('sage.rings.padics.factory', ['Qp', 'Zp']) + from . import padic_lseries as plseries @@ -1188,7 +1189,7 @@ def padic_sigma(self, p, N=20, E2=None, check=False, check_hypotheses=True): # [Note: there are actually more digits available, but it's a bit # tricky to figure out exactly how many, and we only need p^(N-k+1) # for p-adic height purposes anyway] - K = pAdicField(p, N + 1) + K = Qp(p, N + 1) sigma = sigma.padded_list(N+1) @@ -1372,7 +1373,7 @@ def padic_sigma_truncated(self, p, N=20, lamb=0, E2=None, check_hypotheses=True) # Convert the answer to power series over p-adics; drop the precision # of the t^j coefficient to p^{N - 2 + (3 - j)(lamb + 1)}). - K = pAdicField(p, N - 2 + 3*(lamb+1)) + K = Qp(p, N - 2 + 3*(lamb+1)) sigma = sigma.padded_list(trunc+1) @@ -1555,7 +1556,7 @@ def padic_E2(self, p, prec=20, check=False, check_hypotheses=True, algorithm="au frob_p_n = frob_p**prec # todo: think about the sign of this. Is it correct? - output_ring = pAdicField(p, prec) + output_ring = Qp(p, prec) E2_of_X = output_ring( (-12 * frob_p_n[0,1] / frob_p_n[1,1]).lift() ) \ + O(p**prec) diff --git a/src/sage/schemes/elliptic_curves/period_lattice.py b/src/sage/schemes/elliptic_curves/period_lattice.py index aa4662a85ac..ae0b456890d 100644 --- a/src/sage/schemes/elliptic_curves/period_lattice.py +++ b/src/sage/schemes/elliptic_curves/period_lattice.py @@ -108,21 +108,20 @@ import sage.rings.abc -from sage.libs.pari.all import pari from sage.misc.cachefunc import cached_method +from sage.misc.lazy_import import lazy_import from sage.modules.free_module import FreeModule_generic_pid -from sage.rings.complex_mpfr import ComplexField -from sage.rings.complex_mpfr import ComplexNumber +from sage.rings.complex_mpfr import ComplexField, ComplexNumber from sage.rings.infinity import Infinity from sage.rings.integer_ring import ZZ -from sage.rings.number_field.number_field import refine_embedding -from sage.rings.qqbar import AA, QQbar from sage.rings.rational_field import QQ -from sage.rings.real_mpfr import RealField -from sage.rings.real_mpfr import RealNumber as RealNumber +from sage.rings.real_mpfr import RealField, RealNumber from sage.schemes.elliptic_curves.constructor import EllipticCurve from sage.structure.richcmp import richcmp_method, richcmp, richcmp_not_equal +lazy_import('sage.libs.pari.all', 'pari') +lazy_import('sage.rings.number_field.number_field', 'refine_embedding') + class PeriodLattice(FreeModule_generic_pid): """ @@ -215,6 +214,8 @@ def __init__(self, E, embedding=None): sage: L == loads(dumps(L)) True """ + from sage.rings.qqbar import AA, QQbar + # First we cache the elliptic curve with this period lattice: self.E = E diff --git a/src/sage/schemes/elliptic_curves/sha_tate.py b/src/sage/schemes/elliptic_curves/sha_tate.py index 6c8cf3c986f..90003faf1c7 100644 --- a/src/sage/schemes/elliptic_curves/sha_tate.py +++ b/src/sage/schemes/elliptic_curves/sha_tate.py @@ -77,19 +77,23 @@ # the License, or (at your option) any later version. # https://www.gnu.org/licenses/ # **************************************************************************** + from math import sqrt -from sage.functions.log import log +import sage.arith.all as arith + +from sage.misc.lazy_import import lazy_import from sage.misc.verbose import verbose from sage.modules.free_module_element import vector from sage.rings.integer import Integer from sage.rings.integer_ring import ZZ -from sage.rings.padics.factory import Qp from sage.rings.rational_field import Q from sage.rings.real_mpfi import RIF from sage.rings.real_mpfr import RealField from sage.structure.sage_object import SageObject -import sage.arith.all as arith + +lazy_import("sage.functions.log", "log") +lazy_import("sage.rings.padics.factory", "Qp") factor = arith.factor valuation = arith.valuation diff --git a/src/sage/schemes/generic/algebraic_scheme.py b/src/sage/schemes/generic/algebraic_scheme.py index 8cc0e544917..9d4fbbb2c28 100644 --- a/src/sage/schemes/generic/algebraic_scheme.py +++ b/src/sage/schemes/generic/algebraic_scheme.py @@ -1787,7 +1787,7 @@ def rational_points(self, **kwds): over the rationals:: sage: E = EllipticCurve('37a') # needs sage.schemes - sage: E.rational_points(bound=8) # needs sage.schemes + sage: E.rational_points(bound=8) # needs sage.libs.singular sage.schemes [(-1 : -1 : 1), (-1 : 0 : 1), (0 : -1 : 1), (0 : 0 : 1), (0 : 1 : 0), (1/4 : -5/8 : 1), (1/4 : -3/8 : 1), (1 : -1 : 1), (1 : 0 : 1), (2 : -3 : 1), (2 : 2 : 1)] @@ -1796,8 +1796,9 @@ def rational_points(self, **kwds): enumerated. :: sage: Etilde = E.base_extend(GF(3)) # needs sage.schemes - sage: Etilde.rational_points() # needs sage.schemes - [(0 : 1 : 0), (0 : 0 : 1), (0 : 2 : 1), (1 : 0 : 1), (1 : 2 : 1), (2 : 0 : 1), (2 : 2 : 1)] + sage: Etilde.rational_points() # needs sage.libs.singular sage.schemes + [(0 : 1 : 0), (0 : 0 : 1), (0 : 2 : 1), (1 : 0 : 1), + (1 : 2 : 1), (2 : 0 : 1), (2 : 2 : 1)] The class of hyperelliptic curves does not (yet) support desingularization of the places at infinity into two points:: @@ -1805,27 +1806,27 @@ def rational_points(self, **kwds): sage: FF = FiniteField(7) sage: P. = PolynomialRing(FiniteField(7)) sage: C = HyperellipticCurve(x^8 + x + 1) # needs sage.schemes - sage: C.rational_points() # needs sage.schemes + sage: C.rational_points() # needs sage.libs.singular sage.schemes [(0 : 1 : 0), (0 : 1 : 1), (0 : 6 : 1), (2 : 0 : 1), (4 : 0 : 1), (6 : 1 : 1), (6 : 6 : 1)] :: - sage: # needs sage.rings.number_field + sage: # needs sage.rings.number_field sage.rings.real_mpfr sage: K. = QuadraticField(-3) sage: P. = ProjectiveSpace(K, 2) sage: X = P.subscheme([x^2 - v^2*x*z, y*x - v*z^2]) - sage: X.rational_points(F=CC) + sage: X.rational_points(F=CC) # needs sage.libs.singular [(-3.00000000000000 : -0.577350269189626*I : 1.00000000000000), (0.000000000000000 : 1.00000000000000 : 0.000000000000000)] :: - sage: # needs sage.rings.number_field + sage: # needs sage.rings.number_field sage.rings.real_mpfr sage: K. = QuadraticField(3) sage: A. = AffineSpace(K, 2) sage: X = A.subscheme([x^2 - v^2*y, y*x - v]) - sage: X.rational_points(F=RR) + sage: X.rational_points(F=RR) # needs sage.libs.singular [(1.73205080756888, 1.00000000000000)] .. TODO:: diff --git a/src/sage/schemes/generic/divisor_group.py b/src/sage/schemes/generic/divisor_group.py index d6a19f49d60..05c0f06f7d9 100644 --- a/src/sage/schemes/generic/divisor_group.py +++ b/src/sage/schemes/generic/divisor_group.py @@ -15,12 +15,15 @@ # http://www.gnu.org/licenses/ #******************************************************************************* +from sage.misc.lazy_import import lazy_import from sage.schemes.generic.divisor import Divisor_generic, Divisor_curve from sage.structure.formal_sum import FormalSums from sage.structure.unique_representation import UniqueRepresentation from sage.rings.integer_ring import ZZ from sage.rings.rational_field import QQ +lazy_import('sage.schemes.curves.curve', 'Curve_generic') + def DivisorGroup(scheme, base_ring=None): r""" @@ -49,7 +52,6 @@ def DivisorGroup(scheme, base_ring=None): if base_ring is None: base_ring = ZZ - from sage.schemes.curves.curve import Curve_generic if isinstance(scheme, Curve_generic): DG = DivisorGroup_curve(scheme, base_ring) else: diff --git a/src/sage/schemes/generic/morphism.py b/src/sage/schemes/generic/morphism.py index 8034d0b9b5a..6e491c50c9e 100644 --- a/src/sage/schemes/generic/morphism.py +++ b/src/sage/schemes/generic/morphism.py @@ -113,7 +113,10 @@ def is_SchemeMorphism(f): sage: is_SchemeMorphism(f) True """ - from sage.schemes.elliptic_curves.ell_point import EllipticCurvePoint_field + try: + from sage.schemes.elliptic_curves.ell_point import EllipticCurvePoint_field + except ImportError: + EllipticCurvePoint_field = () return isinstance(f, (SchemeMorphism, EllipticCurvePoint_field)) diff --git a/src/sage/schemes/generic/scheme.py b/src/sage/schemes/generic/scheme.py index 715c9d2a687..c697a305f26 100644 --- a/src/sage/schemes/generic/scheme.py +++ b/src/sage/schemes/generic/scheme.py @@ -21,12 +21,15 @@ from sage.structure.parent import Parent from sage.misc.cachefunc import cached_method +from sage.misc.lazy_import import lazy_import from sage.rings.integer_ring import ZZ from sage.categories.commutative_rings import CommutativeRings from sage.rings.ideal import is_Ideal from sage.structure.unique_representation import UniqueRepresentation from sage.schemes.generic.point import SchemeTopologicalPoint_prime_ideal +lazy_import('sage.schemes.elliptic_curves.ell_generic', 'EllipticCurve_generic', as_='EllipticCurve') + def is_Scheme(x): """ diff --git a/src/sage/schemes/hyperelliptic_curves/constructor.py b/src/sage/schemes/hyperelliptic_curves/constructor.py index 46d01cfd2cb..adb7d7cb6f5 100644 --- a/src/sage/schemes/hyperelliptic_curves/constructor.py +++ b/src/sage/schemes/hyperelliptic_curves/constructor.py @@ -14,8 +14,6 @@ # https://www.gnu.org/licenses/ # **************************************************************************** -from sage.schemes.projective.projective_space import ProjectiveSpace - from .hyperelliptic_generic import HyperellipticCurve_generic from .hyperelliptic_finite_field import HyperellipticCurve_finite_field from .hyperelliptic_rational_field import HyperellipticCurve_rational_field @@ -27,6 +25,7 @@ from sage.rings.finite_rings.finite_field_base import FiniteField from sage.rings.polynomial.polynomial_element import Polynomial from sage.rings.rational_field import RationalField +from sage.schemes.projective.projective_space import ProjectiveSpace from sage.structure.dynamic_class import dynamic_class diff --git a/src/sage/schemes/hyperelliptic_curves/hyperelliptic_finite_field.py b/src/sage/schemes/hyperelliptic_curves/hyperelliptic_finite_field.py index db37ec0c6d2..b9106a7082e 100644 --- a/src/sage/schemes/hyperelliptic_curves/hyperelliptic_finite_field.py +++ b/src/sage/schemes/hyperelliptic_curves/hyperelliptic_finite_field.py @@ -56,11 +56,13 @@ from sage.arith.misc import binomial from sage.rings.power_series_ring import PowerSeriesRing from . import hyperelliptic_generic -from sage.schemes.hyperelliptic_curves.hypellfrob import hypellfrob from sage.misc.cachefunc import cached_method from sage.matrix.constructor import identity_matrix, matrix from sage.misc.functional import rank -from sage.libs.pari.all import pari +from sage.misc.lazy_import import lazy_import + +lazy_import('sage.libs.pari.all', 'pari') +lazy_import('sage.schemes.hyperelliptic_curves.hypellfrob', 'hypellfrob') from sage.schemes.curves.projective_curve import ProjectivePlaneCurve_finite_field diff --git a/src/sage/schemes/hyperelliptic_curves/hyperelliptic_generic.py b/src/sage/schemes/hyperelliptic_curves/hyperelliptic_generic.py index 4834152b606..42709c1a033 100644 --- a/src/sage/schemes/hyperelliptic_curves/hyperelliptic_generic.py +++ b/src/sage/schemes/hyperelliptic_curves/hyperelliptic_generic.py @@ -38,7 +38,8 @@ from sage.rings.power_series_ring import PowerSeriesRing from sage.rings.laurent_series_ring import LaurentSeriesRing from sage.rings.real_mpfr import RR -from sage.functions.all import log +from sage.misc.lazy_import import lazy_import +lazy_import("sage.functions.all", "log") from sage.structure.category_object import normalize_names import sage.schemes.curves.projective_curve as plane_curve diff --git a/src/sage/schemes/hyperelliptic_curves/hyperelliptic_padic_field.py b/src/sage/schemes/hyperelliptic_curves/hyperelliptic_padic_field.py index 018d60c22f8..10c471035a7 100644 --- a/src/sage/schemes/hyperelliptic_curves/hyperelliptic_padic_field.py +++ b/src/sage/schemes/hyperelliptic_curves/hyperelliptic_padic_field.py @@ -12,23 +12,23 @@ # https://www.gnu.org/licenses/ # **************************************************************************** - -from sage.rings.power_series_ring import PowerSeriesRing -from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing +from sage.matrix.constructor import matrix +from sage.misc.lazy_import import lazy_import +from sage.modules.free_module import VectorSpace +from sage.modules.free_module_element import vector +from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF +from sage.rings.infinity import Infinity from sage.rings.integer_ring import ZZ +from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing +from sage.rings.power_series_ring import PowerSeriesRing from sage.rings.rational_field import QQ -from sage.rings.padics.factory import Qp as pAdicField -from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF -from sage.rings.real_mpfr import RR from sage.rings.rational_field import RationalField -from sage.rings.infinity import Infinity -from sage.functions.log import log -from sage.modules.free_module import VectorSpace -from sage.matrix.constructor import matrix -from sage.modules.free_module_element import vector - +from sage.rings.real_mpfr import RR from sage.schemes.curves.projective_curve import ProjectivePlaneCurve_field +lazy_import("sage.functions.log", "log") +lazy_import("sage.rings.padics.factory", "Qp", as_="pAdicField") + from . import hyperelliptic_generic diff --git a/src/sage/schemes/hyperelliptic_curves/hyperelliptic_rational_field.py b/src/sage/schemes/hyperelliptic_curves/hyperelliptic_rational_field.py index 1e33f9b67fd..70cd588047f 100644 --- a/src/sage/schemes/hyperelliptic_curves/hyperelliptic_rational_field.py +++ b/src/sage/schemes/hyperelliptic_curves/hyperelliptic_rational_field.py @@ -9,10 +9,11 @@ import sage.rings.abc -from sage.rings.padics.factory import Qp as pAdicField - +from sage.misc.lazy_import import lazy_import from sage.schemes.curves.projective_curve import ProjectivePlaneCurve_field +lazy_import('sage.rings.padics.factory', 'Qp', as_='pAdicField') + from . import hyperelliptic_generic diff --git a/src/sage/schemes/hyperelliptic_curves/jacobian_endomorphism_utils.py b/src/sage/schemes/hyperelliptic_curves/jacobian_endomorphism_utils.py index f72f7bab6e7..339964d7d08 100644 --- a/src/sage/schemes/hyperelliptic_curves/jacobian_endomorphism_utils.py +++ b/src/sage/schemes/hyperelliptic_curves/jacobian_endomorphism_utils.py @@ -92,11 +92,12 @@ from sage.rings.integer_ring import ZZ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing from sage.rings.finite_rings.finite_field_constructor import FiniteField -from sage.rings.number_field.number_field import NumberField from sage.misc.lazy_import import lazy_import from sage.rings.fast_arith import prime_range from sage.arith.misc import GCD as gcd + lazy_import('sage.interfaces.genus2reduction', ['genus2reduction', 'Genus2reduction']) +lazy_import('sage.rings.number_field.number_field', 'NumberField') def satisfies_coefficient_condition(g, p): diff --git a/src/sage/schemes/hyperelliptic_curves/monsky_washnitzer.py b/src/sage/schemes/hyperelliptic_curves/monsky_washnitzer.py index d9a9996d44e..0876bbcb740 100644 --- a/src/sage/schemes/hyperelliptic_curves/monsky_washnitzer.py +++ b/src/sage/schemes/hyperelliptic_curves/monsky_washnitzer.py @@ -48,9 +48,9 @@ from sage.arith.misc import integer_ceil as ceil from sage.arith.misc import binomial from sage.categories.algebras import Algebras -from sage.functions.log import log from sage.matrix.constructor import matrix from sage.misc.cachefunc import cached_method +from sage.misc.lazy_import import lazy_import from sage.misc.misc import newton_method_sizes from sage.misc.profiler import Profiler from sage.misc.repr import repr_lincomb @@ -70,7 +70,6 @@ from sage.categories.integral_domains import IntegralDomains from sage.rings.infinity import Infinity from sage.rings.laurent_series_ring import is_LaurentSeriesRing -from sage.rings.padics.factory import Qp as pAdicField from sage.rings.polynomial.polynomial_element import Polynomial from sage.schemes.elliptic_curves.constructor import EllipticCurve from sage.schemes.elliptic_curves.ell_generic import EllipticCurve_generic @@ -81,6 +80,9 @@ from sage.structure.richcmp import richcmp from sage.structure.unique_representation import UniqueRepresentation +lazy_import('sage.functions.log', 'log') +lazy_import('sage.rings.padics.factory', 'Qp', as_='pAdicField') + class SpecialCubicQuotientRingElement(ModuleElement): """ @@ -3487,7 +3489,7 @@ def coleman_integral(self, P, Q): sage: E = EllipticCurve(K,[-31/3,-2501/108]) #11a sage: P = E(K(14/3), K(11/2)) sage: w = E.invariant_differential() - sage: w.coleman_integral(P,2*P) + sage: w.coleman_integral(P, 2*P) O(5^6) sage: Q = E([3,58332]) diff --git a/src/sage/schemes/plane_conics/con_rational_field.py b/src/sage/schemes/plane_conics/con_rational_field.py index 7be5d2ad242..f357a71edb6 100644 --- a/src/sage/schemes/plane_conics/con_rational_field.py +++ b/src/sage/schemes/plane_conics/con_rational_field.py @@ -23,25 +23,23 @@ # https://www.gnu.org/licenses/ # **************************************************************************** -from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing -from sage.rings.integer_ring import ZZ -from sage.rings.rational_field import QQ - import sage.rings.abc -from sage.structure.sequence import Sequence -from sage.schemes.projective.projective_space import ProjectiveSpace +from sage.arith.functions import lcm +from sage.arith.misc import hilbert_symbol from sage.matrix.constructor import Matrix +from sage.misc.lazy_import import lazy_import +from sage.rings.integer_ring import ZZ +from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing +from sage.rings.rational_field import QQ +from sage.schemes.projective.projective_space import ProjectiveSpace +from sage.structure.element import InfinityElement +from sage.structure.sequence import Sequence -from sage.quadratic_forms.qfsolve import qfsolve, qfparam +lazy_import('sage.quadratic_forms.qfsolve', ['qfsolve', 'qfparam']) from .con_number_field import ProjectiveConic_number_field -from sage.structure.element import InfinityElement - -from sage.arith.functions import lcm -from sage.arith.misc import hilbert_symbol - class ProjectiveConic_rational_field(ProjectiveConic_number_field): r""" diff --git a/src/sage/schemes/projective/proj_bdd_height.py b/src/sage/schemes/projective/proj_bdd_height.py index df3db88cda7..f1191fe78a0 100644 --- a/src/sage/schemes/projective/proj_bdd_height.py +++ b/src/sage/schemes/projective/proj_bdd_height.py @@ -20,18 +20,19 @@ from math import floor -from sage.schemes.projective.projective_space import ProjectiveSpace -from sage.rings.integer_ring import ZZ -from sage.rings.rational_field import QQ -from sage.rings.real_mpfr import RealField -from sage.rings.number_field.unit_group import UnitGroup -from sage.arith.misc import gcd from sage.arith.functions import lcm -from sage.matrix.constructor import matrix, column_matrix -from sage.libs.pari.all import pari -from sage.modules.free_module_element import vector +from sage.arith.misc import gcd +from sage.misc.lazy_import import lazy_import from sage.rings.integer import Integer -from sage.geometry.polyhedron.constructor import Polyhedron +from sage.rings.rational_field import QQ +from sage.schemes.projective.projective_space import ProjectiveSpace + +lazy_import('sage.geometry.polyhedron.constructor', 'Polyhedron') +lazy_import('sage.libs.pari.all', 'pari') +lazy_import('sage.matrix.constructor', ['matrix', 'column_matrix']) +lazy_import('sage.modules.free_module_element', 'vector') +lazy_import('sage.rings.number_field.unit_group', 'UnitGroup') +lazy_import('sage.rings.real_mpfr', 'RealField') def ZZ_points_of_bounded_height(PS, dim, bound): diff --git a/src/sage/schemes/projective/projective_homset.py b/src/sage/schemes/projective/projective_homset.py index bc1a781c00b..b1dca24495f 100644 --- a/src/sage/schemes/projective/projective_homset.py +++ b/src/sage/schemes/projective/projective_homset.py @@ -37,20 +37,21 @@ # http://www.gnu.org/licenses/ # ***************************************************************************** -from sage.rings.integer_ring import ZZ -from sage.rings.real_mpfr import RR -from sage.rings.cc import CC -from sage.schemes.generic.homset import SchemeHomset_points, SchemeHomset_generic - -from sage.misc.verbose import verbose +from copy import copy -from sage.rings.rational_field import RationalField from sage.categories.fields import Fields from sage.categories.number_fields import NumberFields +from sage.misc.lazy_import import lazy_import +from sage.misc.verbose import verbose from sage.rings.finite_rings.finite_field_base import FiniteField +from sage.rings.integer_ring import ZZ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing +from sage.rings.rational_field import RationalField from sage.schemes.generic.algebraic_scheme import AlgebraicScheme_subscheme -from copy import copy +from sage.schemes.generic.homset import SchemeHomset_points, SchemeHomset_generic + +lazy_import('sage.rings.cc', 'CC') +lazy_import('sage.rings.real_mpfr', 'RR') # ******************************************************************* diff --git a/src/sage/schemes/projective/projective_morphism.py b/src/sage/schemes/projective/projective_morphism.py index 339406cd9d6..b6c93310550 100644 --- a/src/sage/schemes/projective/projective_morphism.py +++ b/src/sage/schemes/projective/projective_morphism.py @@ -58,16 +58,16 @@ # **************************************************************************** import sys -from sage.arith.misc import GCD as gcd from sage.arith.functions import lcm -from sage.misc.misc_c import prod +from sage.arith.misc import GCD as gcd from sage.misc.cachefunc import cached_method +from sage.misc.misc_c import prod from sage.misc.lazy_attribute import lazy_attribute +from sage.misc.lazy_import import lazy_import import sage.rings.abc -from sage.rings.integer import Integer -from sage.rings.algebraic_closure_finite_field import AlgebraicClosureFiniteField_generic from sage.rings.finite_rings.finite_field_base import FiniteField from sage.rings.fraction_field import FractionField +from sage.rings.integer import Integer from sage.rings.integer_ring import ZZ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing from sage.rings.quotient_ring import QuotientRing_generic @@ -78,6 +78,16 @@ from sage.categories.homset import Hom, End from sage.categories.fields import Fields +lazy_import('sage.dynamics.arithmetic_dynamics.generic_ds', 'DynamicalSystem') +lazy_import('sage.dynamics.arithmetic_dynamics.projective_ds', + ['DynamicalSystem_projective', 'DynamicalSystem_projective_field', + 'DynamicalSystem_projective_finite_field']) +lazy_import('sage.rings.algebraic_closure_finite_field', 'AlgebraicClosureFiniteField_generic') +lazy_import('sage.rings.number_field.number_field_ideal', 'NumberFieldFractionalIdeal') +lazy_import('sage.rings.padics.padic_base_generic', 'pAdicGeneric') +lazy_import('sage.rings.padics.padic_valuation', 'pAdicValuation_base') + + _NumberFields = NumberFields() _FiniteFields = FiniteFields() _Fields = Fields() @@ -618,7 +628,6 @@ def _matrix_times_polymap_(self, mat, h): ((1/3*i)*x^2 + (1/2*i)*y^2 : i*y^2) """ from sage.modules.free_module_element import vector - from sage.dynamics.arithmetic_dynamics.generic_ds import DynamicalSystem if not mat.is_square(): raise ValueError("matrix must be square") @@ -664,7 +673,6 @@ def _polymap_times_matrix_(self, mat, h): (-1/3*x^2 - 1/2*y^2 : -y^2) """ from sage.modules.free_module_element import vector - from sage.dynamics.arithmetic_dynamics.generic_ds import DynamicalSystem if not mat.is_square(): raise ValueError("matrix must be square") if mat.nrows() != self.domain().ngens(): @@ -716,14 +724,10 @@ def as_dynamical_system(self): sage: g is f # needs sage.schemes True """ - from sage.dynamics.arithmetic_dynamics.generic_ds import DynamicalSystem if isinstance(self, DynamicalSystem): return self if not self.is_endomorphism(): raise TypeError("must be an endomorphism") - from sage.dynamics.arithmetic_dynamics.projective_ds import DynamicalSystem_projective - from sage.dynamics.arithmetic_dynamics.projective_ds import DynamicalSystem_projective_field - from sage.dynamics.arithmetic_dynamics.projective_ds import DynamicalSystem_projective_finite_field R = self.base_ring() if R not in _Fields: return DynamicalSystem_projective(list(self), self.domain()) @@ -948,7 +952,6 @@ def normalize_coordinates(self, **kwds): # defined by the ideal/valuation ideal = kwds.pop('ideal', None) if ideal is not None: - from sage.rings.number_field.number_field_ideal import NumberFieldFractionalIdeal if not (ideal in ZZ or isinstance(ideal, NumberFieldFractionalIdeal)): raise TypeError('ideal must be an ideal of a number field, not %s' % ideal) if isinstance(ideal, NumberFieldFractionalIdeal): @@ -980,7 +983,6 @@ def normalize_coordinates(self, **kwds): valuation = kwds.pop('valuation', None) if valuation is not None: - from sage.rings.padics.padic_valuation import pAdicValuation_base if not isinstance(valuation, pAdicValuation_base): raise TypeError('valuation must be a valuation on a number field, not %s' % valuation) if valuation.domain() != self.base_ring(): @@ -1048,7 +1050,6 @@ def normalize_coordinates(self, **kwds): self.scale_by(1 / GCD) # If R is not p-adic, we make the first coordinate positive - from sage.rings.padics.padic_base_generic import pAdicGeneric if not isinstance(R, pAdicGeneric): if self[0].lc() < 0: self.scale_by(-1) diff --git a/src/sage/schemes/projective/projective_point.py b/src/sage/schemes/projective/projective_point.py index 1efc16af934..62d51c18f68 100644 --- a/src/sage/schemes/projective/projective_point.py +++ b/src/sage/schemes/projective/projective_point.py @@ -26,26 +26,32 @@ # https://www.gnu.org/licenses/ # **************************************************************************** +from copy import copy + +from sage.arith.functions import lcm +from sage.arith.misc import gcd from sage.categories.integral_domains import IntegralDomains from sage.categories.number_fields import NumberFields -_NumberFields = NumberFields() -from sage.rings.integer_ring import ZZ +from sage.misc.lazy_import import lazy_import +from sage.misc.misc_c import prod +from sage.rings.abc import Order from sage.rings.fraction_field import FractionField -from sage.rings.number_field.order import Order as NumberFieldOrder -from sage.rings.qqbar import number_field_elements_from_algebraics +from sage.rings.integer_ring import ZZ from sage.rings.quotient_ring import QuotientRing_generic from sage.rings.rational_field import QQ -from sage.arith.misc import GCD as gcd -from sage.arith.functions import lcm -from sage.misc.misc_c import prod - -from copy import copy +from sage.rings.ring import CommutativeRing from sage.schemes.generic.morphism import (SchemeMorphism, is_SchemeMorphism, SchemeMorphism_point) from sage.structure.element import AdditiveGroupElement -from sage.structure.sequence import Sequence from sage.structure.richcmp import richcmp, op_EQ, op_NE +from sage.structure.sequence import Sequence + +lazy_import('sage.rings.qqbar', 'number_field_elements_from_algebraics') +lazy_import('sage.schemes.elliptic_curves.ell_point', 'EllipticCurvePoint_field') + +_NumberFields = NumberFields() + # -------------------- @@ -161,8 +167,6 @@ def __init__(self, X, v, check=True): SchemeMorphism.__init__(self, X) if check: - from sage.schemes.elliptic_curves.ell_point import EllipticCurvePoint_field - from sage.rings.ring import CommutativeRing d = X.codomain().ambient_space().ngens() if is_SchemeMorphism(v) or isinstance(v, EllipticCurvePoint_field): v = list(v) @@ -749,7 +753,7 @@ def global_height(self, prec=None): if prec is None: prec = 53 K = self.codomain().base_ring() - if K in _NumberFields or isinstance(K, NumberFieldOrder) or K == ZZ: + if K in _NumberFields or K is ZZ or isinstance(K, Order): P = self else: try: @@ -758,7 +762,7 @@ def global_height(self, prec=None): raise TypeError("must be defined over an algebraic field") else: K = P.codomain().base_ring() - if isinstance(K, NumberFieldOrder): + if isinstance(K, Order): K = K.number_field() # first get rid of the denominators denom = lcm([xi.denominator() for xi in P]) @@ -1138,8 +1142,6 @@ def __init__(self, X, v, check=True): self._normalized = False if check: - from sage.schemes.elliptic_curves.ell_point import EllipticCurvePoint_field - from sage.rings.ring import CommutativeRing d = X.codomain().ambient_space().ngens() if is_SchemeMorphism(v) or isinstance(v, EllipticCurvePoint_field): v = list(v) diff --git a/src/sage/schemes/projective/projective_rational_point.py b/src/sage/schemes/projective/projective_rational_point.py index bc4b3fbdcd4..4e68426fb1f 100644 --- a/src/sage/schemes/projective/projective_rational_point.py +++ b/src/sage/schemes/projective/projective_rational_point.py @@ -54,19 +54,23 @@ # (at your option) any later version. # https://www.gnu.org/licenses/ # **************************************************************************** + from itertools import product from sage.arith.misc import gcd, next_prime, previous_prime, crt from sage.arith.srange import srange -from sage.rings.integer_ring import ZZ -from sage.rings.real_mpfr import RR -from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF +from sage.misc.lazy_import import lazy_import from sage.misc.misc_c import prod from sage.misc.mrange import xmrange from sage.schemes.generic.scheme import Scheme from sage.parallel.ncpus import ncpus from sage.parallel.use_fork import p_iter_fork -from sage.matrix.constructor import matrix +from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF +from sage.rings.integer_ring import ZZ +from sage.schemes.generic.scheme import is_Scheme + +lazy_import('sage.matrix.constructor', 'matrix') +lazy_import('sage.rings.real_mpfr', 'RR') def enum_projective_rational_field(X, B): diff --git a/src/sage/schemes/projective/projective_space.py b/src/sage/schemes/projective/projective_space.py index c05588f4698..c8e50b98cd1 100644 --- a/src/sage/schemes/projective/projective_space.py +++ b/src/sage/schemes/projective/projective_space.py @@ -80,6 +80,8 @@ # **************************************************************************** from itertools import product +import sage.rings.abc + from sage.arith.misc import gcd, binomial from sage.rings.finite_rings.finite_field_base import FiniteField @@ -90,7 +92,6 @@ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing from sage.rings.rational_field import QQ, RationalField from sage.rings.fraction_field import FractionField -from sage.rings.number_field.order import Order from sage.categories.fields import Fields from sage.categories.rings import Rings @@ -98,19 +99,15 @@ from sage.categories.homset import Hom from sage.categories.map import Map from sage.misc.latex import latex +from sage.misc.lazy_import import lazy_import from sage.misc.misc_c import prod from sage.misc.persist import register_unpickle_override from sage.structure.category_object import normalize_names from sage.structure.unique_representation import UniqueRepresentation from sage.combinat.integer_vector import IntegerVectors -from sage.combinat.integer_vector_weighted import WeightedIntegerVectors from sage.combinat.permutation import Permutation -from sage.combinat.tuple import Tuples -from sage.combinat.tuple import UnorderedTuples from sage.combinat.subset import Subsets -from sage.matrix.constructor import matrix -from sage.modules.free_module_element import prepare from sage.schemes.generic.ambient_space import AmbientSpace from sage.schemes.projective.projective_homset import (SchemeHomset_points_projective_ring, SchemeHomset_points_projective_field, @@ -122,6 +119,17 @@ SchemeMorphism_polynomial_projective_space_field, SchemeMorphism_polynomial_projective_space_finite_field) +lazy_import('sage.combinat.integer_vector_weighted', 'WeightedIntegerVectors') +lazy_import('sage.combinat.tuple', ['Tuples', 'UnorderedTuples']) +lazy_import('sage.dynamics.arithmetic_dynamics.projective_ds', 'DynamicalSystem_projective') +lazy_import('sage.matrix.constructor', 'matrix') +lazy_import('sage.modules.free_module_element', 'prepare') +lazy_import('sage.schemes.generic.algebraic_scheme', 'AlgebraicScheme_subscheme') +lazy_import('sage.schemes.product_projective.space', + ['ProductProjectiveSpaces', 'ProductProjectiveSpaces_ring']) +lazy_import('sage.schemes.projective.projective_subscheme', + ['AlgebraicScheme_subscheme_projective', 'AlgebraicScheme_subscheme_projective_field']) + # for better efficiency _Fields = Fields() @@ -511,7 +519,6 @@ def __pow__(self, m): mm = int(m) if mm != m: raise ValueError("m must be an integer") - from sage.schemes.product_projective.space import ProductProjectiveSpaces return ProductProjectiveSpaces([self.dimension_relative()] * mm, self.base_ring()) def __mul__(self, right): @@ -562,11 +569,7 @@ def __mul__(self, right): if self.base_ring() != right.base_ring(): raise ValueError('Must have the same base ring') - from sage.schemes.product_projective.space import ProductProjectiveSpaces_ring - from sage.schemes.product_projective.space import ProductProjectiveSpaces - from sage.schemes.generic.algebraic_scheme import AlgebraicScheme_subscheme - - if isinstance(right, (ProductProjectiveSpaces_ring)): + if isinstance(right, ProductProjectiveSpaces_ring): return ProductProjectiveSpaces([self] + right.components()) elif isinstance(right, ProjectiveSpace_ring): if self is right: @@ -990,8 +993,6 @@ def subscheme(self, X): "_test_elements_eq_symmetric", "_test_elements_eq_transitive",\ "_test_elements_neq"]) """ - from sage.schemes.projective.projective_subscheme import (AlgebraicScheme_subscheme_projective, - AlgebraicScheme_subscheme_projective_field) R = self.base_ring() if R.is_field() and R.is_exact(): return AlgebraicScheme_subscheme_projective_field(self, X) @@ -1175,7 +1176,7 @@ def points_of_bounded_height(self, **kwds): elif R in NumberFields(): # True for the rational field as well, so check RationalField first field_type = True - elif (R is ZZ) or (isinstance(R, Order) and R.is_integrally_closed()): # Ensure ring of integers / maximal order + elif R is ZZ or (isinstance(R, sage.rings.abc.Order) and R.is_integrally_closed()): # Ensure ring of integers / maximal order is_ring_of_ints = True else: raise NotImplementedError("self must be a projective space over a number field or a ring of integers") @@ -1364,7 +1365,6 @@ def Lattes_map(self, E, m): x, y = R.gens() phi = F[0].parent().hom([x], R) F = [phi(F[0]).homogenize(y), phi(F[1]).homogenize(y) * y] - from sage.dynamics.arithmetic_dynamics.projective_ds import DynamicalSystem_projective return DynamicalSystem_projective(F, domain=self) def cartesian_product(self, other): @@ -1389,7 +1389,6 @@ def cartesian_product(self, other): sage: PP.gens() (x0, x1, y0, y1, y2) """ - from sage.schemes.product_projective.space import ProductProjectiveSpaces return ProductProjectiveSpaces([self, other]) def chebyshev_polynomial(self, n, kind='first', monic=False): @@ -1556,7 +1555,6 @@ def veronese_embedding(self, d, CS=None, order='lex'): def point_transformation_matrix(self, points_source, points_target, normalize=True): r""" - Returns a unique element of PGL that transforms one set of points to another. Given a projective space of dimension n and a set of n+2 source points and a set of n+2 target @@ -1898,7 +1896,6 @@ def hyperplane_transformation_matrix(self, plane_1, plane_2): ... ValueError: plane_1 must be defined by a single degree 1 equation """ - from sage.schemes.projective.projective_subscheme import AlgebraicScheme_subscheme_projective if not isinstance(plane_1, AlgebraicScheme_subscheme_projective): raise TypeError('plane_1 must be a subscheme') if not isinstance(plane_2, AlgebraicScheme_subscheme_projective): diff --git a/src/sage/schemes/projective/projective_subscheme.py b/src/sage/schemes/projective/projective_subscheme.py index 6135a62b1cb..eff64907afc 100644 --- a/src/sage/schemes/projective/projective_subscheme.py +++ b/src/sage/schemes/projective/projective_subscheme.py @@ -22,19 +22,19 @@ # **************************************************************************** from sage.arith.misc import binomial - from sage.categories.fields import Fields from sage.categories.homset import Hom - -from sage.matrix.constructor import matrix - +from sage.misc.lazy_import import lazy_import from sage.rings.integer_ring import ZZ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing from sage.rings.rational_field import RationalField - from sage.schemes.generic.algebraic_scheme import AlgebraicScheme_subscheme from sage.schemes.projective.projective_morphism import SchemeMorphism_polynomial_projective_subscheme_field +lazy_import('sage.dynamics.arithmetic_dynamics.generic_ds', 'DynamicalSystem') +lazy_import('sage.matrix.constructor', 'matrix') +lazy_import('sage.schemes.elliptic_curves.ell_generic', 'EllipticCurve_generic', as_='EllipticCurve') + class AlgebraicScheme_subscheme_projective(AlgebraicScheme_subscheme): r""" @@ -183,8 +183,8 @@ def dimension(self): Something less obvious:: sage: P3. = ProjectiveSpace(4, QQ) - sage: X = P3.subscheme([x^2, x^2*y^2 + z^2*t^2, z^2 - w^2, 10*x^2 + w^2 - z^2]) - sage: X + sage: X = P3.subscheme([x^2, x^2*y^2 + z^2*t^2, + ....: z^2 - w^2, 10*x^2 + w^2 - z^2]); X Closed subscheme of Projective Space of dimension 4 over Rational Field defined by: x^2, x^2*y^2 + z^2*t^2, @@ -509,7 +509,6 @@ def orbit(self, f, N) -> list: ... TypeError: orbit bounds must be non-negative """ - from sage.dynamics.arithmetic_dynamics.generic_ds import DynamicalSystem if not isinstance(f, DynamicalSystem): raise TypeError("map must be a dynamical system for iteration") if not isinstance(N, (list, tuple)): @@ -753,11 +752,12 @@ def _forward_image(self, f, check=True): ... TypeError: subscheme must be in ambient space of domain of map """ - dom = f.domain() - codom = f.codomain() if check: if not f.is_morphism(): raise TypeError("map must be a morphism") + dom = f.domain() + codom = f.codomain() + if check: if self.ambient_space() != dom: raise TypeError("subscheme must be in ambient space of domain of map") CR_dom = dom.coordinate_ring() @@ -1442,7 +1442,7 @@ def global_height(self, prec=None): sage: P. = ProjectiveSpace(QQ, 2) sage: X = P.subscheme([z^2 - 101*y^2 - 3*x*z]) - sage: X.global_height() # long time # needs sage.libs.singular + sage: X.global_height() # long time # needs sage.libs.singular 4.61512051684126 """ return self.Chow_form().global_height(prec) diff --git a/src/sage/schemes/riemann_surfaces/riemann_surface.py b/src/sage/schemes/riemann_surfaces/riemann_surface.py index b50cc038f47..28d761803b7 100644 --- a/src/sage/schemes/riemann_surfaces/riemann_surface.py +++ b/src/sage/schemes/riemann_surfaces/riemann_surface.py @@ -116,7 +116,6 @@ from sage.arith.functions import lcm from sage.arith.misc import GCD, algdep from sage.ext.fast_callable import fast_callable -from sage.functions.log import lambert_w from sage.graphs.graph import Graph from sage.groups.matrix_gps.finitely_generated import MatrixGroup from sage.groups.perm_gps.permgroup_named import SymmetricGroup @@ -3108,6 +3107,8 @@ def initialise(z, i): else: n_steps = 15 + from sage.functions.log import lambert_w + V = VectorSpace(self._CC, self.genus) h = one Nh = (-lambert_w(-1, -tau / 2) / la).log().ceil() diff --git a/src/sage/schemes/toric/divisor.py b/src/sage/schemes/toric/divisor.py index ff0373b3bef..8ce2a235d52 100644 --- a/src/sage/schemes/toric/divisor.py +++ b/src/sage/schemes/toric/divisor.py @@ -171,11 +171,11 @@ import sage.geometry.abc from sage.geometry.polyhedron.constructor import Polyhedron from sage.geometry.toric_lattice_element import ToricLatticeElement -from sage.topology.simplicial_complex import SimplicialComplex from sage.matrix.constructor import matrix from sage.misc.cachefunc import cached_method from sage.misc.flatten import flatten from sage.misc.latex import latex +from sage.misc.lazy_import import lazy_import from sage.misc.misc_c import prod from sage.modules.free_module_element import vector from sage.modules.free_module import (FreeModule_ambient_field, @@ -189,6 +189,8 @@ from sage.structure.unique_representation import UniqueRepresentation from sage.structure.element import Vector +lazy_import('sage.topology.simplicial_complex', 'SimplicialComplex') + def is_ToricDivisor(x): r""" diff --git a/src/sage/schemes/toric/toric_subscheme.py b/src/sage/schemes/toric/toric_subscheme.py index cddcc91f474..0abe5530f08 100644 --- a/src/sage/schemes/toric/toric_subscheme.py +++ b/src/sage/schemes/toric/toric_subscheme.py @@ -20,7 +20,8 @@ # https://www.gnu.org/licenses/ # **************************************************************************** -from sage.calculus.functions import jacobian +from sage.misc.lazy_import import lazy_import +lazy_import("sage.calculus.functions", "jacobian") from sage.rings.integer_ring import ZZ from sage.schemes.generic.algebraic_scheme import AlgebraicScheme_subscheme diff --git a/src/sage/schemes/toric/variety.py b/src/sage/schemes/toric/variety.py index c1ca8351263..ea9ce4477a8 100644 --- a/src/sage/schemes/toric/variety.py +++ b/src/sage/schemes/toric/variety.py @@ -236,6 +236,7 @@ Every cone defines a torus orbit closure, and hence a (co)homology class:: + sage: # needs sage.libs.singular sage: HH.gens() ([3*z4], [3*z4], [z4], [z4], [z4]) sage: list(map(HH, P4_11133.fan(1))) @@ -248,6 +249,7 @@ We can compute intersection numbers by integrating top-dimensional cohomology classes:: + sage: # needs sage.libs.singular sage: D = P4_11133.divisor(0) sage: HH(D) [3*z4] @@ -302,7 +304,8 @@ import sys -from sage.functions.all import factorial +from sage.misc.lazy_import import lazy_import +lazy_import("sage.functions.all", "factorial") import sage.geometry.abc from sage.geometry.cone import Cone from sage.geometry.fan import Fan From 526593e8b4b0b901269e240672276e23c5751536 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 2 Jun 2024 19:36:58 -0700 Subject: [PATCH 089/231] Codestyle fixes --- src/sage/schemes/berkovich/berkovich_space.py | 1 - src/sage/schemes/projective/projective_point.py | 2 -- 2 files changed, 3 deletions(-) diff --git a/src/sage/schemes/berkovich/berkovich_space.py b/src/sage/schemes/berkovich/berkovich_space.py index d566ccfa0dd..0d9af5518f2 100644 --- a/src/sage/schemes/berkovich/berkovich_space.py +++ b/src/sage/schemes/berkovich/berkovich_space.py @@ -55,7 +55,6 @@ lazy_import('sage.rings.number_field.number_field_ideal', 'NumberFieldFractionalIdeal') - def is_Berkovich(space) -> bool: """ Check if ``space`` is a Berkovich space. diff --git a/src/sage/schemes/projective/projective_point.py b/src/sage/schemes/projective/projective_point.py index 62d51c18f68..2e9dd6fca9f 100644 --- a/src/sage/schemes/projective/projective_point.py +++ b/src/sage/schemes/projective/projective_point.py @@ -52,8 +52,6 @@ _NumberFields = NumberFields() - - # -------------------- # Projective varieties # -------------------- From cc79bffe7d997487c623ee60034d1f5e95c199e9 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 2 Jun 2024 20:43:34 -0700 Subject: [PATCH 090/231] src/sage/schemes/elliptic_curves/ell_curve_isogeny.py: Fix # needs --- src/sage/schemes/elliptic_curves/ell_curve_isogeny.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py b/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py index 2d7291aea10..1345d7ba8ee 100644 --- a/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py +++ b/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py @@ -3720,8 +3720,9 @@ def compute_intermediate_curves(E1, E2): EXAMPLES:: - sage: # needs sage.rings.finite_rings sage: from sage.schemes.elliptic_curves.ell_curve_isogeny import compute_intermediate_curves + + sage: # needs sage.rings.finite_rings sage: E = EllipticCurve(GF(83), [1,0,1,1,0]) sage: R. = GF(83)[]; f = x + 24 sage: phi = EllipticCurveIsogeny(E, f) From c241e3624befc6f31054a48ea58348149dcdb6ec Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 2 Jun 2024 20:50:43 -0700 Subject: [PATCH 091/231] src/sage/schemes/berkovich/berkovich_space.py: Remove duplicate imports --- src/sage/schemes/berkovich/berkovich_space.py | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/sage/schemes/berkovich/berkovich_space.py b/src/sage/schemes/berkovich/berkovich_space.py index 0d9af5518f2..f64b7835f79 100644 --- a/src/sage/schemes/berkovich/berkovich_space.py +++ b/src/sage/schemes/berkovich/berkovich_space.py @@ -31,13 +31,6 @@ # https://www.gnu.org/licenses/ # **************************************************************************** -from sage.schemes.berkovich.berkovich_cp_element import (Berkovich_Element_Cp_Affine, - Berkovich_Element_Cp_Projective) -from sage.structure.parent import Parent -from sage.schemes.affine.affine_space import AffineSpace_generic -from sage.schemes.projective.projective_space import ProjectiveSpace_ring, ProjectiveSpace -from sage.structure.unique_representation import UniqueRepresentation -from sage.categories.number_fields import NumberFields import sage.rings.abc from sage.categories.number_fields import NumberFields @@ -45,10 +38,10 @@ from sage.misc.lazy_import import lazy_import from sage.rings.integer_ring import ZZ from sage.rings.rational_field import QQ -from sage.schemes.affine.affine_space import is_AffineSpace +from sage.schemes.affine.affine_space import AffineSpace_generic from sage.schemes.berkovich.berkovich_cp_element import (Berkovich_Element_Cp_Affine, Berkovich_Element_Cp_Projective) -from sage.schemes.projective.projective_space import is_ProjectiveSpace, ProjectiveSpace +from sage.schemes.projective.projective_space import ProjectiveSpace_ring, ProjectiveSpace from sage.structure.parent import Parent from sage.structure.unique_representation import UniqueRepresentation From 80baf6beb34c3fe97f3634923eec70fdd11b8972 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 2 Jun 2024 20:53:04 -0700 Subject: [PATCH 092/231] src/sage/schemes/curves/zariski_vankampen.py: Fix whitespace --- src/sage/schemes/curves/zariski_vankampen.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/schemes/curves/zariski_vankampen.py b/src/sage/schemes/curves/zariski_vankampen.py index 5e035c3811c..b4c1cb7bfe9 100644 --- a/src/sage/schemes/curves/zariski_vankampen.py +++ b/src/sage/schemes/curves/zariski_vankampen.py @@ -44,8 +44,8 @@ import itertools from copy import copy - from itertools import combinations + from sage.combinat.permutation import Permutation from sage.functions.generalized import sign from sage.geometry.voronoi_diagram import VoronoiDiagram From 4d0965135620e51b59a2140a61d297fbbaf619cb Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 2 Jun 2024 21:05:06 -0700 Subject: [PATCH 093/231] src/sage/schemes/elliptic_curves: Sort imports --- src/sage/schemes/elliptic_curves/ell_point.py | 20 +++--- .../elliptic_curves/ell_rational_field.py | 71 +++++++++---------- .../schemes/elliptic_curves/lseries_ell.py | 11 +-- 3 files changed, 47 insertions(+), 55 deletions(-) diff --git a/src/sage/schemes/elliptic_curves/ell_point.py b/src/sage/schemes/elliptic_curves/ell_point.py index 2d3037733fc..568d76ffc94 100644 --- a/src/sage/schemes/elliptic_curves/ell_point.py +++ b/src/sage/schemes/elliptic_curves/ell_point.py @@ -121,26 +121,22 @@ import sage.rings.abc from sage.misc.lazy_import import lazy_import +from sage.rings.finite_rings.integer_mod import Mod from sage.rings.infinity import Infinity as oo from sage.rings.integer import Integer from sage.rings.integer_ring import ZZ from sage.rings.padics.precision_error import PrecisionError from sage.rings.rational_field import QQ -from sage.rings.finite_rings.integer_mod import Mod -from sage.rings.real_mpfr import RealField -from sage.rings.real_mpfr import RR -from sage.structure.element import AdditiveGroupElement -from sage.structure.sequence import Sequence -from sage.structure.richcmp import richcmp - -from sage.structure.coerce_actions import IntegerMulAction - +from sage.rings.real_mpfr import RealField, RR from sage.schemes.curves.projective_curve import Hasse_bounds +from sage.schemes.elliptic_curves.constructor import EllipticCurve +from sage.schemes.generic.morphism import is_SchemeMorphism from sage.schemes.projective.projective_point import (SchemeMorphism_point_projective_ring, SchemeMorphism_point_abelian_variety_field) -from sage.schemes.generic.morphism import is_SchemeMorphism - -from .constructor import EllipticCurve +from sage.structure.coerce_actions import IntegerMulAction +from sage.structure.element import AdditiveGroupElement +from sage.structure.richcmp import richcmp +from sage.structure.sequence import Sequence lazy_import('sage.rings.padics.factory', 'Qp') diff --git a/src/sage/schemes/elliptic_curves/ell_rational_field.py b/src/sage/schemes/elliptic_curves/ell_rational_field.py index 96a009b7b2c..441ba994e63 100644 --- a/src/sage/schemes/elliptic_curves/ell_rational_field.py +++ b/src/sage/schemes/elliptic_curves/ell_rational_field.py @@ -47,60 +47,55 @@ # # https://www.gnu.org/licenses/ ############################################################################## -from itertools import product - -from . import constructor -from . import BSD -from .ell_generic import EllipticCurve_generic -from . import ell_modular_symbols -from .ell_number_field import EllipticCurve_number_field -from . import ell_point -from . import ell_tate_curve -from . import ell_torsion -from . import heegner -from . import mod5family -from .modular_parametrization import ModularParameterization -from . import padics -from sage.modular.modsym.modsym import ModularSymbols -from sage.modular.pollack_stevens.space import ps_modsym_from_elliptic_curve +from copy import copy +from itertools import product +from math import sqrt +import sage.arith.all as arith +import sage.databases.cremona import sage.modular.modform.constructor import sage.modular.modform.element -import sage.databases.cremona -import sage.arith.all as arith -from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF +from sage.matrix.matrix_space import MatrixSpace +from sage.misc.cachefunc import cached_method +from sage.misc.lazy_import import lazy_import +from sage.misc.misc_c import prod, prod as mul +from sage.misc.verbose import verbose as verbose_verbose +from sage.modular.modsym.modsym import ModularSymbols +from sage.modular.pollack_stevens.space import ps_modsym_from_elliptic_curve +from sage.rings.complex_mpfr import ComplexField from sage.rings.fast_arith import prime_range -from sage.rings.real_mpfr import RR -from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing -from sage.structure.element import RingElement -from sage.rings.power_series_ring import PowerSeriesRing +from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF from sage.rings.infinity import Infinity as oo +from sage.rings.integer import Integer from sage.rings.integer_ring import ZZ, IntegerRing +from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing +from sage.rings.power_series_ring import PowerSeriesRing from sage.rings.rational_field import QQ -from sage.rings.integer import Integer -from sage.rings.real_mpfi import RealIntervalField -from sage.rings.real_mpfr import RealField -from sage.rings.complex_mpfr import ComplexField from sage.rings.rational_field import RationalField - +from sage.rings.real_mpfi import RealIntervalField +from sage.rings.real_mpfr import RealField, RR from sage.structure.coerce import py_scalar_to_element -from sage.structure.element import Element -from sage.misc.misc_c import prod as mul -from sage.misc.misc_c import prod -from sage.misc.verbose import verbose as verbose_verbose +from sage.structure.element import Element, RingElement -from sage.misc.lazy_import import lazy_import lazy_import("sage.functions.log", "log") - -from sage.matrix.matrix_space import MatrixSpace lazy_import('sage.libs.pari.all', 'pari') lazy_import("sage.functions.gamma", "gamma_inc") -from math import sqrt lazy_import('sage.interfaces.gp', 'gp') -from sage.misc.cachefunc import cached_method -from copy import copy + +from . import constructor +from . import BSD +from .ell_generic import EllipticCurve_generic +from . import ell_modular_symbols +from .ell_number_field import EllipticCurve_number_field +from . import ell_point +from . import ell_tate_curve +from . import ell_torsion +from . import heegner +from . import mod5family +from .modular_parametrization import ModularParameterization +from . import padics Q = RationalField() C = ComplexField() diff --git a/src/sage/schemes/elliptic_curves/lseries_ell.py b/src/sage/schemes/elliptic_curves/lseries_ell.py index 6a73953ff62..cd5cd43cbdf 100644 --- a/src/sage/schemes/elliptic_curves/lseries_ell.py +++ b/src/sage/schemes/elliptic_curves/lseries_ell.py @@ -20,12 +20,13 @@ # http://www.gnu.org/licenses/ #***************************************************************************** -from sage.structure.sage_object import SageObject -from sage.rings.real_mpfr import RealField -from sage.rings.rational_field import RationalField -from math import sqrt, log, ceil -from sage.misc.verbose import verbose +from math import ceil, log, sqrt + from sage.misc.cachefunc import cached_method +from sage.misc.verbose import verbose +from sage.rings.rational_field import RationalField +from sage.rings.real_mpfr import RealField +from sage.structure.sage_object import SageObject class Lseries_ell(SageObject): From 3e6acd5969a7e33ada8cce102bd877bf404102f4 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 2 Jun 2024 21:08:19 -0700 Subject: [PATCH 094/231] src/sage/schemes/elliptic_curves/ell_curve_isogeny.py: Remove unnecessary # needs --- src/sage/schemes/elliptic_curves/ell_curve_isogeny.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py b/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py index 1345d7ba8ee..b2a244998cd 100644 --- a/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py +++ b/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py @@ -192,7 +192,6 @@ def isogeny_codomain_from_kernel(E, kernel): EXAMPLES:: - sage: # needs sage.rings.finite_rings sage: from sage.schemes.elliptic_curves.ell_curve_isogeny import isogeny_codomain_from_kernel sage: E = EllipticCurve(GF(7), [1,0,1,0,1]) sage: R. = GF(7)[] @@ -403,7 +402,6 @@ def compute_codomain_kohel(E, kernel): EXAMPLES:: - sage: # needs sage.rings.finite_rings sage: from sage.schemes.elliptic_curves.ell_curve_isogeny import compute_codomain_kohel sage: E = EllipticCurve(GF(19), [1,2,3,4,5]) sage: phi = EllipticCurveIsogeny(E, [9,1]) @@ -3722,7 +3720,6 @@ def compute_intermediate_curves(E1, E2): sage: from sage.schemes.elliptic_curves.ell_curve_isogeny import compute_intermediate_curves - sage: # needs sage.rings.finite_rings sage: E = EllipticCurve(GF(83), [1,0,1,1,0]) sage: R. = GF(83)[]; f = x + 24 sage: phi = EllipticCurveIsogeny(E, f) From cfa6a7b8a8f2b01273b75adfb58cd29954f7268f Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 22 Jun 2024 13:05:15 -0700 Subject: [PATCH 095/231] src/sage/schemes: Sort imports --- src/sage/schemes/elliptic_curves/height.py | 17 +++++---- .../schemes/projective/projective_morphism.py | 14 ++++--- .../schemes/projective/projective_space.py | 37 +++++++++---------- 3 files changed, 34 insertions(+), 34 deletions(-) diff --git a/src/sage/schemes/elliptic_curves/height.py b/src/sage/schemes/elliptic_curves/height.py index 82a213cd9b7..9b5b6176b80 100644 --- a/src/sage/schemes/elliptic_curves/height.py +++ b/src/sage/schemes/elliptic_curves/height.py @@ -29,21 +29,22 @@ import numpy import math import bisect + from itertools import product -from sage.rings.integer_ring import ZZ -from sage.rings.rational_field import QQ -from sage.rings.infinity import infinity +from sage.arith.functions import lcm +from sage.arith.misc import factorial +from sage.ext.fast_callable import fast_callable +from sage.misc.cachefunc import cached_method +from sage.misc.lazy_import import lazy_import from sage.rings.cc import CC from sage.rings.complex_double import CDF +from sage.rings.infinity import infinity +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ from sage.rings.real_double import RDF from sage.rings.real_mpfr import RR -from sage.misc.cachefunc import cached_method -from sage.arith.functions import lcm -from sage.arith.misc import factorial -from sage.ext.fast_callable import fast_callable -from sage.misc.lazy_import import lazy_import lazy_import("sage.functions.log", ["log", "exp"]) lazy_import("sage.rings.cif", "CIF") lazy_import("sage.rings.real_mpfi", "RIF") diff --git a/src/sage/schemes/projective/projective_morphism.py b/src/sage/schemes/projective/projective_morphism.py index b6c93310550..472d6227987 100644 --- a/src/sage/schemes/projective/projective_morphism.py +++ b/src/sage/schemes/projective/projective_morphism.py @@ -58,13 +58,19 @@ # **************************************************************************** import sys + +import sage.rings.abc + from sage.arith.functions import lcm from sage.arith.misc import GCD as gcd +from sage.categories.fields import Fields +from sage.categories.finite_fields import FiniteFields +from sage.categories.homset import Hom, End +from sage.categories.number_fields import NumberFields from sage.misc.cachefunc import cached_method -from sage.misc.misc_c import prod from sage.misc.lazy_attribute import lazy_attribute from sage.misc.lazy_import import lazy_import -import sage.rings.abc +from sage.misc.misc_c import prod from sage.rings.finite_rings.finite_field_base import FiniteField from sage.rings.fraction_field import FractionField from sage.rings.integer import Integer @@ -73,10 +79,6 @@ from sage.rings.quotient_ring import QuotientRing_generic from sage.rings.rational_field import QQ from sage.schemes.generic.morphism import SchemeMorphism_polynomial -from sage.categories.finite_fields import FiniteFields -from sage.categories.number_fields import NumberFields -from sage.categories.homset import Hom, End -from sage.categories.fields import Fields lazy_import('sage.dynamics.arithmetic_dynamics.generic_ds', 'DynamicalSystem') lazy_import('sage.dynamics.arithmetic_dynamics.projective_ds', diff --git a/src/sage/schemes/projective/projective_space.py b/src/sage/schemes/projective/projective_space.py index c8e50b98cd1..188bab9ba28 100644 --- a/src/sage/schemes/projective/projective_space.py +++ b/src/sage/schemes/projective/projective_space.py @@ -83,41 +83,38 @@ import sage.rings.abc from sage.arith.misc import gcd, binomial - -from sage.rings.finite_rings.finite_field_base import FiniteField -from sage.rings.integer import Integer -from sage.rings.integer_ring import ZZ -from sage.rings.polynomial.multi_polynomial_ring import is_MPolynomialRing -from sage.rings.polynomial.polynomial_ring import is_PolynomialRing -from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing -from sage.rings.rational_field import QQ, RationalField -from sage.rings.fraction_field import FractionField - from sage.categories.fields import Fields -from sage.categories.rings import Rings -from sage.categories.number_fields import NumberFields from sage.categories.homset import Hom from sage.categories.map import Map +from sage.categories.number_fields import NumberFields +from sage.categories.rings import Rings +from sage.combinat.integer_vector import IntegerVectors +from sage.combinat.permutation import Permutation +from sage.combinat.subset import Subsets from sage.misc.latex import latex from sage.misc.lazy_import import lazy_import from sage.misc.misc_c import prod from sage.misc.persist import register_unpickle_override - +from sage.rings.finite_rings.finite_field_base import FiniteField +from sage.rings.fraction_field import FractionField +from sage.rings.integer import Integer +from sage.rings.integer_ring import ZZ +from sage.rings.polynomial.multi_polynomial_ring import is_MPolynomialRing +from sage.rings.polynomial.polynomial_ring import is_PolynomialRing +from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing +from sage.rings.rational_field import QQ, RationalField +from sage.schemes.generic.ambient_space import AmbientSpace from sage.structure.category_object import normalize_names from sage.structure.unique_representation import UniqueRepresentation -from sage.combinat.integer_vector import IntegerVectors -from sage.combinat.permutation import Permutation -from sage.combinat.subset import Subsets -from sage.schemes.generic.ambient_space import AmbientSpace from sage.schemes.projective.projective_homset import (SchemeHomset_points_projective_ring, SchemeHomset_points_projective_field, SchemeHomset_polynomial_projective_space) -from sage.schemes.projective.projective_point import (SchemeMorphism_point_projective_ring, - SchemeMorphism_point_projective_field, - SchemeMorphism_point_projective_finite_field) from sage.schemes.projective.projective_morphism import (SchemeMorphism_polynomial_projective_space, SchemeMorphism_polynomial_projective_space_field, SchemeMorphism_polynomial_projective_space_finite_field) +from sage.schemes.projective.projective_point import (SchemeMorphism_point_projective_ring, + SchemeMorphism_point_projective_field, + SchemeMorphism_point_projective_finite_field) lazy_import('sage.combinat.integer_vector_weighted', 'WeightedIntegerVectors') lazy_import('sage.combinat.tuple', ['Tuples', 'UnorderedTuples']) From 635a14f1767dd129bea5802d1868b36e019832d5 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 3 Jun 2024 09:59:27 -0700 Subject: [PATCH 096/231] src/sage/schemes/elliptic_curves/ell_curve_isogeny.py: Revert add of blank line in doctest --- src/sage/schemes/elliptic_curves/ell_curve_isogeny.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py b/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py index b2a244998cd..bce46802b9c 100644 --- a/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py +++ b/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py @@ -3719,7 +3719,6 @@ def compute_intermediate_curves(E1, E2): EXAMPLES:: sage: from sage.schemes.elliptic_curves.ell_curve_isogeny import compute_intermediate_curves - sage: E = EllipticCurve(GF(83), [1,0,1,1,0]) sage: R. = GF(83)[]; f = x + 24 sage: phi = EllipticCurveIsogeny(E, f) From dc35e843e98a7547be2c18546f6363886c833bf2 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 3 Jun 2024 10:02:25 -0700 Subject: [PATCH 097/231] Sort imports, separate lazy_import --- .../hyperelliptic_generic.py | 12 +++++++----- src/sage/schemes/toric/toric_subscheme.py | 3 ++- src/sage/schemes/toric/variety.py | 19 +++++++++++-------- 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/src/sage/schemes/hyperelliptic_curves/hyperelliptic_generic.py b/src/sage/schemes/hyperelliptic_curves/hyperelliptic_generic.py index 42709c1a033..fcd904998dd 100644 --- a/src/sage/schemes/hyperelliptic_curves/hyperelliptic_generic.py +++ b/src/sage/schemes/hyperelliptic_curves/hyperelliptic_generic.py @@ -33,16 +33,18 @@ # http://www.gnu.org/licenses/ #***************************************************************************** -from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing +import sage.schemes.curves.projective_curve as plane_curve + +from sage.misc.lazy_import import lazy_import from sage.rings.big_oh import O -from sage.rings.power_series_ring import PowerSeriesRing from sage.rings.laurent_series_ring import LaurentSeriesRing +from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing +from sage.rings.power_series_ring import PowerSeriesRing from sage.rings.real_mpfr import RR -from sage.misc.lazy_import import lazy_import -lazy_import("sage.functions.all", "log") from sage.structure.category_object import normalize_names -import sage.schemes.curves.projective_curve as plane_curve +lazy_import("sage.functions.all", "log") + def is_HyperellipticCurve(C): """ diff --git a/src/sage/schemes/toric/toric_subscheme.py b/src/sage/schemes/toric/toric_subscheme.py index 0abe5530f08..93f35acbc2e 100644 --- a/src/sage/schemes/toric/toric_subscheme.py +++ b/src/sage/schemes/toric/toric_subscheme.py @@ -21,10 +21,11 @@ # **************************************************************************** from sage.misc.lazy_import import lazy_import -lazy_import("sage.calculus.functions", "jacobian") from sage.rings.integer_ring import ZZ from sage.schemes.generic.algebraic_scheme import AlgebraicScheme_subscheme +lazy_import("sage.calculus.functions", "jacobian") + class AlgebraicScheme_subscheme_toric(AlgebraicScheme_subscheme): r""" diff --git a/src/sage/schemes/toric/variety.py b/src/sage/schemes/toric/variety.py index ea9ce4477a8..8cedd73e620 100644 --- a/src/sage/schemes/toric/variety.py +++ b/src/sage/schemes/toric/variety.py @@ -304,26 +304,29 @@ import sys -from sage.misc.lazy_import import lazy_import -lazy_import("sage.functions.all", "factorial") import sage.geometry.abc + +from sage.categories.fields import Fields from sage.geometry.cone import Cone from sage.geometry.fan import Fan +from sage.misc.cachefunc import cached_method from sage.misc.latex import latex +from sage.misc.lazy_import import lazy_import from sage.misc.misc_c import prod -from sage.misc.cachefunc import cached_method -from sage.structure.unique_representation import UniqueRepresentation from sage.modules.free_module_element import vector -from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing from sage.rings.integer_ring import ZZ -from sage.rings.rational_field import QQ -from sage.rings.quotient_ring_element import QuotientRingElement +from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing from sage.rings.quotient_ring import QuotientRing_generic +from sage.rings.quotient_ring_element import QuotientRingElement +from sage.rings.rational_field import QQ from sage.schemes.affine.affine_space import AffineSpace from sage.schemes.generic.ambient_space import AmbientSpace from sage.schemes.toric.homset import SchemeHomset_points_toric_field from sage.structure.category_object import certify_names -from sage.categories.fields import Fields +from sage.structure.unique_representation import UniqueRepresentation + +lazy_import("sage.functions.all", "factorial") + _Fields = Fields() From d6ec5dd39e669f6325bacb2fb779ca1c48e8bd42 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 26 May 2024 23:44:08 -0700 Subject: [PATCH 098/231] build/pkgs/mathics: Reduce to pip package, remove dependencies --- build/pkgs/mathics/checksums.ini | 4 ---- build/pkgs/mathics/dependencies | 2 +- build/pkgs/mathics/package-version.txt | 1 - ...rsion_requirements.txt => requirements.txt} | 0 build/pkgs/mathics/spkg-install.in | 2 -- build/pkgs/mathics_scanner/SPKG.rst | 18 ------------------ build/pkgs/mathics_scanner/checksums.ini | 4 ---- build/pkgs/mathics_scanner/dependencies | 4 ---- build/pkgs/mathics_scanner/math | 0 build/pkgs/mathics_scanner/package-version.txt | 1 - build/pkgs/mathics_scanner/spkg-configure.m4 | 1 - build/pkgs/mathics_scanner/spkg-install.in | 2 -- build/pkgs/mathics_scanner/type | 1 - .../mathics_scanner/version_requirements.txt | 1 - build/pkgs/palettable/SPKG.rst | 16 ---------------- build/pkgs/palettable/checksums.ini | 4 ---- build/pkgs/palettable/dependencies | 4 ---- build/pkgs/palettable/distros/conda.txt | 1 - build/pkgs/palettable/package-version.txt | 1 - build/pkgs/palettable/spkg-configure.m4 | 1 - build/pkgs/palettable/spkg-install.in | 2 -- build/pkgs/palettable/type | 1 - build/pkgs/palettable/version_requirements.txt | 1 - build/pkgs/pint/SPKG.rst | 18 ------------------ build/pkgs/pint/checksums.ini | 4 ---- build/pkgs/pint/dependencies | 4 ---- build/pkgs/pint/distros/conda.txt | 1 - build/pkgs/pint/package-version.txt | 1 - build/pkgs/pint/spkg-configure.m4 | 1 - build/pkgs/pint/spkg-install.in | 2 -- build/pkgs/pint/type | 1 - build/pkgs/pint/version_requirements.txt | 1 - 32 files changed, 1 insertion(+), 104 deletions(-) delete mode 100644 build/pkgs/mathics/checksums.ini delete mode 100644 build/pkgs/mathics/package-version.txt rename build/pkgs/mathics/{version_requirements.txt => requirements.txt} (100%) delete mode 100644 build/pkgs/mathics/spkg-install.in delete mode 100644 build/pkgs/mathics_scanner/SPKG.rst delete mode 100644 build/pkgs/mathics_scanner/checksums.ini delete mode 100644 build/pkgs/mathics_scanner/dependencies delete mode 100644 build/pkgs/mathics_scanner/math delete mode 100644 build/pkgs/mathics_scanner/package-version.txt delete mode 100644 build/pkgs/mathics_scanner/spkg-configure.m4 delete mode 100644 build/pkgs/mathics_scanner/spkg-install.in delete mode 100644 build/pkgs/mathics_scanner/type delete mode 100644 build/pkgs/mathics_scanner/version_requirements.txt delete mode 100644 build/pkgs/palettable/SPKG.rst delete mode 100644 build/pkgs/palettable/checksums.ini delete mode 100644 build/pkgs/palettable/dependencies delete mode 100644 build/pkgs/palettable/distros/conda.txt delete mode 100644 build/pkgs/palettable/package-version.txt delete mode 100644 build/pkgs/palettable/spkg-configure.m4 delete mode 100644 build/pkgs/palettable/spkg-install.in delete mode 100644 build/pkgs/palettable/type delete mode 100644 build/pkgs/palettable/version_requirements.txt delete mode 100644 build/pkgs/pint/SPKG.rst delete mode 100644 build/pkgs/pint/checksums.ini delete mode 100644 build/pkgs/pint/dependencies delete mode 100644 build/pkgs/pint/distros/conda.txt delete mode 100644 build/pkgs/pint/package-version.txt delete mode 100644 build/pkgs/pint/spkg-configure.m4 delete mode 100644 build/pkgs/pint/spkg-install.in delete mode 100644 build/pkgs/pint/type delete mode 100644 build/pkgs/pint/version_requirements.txt diff --git a/build/pkgs/mathics/checksums.ini b/build/pkgs/mathics/checksums.ini deleted file mode 100644 index d43327d515d..00000000000 --- a/build/pkgs/mathics/checksums.ini +++ /dev/null @@ -1,4 +0,0 @@ -tarball=Mathics3-VERSION.tar.gz -sha1=a72550d3df97dd4055cf903a9f012683ca2adf35 -sha256=d50ee5ad07db845609078c99af789253337a45f50bef6f8b09262f48dca8da7c -upstream_url=https://pypi.io/packages/source/M/Mathics3/Mathics3-VERSION.tar.gz diff --git a/build/pkgs/mathics/dependencies b/build/pkgs/mathics/dependencies index 11d5626d8c7..47296a7bace 100644 --- a/build/pkgs/mathics/dependencies +++ b/build/pkgs/mathics/dependencies @@ -1,4 +1,4 @@ - | $(PYTHON_TOOLCHAIN) pint palettable mathics_scanner $(PYTHON) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/mathics/package-version.txt b/build/pkgs/mathics/package-version.txt deleted file mode 100644 index fcdb2e109f6..00000000000 --- a/build/pkgs/mathics/package-version.txt +++ /dev/null @@ -1 +0,0 @@ -4.0.0 diff --git a/build/pkgs/mathics/version_requirements.txt b/build/pkgs/mathics/requirements.txt similarity index 100% rename from build/pkgs/mathics/version_requirements.txt rename to build/pkgs/mathics/requirements.txt diff --git a/build/pkgs/mathics/spkg-install.in b/build/pkgs/mathics/spkg-install.in deleted file mode 100644 index 37ac1a53437..00000000000 --- a/build/pkgs/mathics/spkg-install.in +++ /dev/null @@ -1,2 +0,0 @@ -cd src -sdh_pip_install . diff --git a/build/pkgs/mathics_scanner/SPKG.rst b/build/pkgs/mathics_scanner/SPKG.rst deleted file mode 100644 index f5b5fb463d8..00000000000 --- a/build/pkgs/mathics_scanner/SPKG.rst +++ /dev/null @@ -1,18 +0,0 @@ -mathics_scanner: Character Tables and Tokenizer for Mathics and the Wolfram Language -==================================================================================== - -Description ------------ - -Character Tables and Tokenizer for Mathics and the Wolfram Language - -License -------- - -GPL-3.0-only - -Upstream Contact ----------------- - -https://pypi.org/project/Mathics-Scanner/ - diff --git a/build/pkgs/mathics_scanner/checksums.ini b/build/pkgs/mathics_scanner/checksums.ini deleted file mode 100644 index 9d04979b6bd..00000000000 --- a/build/pkgs/mathics_scanner/checksums.ini +++ /dev/null @@ -1,4 +0,0 @@ -tarball=Mathics_Scanner-VERSION.tar.gz -sha1=c89bb997c1da04c1cfe945d16be96bdb0c6ae9a8 -sha256=7b05939751aacea42f3fc4e7eb1ab111f9fe32bae827e89f46a50e04907b19ef -upstream_url=https://pypi.io/packages/source/m/mathics_scanner/Mathics_Scanner-VERSION.tar.gz diff --git a/build/pkgs/mathics_scanner/dependencies b/build/pkgs/mathics_scanner/dependencies deleted file mode 100644 index 47296a7bace..00000000000 --- a/build/pkgs/mathics_scanner/dependencies +++ /dev/null @@ -1,4 +0,0 @@ - | $(PYTHON_TOOLCHAIN) $(PYTHON) - ----------- -All lines of this file are ignored except the first. diff --git a/build/pkgs/mathics_scanner/math b/build/pkgs/mathics_scanner/math deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/build/pkgs/mathics_scanner/package-version.txt b/build/pkgs/mathics_scanner/package-version.txt deleted file mode 100644 index e8ea05db814..00000000000 --- a/build/pkgs/mathics_scanner/package-version.txt +++ /dev/null @@ -1 +0,0 @@ -1.2.4 diff --git a/build/pkgs/mathics_scanner/spkg-configure.m4 b/build/pkgs/mathics_scanner/spkg-configure.m4 deleted file mode 100644 index 09917819a0f..00000000000 --- a/build/pkgs/mathics_scanner/spkg-configure.m4 +++ /dev/null @@ -1 +0,0 @@ -SAGE_SPKG_CONFIGURE([mathics_scanner], [SAGE_PYTHON_PACKAGE_CHECK([mathics_scanner])]) diff --git a/build/pkgs/mathics_scanner/spkg-install.in b/build/pkgs/mathics_scanner/spkg-install.in deleted file mode 100644 index 37ac1a53437..00000000000 --- a/build/pkgs/mathics_scanner/spkg-install.in +++ /dev/null @@ -1,2 +0,0 @@ -cd src -sdh_pip_install . diff --git a/build/pkgs/mathics_scanner/type b/build/pkgs/mathics_scanner/type deleted file mode 100644 index 134d9bc32d5..00000000000 --- a/build/pkgs/mathics_scanner/type +++ /dev/null @@ -1 +0,0 @@ -optional diff --git a/build/pkgs/mathics_scanner/version_requirements.txt b/build/pkgs/mathics_scanner/version_requirements.txt deleted file mode 100644 index 53e09a35113..00000000000 --- a/build/pkgs/mathics_scanner/version_requirements.txt +++ /dev/null @@ -1 +0,0 @@ -Mathics-Scanner diff --git a/build/pkgs/palettable/SPKG.rst b/build/pkgs/palettable/SPKG.rst deleted file mode 100644 index b0557d6c128..00000000000 --- a/build/pkgs/palettable/SPKG.rst +++ /dev/null @@ -1,16 +0,0 @@ -palettable: Color palettes for Python -===================================== - -Description ------------ - -Color palettes for Python - -License -------- - -Upstream Contact ----------------- - -https://pypi.org/project/palettable/ - diff --git a/build/pkgs/palettable/checksums.ini b/build/pkgs/palettable/checksums.ini deleted file mode 100644 index 1ec683df7d8..00000000000 --- a/build/pkgs/palettable/checksums.ini +++ /dev/null @@ -1,4 +0,0 @@ -tarball=palettable-VERSION.tar.gz -sha1=4bdbbeae7f20bc71ce8246cb5269da2c3046ad62 -sha256=72feca71cf7d79830cd6d9181b02edf227b867d503bec953cf9fa91bf44896bd -upstream_url=https://pypi.io/packages/source/p/palettable/palettable-VERSION.tar.gz diff --git a/build/pkgs/palettable/dependencies b/build/pkgs/palettable/dependencies deleted file mode 100644 index 47296a7bace..00000000000 --- a/build/pkgs/palettable/dependencies +++ /dev/null @@ -1,4 +0,0 @@ - | $(PYTHON_TOOLCHAIN) $(PYTHON) - ----------- -All lines of this file are ignored except the first. diff --git a/build/pkgs/palettable/distros/conda.txt b/build/pkgs/palettable/distros/conda.txt deleted file mode 100644 index 646dd7426bb..00000000000 --- a/build/pkgs/palettable/distros/conda.txt +++ /dev/null @@ -1 +0,0 @@ -palettable diff --git a/build/pkgs/palettable/package-version.txt b/build/pkgs/palettable/package-version.txt deleted file mode 100644 index 15a27998172..00000000000 --- a/build/pkgs/palettable/package-version.txt +++ /dev/null @@ -1 +0,0 @@ -3.3.0 diff --git a/build/pkgs/palettable/spkg-configure.m4 b/build/pkgs/palettable/spkg-configure.m4 deleted file mode 100644 index 76d3715e9fd..00000000000 --- a/build/pkgs/palettable/spkg-configure.m4 +++ /dev/null @@ -1 +0,0 @@ -SAGE_SPKG_CONFIGURE([palettable], [SAGE_PYTHON_PACKAGE_CHECK([palettable])]) diff --git a/build/pkgs/palettable/spkg-install.in b/build/pkgs/palettable/spkg-install.in deleted file mode 100644 index 37ac1a53437..00000000000 --- a/build/pkgs/palettable/spkg-install.in +++ /dev/null @@ -1,2 +0,0 @@ -cd src -sdh_pip_install . diff --git a/build/pkgs/palettable/type b/build/pkgs/palettable/type deleted file mode 100644 index 134d9bc32d5..00000000000 --- a/build/pkgs/palettable/type +++ /dev/null @@ -1 +0,0 @@ -optional diff --git a/build/pkgs/palettable/version_requirements.txt b/build/pkgs/palettable/version_requirements.txt deleted file mode 100644 index 646dd7426bb..00000000000 --- a/build/pkgs/palettable/version_requirements.txt +++ /dev/null @@ -1 +0,0 @@ -palettable diff --git a/build/pkgs/pint/SPKG.rst b/build/pkgs/pint/SPKG.rst deleted file mode 100644 index 05ee603025c..00000000000 --- a/build/pkgs/pint/SPKG.rst +++ /dev/null @@ -1,18 +0,0 @@ -pint: Physical quantities module -================================ - -Description ------------ - -Physical quantities module - -License -------- - -BSD - -Upstream Contact ----------------- - -https://pypi.org/project/Pint/ - diff --git a/build/pkgs/pint/checksums.ini b/build/pkgs/pint/checksums.ini deleted file mode 100644 index 7e883f32e55..00000000000 --- a/build/pkgs/pint/checksums.ini +++ /dev/null @@ -1,4 +0,0 @@ -tarball=Pint-VERSION.tar.gz -sha1=c14ac08ca2d5a68d79ea7cd2252dc7e2a572c56a -sha256=387cf04078dc7dfe4a708033baad54ab61d82ab06c4ee3d4922b1e45d5626067 -upstream_url=https://pypi.io/packages/source/p/pint/Pint-VERSION.tar.gz diff --git a/build/pkgs/pint/dependencies b/build/pkgs/pint/dependencies deleted file mode 100644 index 47296a7bace..00000000000 --- a/build/pkgs/pint/dependencies +++ /dev/null @@ -1,4 +0,0 @@ - | $(PYTHON_TOOLCHAIN) $(PYTHON) - ----------- -All lines of this file are ignored except the first. diff --git a/build/pkgs/pint/distros/conda.txt b/build/pkgs/pint/distros/conda.txt deleted file mode 100644 index 45f523a5a6e..00000000000 --- a/build/pkgs/pint/distros/conda.txt +++ /dev/null @@ -1 +0,0 @@ -pint diff --git a/build/pkgs/pint/package-version.txt b/build/pkgs/pint/package-version.txt deleted file mode 100644 index 847e9aef6d1..00000000000 --- a/build/pkgs/pint/package-version.txt +++ /dev/null @@ -1 +0,0 @@ -0.20.1 diff --git a/build/pkgs/pint/spkg-configure.m4 b/build/pkgs/pint/spkg-configure.m4 deleted file mode 100644 index bfa78b5f327..00000000000 --- a/build/pkgs/pint/spkg-configure.m4 +++ /dev/null @@ -1 +0,0 @@ -SAGE_SPKG_CONFIGURE([pint], [SAGE_PYTHON_PACKAGE_CHECK([pint])]) diff --git a/build/pkgs/pint/spkg-install.in b/build/pkgs/pint/spkg-install.in deleted file mode 100644 index 37ac1a53437..00000000000 --- a/build/pkgs/pint/spkg-install.in +++ /dev/null @@ -1,2 +0,0 @@ -cd src -sdh_pip_install . diff --git a/build/pkgs/pint/type b/build/pkgs/pint/type deleted file mode 100644 index 134d9bc32d5..00000000000 --- a/build/pkgs/pint/type +++ /dev/null @@ -1 +0,0 @@ -optional diff --git a/build/pkgs/pint/version_requirements.txt b/build/pkgs/pint/version_requirements.txt deleted file mode 100644 index a3031611162..00000000000 --- a/build/pkgs/pint/version_requirements.txt +++ /dev/null @@ -1 +0,0 @@ -Pint From 6be1dd602107b6dc994d8190db685202be02ae26 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 27 May 2024 00:01:14 -0700 Subject: [PATCH 099/231] build/pkgs/mathics: Force use of our numpy --- build/pkgs/mathics/dependencies | 2 +- build/pkgs/mathics/requirements.txt | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/build/pkgs/mathics/dependencies b/build/pkgs/mathics/dependencies index 47296a7bace..cb5e642ed7a 100644 --- a/build/pkgs/mathics/dependencies +++ b/build/pkgs/mathics/dependencies @@ -1,4 +1,4 @@ - | $(PYTHON_TOOLCHAIN) $(PYTHON) +numpy | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/mathics/requirements.txt b/build/pkgs/mathics/requirements.txt index e0924d3dace..d853c123b4a 100644 --- a/build/pkgs/mathics/requirements.txt +++ b/build/pkgs/mathics/requirements.txt @@ -1 +1,2 @@ Mathics3 +-c ${SAGE_VENV}/var/lib/sage/scripts/numpy/spkg-requirements.txt From e2e9dd570ee91edcf8d7b352ec603146b0fbe01d Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 27 May 2024 00:07:29 -0700 Subject: [PATCH 100/231] build/pkgs/mathics: Add more dependencies --- build/pkgs/mathics/dependencies | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/pkgs/mathics/dependencies b/build/pkgs/mathics/dependencies index cb5e642ed7a..fad887c5546 100644 --- a/build/pkgs/mathics/dependencies +++ b/build/pkgs/mathics/dependencies @@ -1,4 +1,4 @@ -numpy | $(PYTHON_TOOLCHAIN) $(PYTHON) +numpy pillow mpmath dateutil requests sympy pyyaml charset_normalizer typing_extensions | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. From c00b6c36be80162e7a7b24e9dd562a735628c57a Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 27 May 2024 00:19:36 -0700 Subject: [PATCH 101/231] build/pkgs/mathics: Switch to git version --- build/pkgs/mathics/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/pkgs/mathics/requirements.txt b/build/pkgs/mathics/requirements.txt index d853c123b4a..e3e21e46ab5 100644 --- a/build/pkgs/mathics/requirements.txt +++ b/build/pkgs/mathics/requirements.txt @@ -1,2 +1,2 @@ -Mathics3 +Mathics3 @ git+https://github.com/Mathics3/mathics-core@c3c1791e2eff66c6d7883b4265019c35e4959df6 -c ${SAGE_VENV}/var/lib/sage/scripts/numpy/spkg-requirements.txt From c560ce7039193d739371cefcc6c05bda0d732101 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 27 May 2024 12:36:29 -0700 Subject: [PATCH 102/231] build/pkgs/mathics/requirements.txt: Use https://github.com/Mathics3/mathics-core/pull/1034 --- build/pkgs/mathics/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/pkgs/mathics/requirements.txt b/build/pkgs/mathics/requirements.txt index e3e21e46ab5..6a5180d0b4c 100644 --- a/build/pkgs/mathics/requirements.txt +++ b/build/pkgs/mathics/requirements.txt @@ -1,2 +1,2 @@ -Mathics3 @ git+https://github.com/Mathics3/mathics-core@c3c1791e2eff66c6d7883b4265019c35e4959df6 +Mathics3 @ git+https://github.com/mkoeppe/mathics-core@99536fd39869a72155ca71e2f45b63f68931169a -c ${SAGE_VENV}/var/lib/sage/scripts/numpy/spkg-requirements.txt From 240c06cb9f0513910ece11c7103f5d7a62806b1c Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 27 May 2024 12:36:45 -0700 Subject: [PATCH 103/231] src/sage/features/interfaces.py (Mathics): New --- src/sage/features/interfaces.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/sage/features/interfaces.py b/src/sage/features/interfaces.py index 6d5249ab443..7bb061270fc 100644 --- a/src/sage/features/interfaces.py +++ b/src/sage/features/interfaces.py @@ -91,6 +91,23 @@ def _is_present(self): reason=f"Interface {interface} is not functional: {exception}") +class Mathics(InterfaceFeature): + r""" + A :class:`~sage.features.Feature` describing whether :class:`sage.interfaces.mathics.Mathics` + is present and functional. + + EXAMPLES:: + + sage: from sage.features.interfaces import Mathics + sage: Mathics().is_present() # not tested + FeatureTestResult('mathics', False) + """ + + @staticmethod + def __classcall__(cls): + return InterfaceFeature.__classcall__(cls, 'mathics', 'sage.interfaces.mathics') + + # The following are provided by external software only (no SPKG) class Magma(InterfaceFeature): @@ -223,6 +240,7 @@ def all_features(): [Feature('magma'), Feature('matlab'), Feature('mathematica'), + Feature('mathics'), Feature('maple'), Feature('macaulay2'), Feature('octave'), @@ -231,6 +249,7 @@ def all_features(): return [Magma(), Matlab(), Mathematica(), + Mathics(), Maple(), Macaulay2(), Octave(), From 282e5120ba56f4ca86070e62939a7a39200026ab Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 29 May 2024 11:27:16 -0700 Subject: [PATCH 104/231] build/pkgs/mathics/requirements.txt: Back to Mathics3/mathics-core --- build/pkgs/mathics/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/pkgs/mathics/requirements.txt b/build/pkgs/mathics/requirements.txt index 6a5180d0b4c..10ce8e62632 100644 --- a/build/pkgs/mathics/requirements.txt +++ b/build/pkgs/mathics/requirements.txt @@ -1,2 +1,2 @@ -Mathics3 @ git+https://github.com/mkoeppe/mathics-core@99536fd39869a72155ca71e2f45b63f68931169a +Mathics3 @ git+https://github.com/Mathics3/mathics-core@af5fa42841c237a0537c1d8a3741b12567fbc1de -c ${SAGE_VENV}/var/lib/sage/scripts/numpy/spkg-requirements.txt From 6d4c5f8a2eb3df4d9678f386d2a21dfc145f6cfc Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 29 May 2024 11:27:47 -0700 Subject: [PATCH 105/231] build/pkgs/mathics/requirements.txt: Unpin, just use master branch HEAD --- build/pkgs/mathics/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/pkgs/mathics/requirements.txt b/build/pkgs/mathics/requirements.txt index 10ce8e62632..5335f5690e1 100644 --- a/build/pkgs/mathics/requirements.txt +++ b/build/pkgs/mathics/requirements.txt @@ -1,2 +1,2 @@ -Mathics3 @ git+https://github.com/Mathics3/mathics-core@af5fa42841c237a0537c1d8a3741b12567fbc1de +Mathics3 @ git+https://github.com/Mathics3/mathics-core -c ${SAGE_VENV}/var/lib/sage/scripts/numpy/spkg-requirements.txt From f78b3a1edd153b4de9aaff2ddfafcd50dc0960ac Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 29 May 2024 12:48:51 -0700 Subject: [PATCH 106/231] src/sage/interfaces/mathics.py: Call mathics.core.load_builtin.import_and_load_builtins as suggested --- src/sage/interfaces/mathics.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/sage/interfaces/mathics.py b/src/sage/interfaces/mathics.py index b6ffbd3d4f2..24b564f8f6a 100644 --- a/src/sage/interfaces/mathics.py +++ b/src/sage/interfaces/mathics.py @@ -512,6 +512,8 @@ def _start(self): """ if not self._session: from mathics.session import MathicsSession + from mathics.core.load_builtin import import_and_load_builtins + import_and_load_builtins() self._session = MathicsSession() from sage.interfaces.sympy import sympy_init sympy_init() From 4c521a1a8cf657bf8e5cf3a81ee2ac4f5d28f63e Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 3 Jun 2024 11:01:25 -0700 Subject: [PATCH 107/231] src/sage/doctest/external.py: Update doctest output --- src/sage/doctest/external.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sage/doctest/external.py b/src/sage/doctest/external.py index e1f00d0e740..ceec70230d0 100644 --- a/src/sage/doctest/external.py +++ b/src/sage/doctest/external.py @@ -398,6 +398,7 @@ class AvailableSoftware(): 'magma', 'maple', 'mathematica', + 'mathics', 'matlab', 'octave', 'pdflatex', From 9f475223645477cddb2bc526274c74e208b6486b Mon Sep 17 00:00:00 2001 From: Juan Mauricio Matera Date: Tue, 4 Jun 2024 14:20:44 -0300 Subject: [PATCH 108/231] add __round__ to the customized mpmath lib (#43) --- src/sage/libs/mpmath/ext_main.pyx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/sage/libs/mpmath/ext_main.pyx b/src/sage/libs/mpmath/ext_main.pyx index 29d524536ea..99a0c782423 100644 --- a/src/sage/libs/mpmath/ext_main.pyx +++ b/src/sage/libs/mpmath/ext_main.pyx @@ -1815,7 +1815,7 @@ cdef class mpf_base(mpnumber): sage: X().to_fixed(30) 3489660928 """ - return libmp.to_fixed(self._mpf_, prec) + return libmp.to_fixed(self._mpf_, prec) def __getstate__(self): return libmp.to_pickable(self._mpf_) @@ -2135,6 +2135,9 @@ cdef class mpf(mpf_base): MPF_sqrt(&r.value, &s.value, global_opts) return r + def __round__(self, *args): + return round(float(self), *args) + def __richcmp__(self, other, int op): """ Compares numbers :: From 13bc753f2e2f83ce8dcb934264bb7591edee7b6e Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 22 Jun 2024 15:46:39 -0700 Subject: [PATCH 109/231] src/sage/schemes/toric/variety.py: Fix # needs --- src/sage/schemes/toric/variety.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/sage/schemes/toric/variety.py b/src/sage/schemes/toric/variety.py index 8cedd73e620..b7c78bd8ab5 100644 --- a/src/sage/schemes/toric/variety.py +++ b/src/sage/schemes/toric/variety.py @@ -263,12 +263,14 @@ sage: AA = P4_11133.Chow_group(QQ) sage: list(map(AA, P4_11133.fan(1))) # long time (5s on sage.math, 2012) - [( 0 | 0 | 0 | 3 | 0 ), ( 0 | 0 | 0 | 3 | 0 ), ( 0 | 0 | 0 | 1 | 0 ), ( 0 | 0 | 0 | 1 | 0 ), ( 0 | 0 | 0 | 1 | 0 )] + [( 0 | 0 | 0 | 3 | 0 ), ( 0 | 0 | 0 | 3 | 0 ), + ( 0 | 0 | 0 | 1 | 0 ), ( 0 | 0 | 0 | 1 | 0 ), ( 0 | 0 | 0 | 1 | 0 )] sage: list(map(AA, P4_11133.fan(4))) # long time (5s on sage.math, 2012) - [( 1 | 0 | 0 | 0 | 0 ), ( 1 | 0 | 0 | 0 | 0 ), ( 1 | 0 | 0 | 0 | 0 ), ( 1 | 0 | 0 | 0 | 0 ), ( 1 | 0 | 0 | 0 | 0 )] - sage: AA(cone).intersection_with_divisor(D) # long time (4s on sage.math, 2013) + [( 1 | 0 | 0 | 0 | 0 ), ( 1 | 0 | 0 | 0 | 0 ), + ( 1 | 0 | 0 | 0 | 0 ), ( 1 | 0 | 0 | 0 | 0 ), ( 1 | 0 | 0 | 0 | 0 )] + sage: AA(cone).intersection_with_divisor(D) # long time (4s on sage.math, 2013) # needs sage.libs.singular ( 1 | 0 | 0 | 0 | 0 ) - sage: AA(cone).intersection_with_divisor(D).count_points() # long time + sage: AA(cone).intersection_with_divisor(D).count_points() # long time # needs sage.libs.singular 1 The real advantage of the Chow group is that From 409dd7a4e3c7023b1455db3a2b0c8bc7fa16f423 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 30 May 2024 18:52:48 -0700 Subject: [PATCH 110/231] sage.knots: Modularization fixes (imports), # needs --- src/sage/knots/knot.py | 30 +++- src/sage/knots/knotinfo.py | 107 ++++++----- src/sage/knots/link.py | 352 +++++++++++++++++++++++-------------- 3 files changed, 308 insertions(+), 181 deletions(-) diff --git a/src/sage/knots/knot.py b/src/sage/knots/knot.py index 9d6a73cbfbf..3593983ed4b 100644 --- a/src/sage/knots/knot.py +++ b/src/sage/knots/knot.py @@ -53,6 +53,7 @@ class Knot(Link, Element, metaclass=InheritComparisonClasscallMetaclass): We construct the knot `8_{14}` and compute some invariants:: + sage: # needs sage.groups sage: B = BraidGroup(4) sage: K = Knot(B([1,1,1,2,-1,2,-3,2,-3])) @@ -65,6 +66,7 @@ class Knot(Link, Element, metaclass=InheritComparisonClasscallMetaclass): :: + sage: # needs sage.groups sage: K.alexander_polynomial() -2*t^-2 + 8*t^-1 - 11 + 8*t - 2*t^2 sage: K.jones_polynomial() @@ -88,6 +90,7 @@ def __classcall_private__(self, data, check=True): EXAMPLES:: + sage: # needs sage.groups sage: B = BraidGroup(8) sage: K = Knot(B([-1, -1, -1, 2, 1, -2, 3, -2, 3])) sage: type(K) @@ -101,6 +104,7 @@ def __init__(self, data, check=True): TESTS:: + sage: # needs sage.groups sage: B = BraidGroup(8) sage: K = Knot(B([1, -2, 1, -2])) sage: TestSuite(K).run() @@ -130,6 +134,7 @@ def _repr_(self): EXAMPLES:: + sage: # needs sage.groups sage: B = BraidGroup(8) sage: K = Knot(B([1, 2, 1, 2])) sage: K @@ -269,15 +274,18 @@ def dt_code(self): EXAMPLES:: sage: K = Knot([[1,5,2,4],[5,3,6,2],[3,1,4,6]]) - sage: K.dt_code() + sage: K.dt_code() # needs sage.groups [4, 6, 2] + + sage: # needs sage.groups sage: B = BraidGroup(4) sage: K = Knot(B([1, 2, 1, 2])) sage: K.dt_code() [4, -6, 8, -2] + sage: K = Knot([[[1, -2, 3, -4, 5, -1, 2, -3, 4, -5]], ....: [1, 1, 1, 1, 1]]) - sage: K.dt_code() + sage: K.dt_code() # needs sage.groups [6, 8, 10, 2, 4] """ b = self.braid().Tietze() @@ -333,6 +341,7 @@ def arf_invariant(self): EXAMPLES:: + sage: # needs sage.groups sage: B = BraidGroup(4) sage: K = Knot(B([-1, 2, 1, 2])) sage: K.arf_invariant() @@ -371,6 +380,7 @@ def colored_jones_polynomial(self, N, variab=None, try_inverse=True): EXAMPLES:: + sage: # needs sage.groups sage: W = Knots() sage: K = W.from_dowker_code([-4,-6,-2]) sage: K.colored_jones_polynomial(2) @@ -382,7 +392,7 @@ def colored_jones_polynomial(self, N, variab=None, try_inverse=True): -t^-4 - t^-3 - t^-1 sage: R. = ZZ[] - sage: K.colored_jones_polynomial(2, t+1) + sage: K.colored_jones_polynomial(2, t+1) # needs sage.groups (t^3 + 3*t^2 + 4*t + 1)/(t^4 + 4*t^3 + 6*t^2 + 4*t + 1) """ return self.braid().colored_jones_polynomial(N=N, variab=variab, @@ -407,6 +417,7 @@ def connected_sum(self, other): EXAMPLES:: + sage: # needs sage.groups sage: B = BraidGroup(2) sage: trefoil = Knot(B([1,1,1])) sage: K = trefoil.connected_sum(trefoil); K @@ -424,6 +435,7 @@ def connected_sum(self, other): :: + sage: # needs sage.groups sage: rev_trefoil = Knot(B([-1,-1,-1])) sage: K2 = trefoil.connected_sum(rev_trefoil); K2 Knot represented by 6 crossings @@ -443,6 +455,7 @@ def connected_sum(self, other): the constructing from DT-code may not be unique for non prime knots, see :meth:`from_dowker_code`):: + sage: # needs sage.groups sage: K.dowker_notation() [(4, 1), (2, 5), (6, 3), (10, 7), (8, 11), (12, 9)] sage: K2.dowker_notation() @@ -452,6 +465,7 @@ def connected_sum(self, other): TESTS:: + sage: # needs sage.groups sage: B = BraidGroup(2) sage: trivial = Knots().one() sage: trivial * trivial @@ -552,7 +566,7 @@ def from_gauss_code(self, gauss): sage: W = Knots() sage: K1 = W.from_gauss_code([2, -1, 3, -2, 1, -3]) - sage: K1.alexander_polynomial() + sage: K1.alexander_polynomial() # needs sage.groups t^-1 - 1 + t """ orientations = recover_orientations(gauss)[3] @@ -638,11 +652,13 @@ def from_table(self, n, k): EXAMPLES:: + sage: # needs sage.groups sage: K1 = Knots().from_table(6,3); K1 Knot represented by 6 crossings sage: K1.alexander_polynomial() t^-2 - 3*t^-1 + 5 - 3*t + t^2 + sage: # needs sage.groups sage: K2 = Knots().from_table(8,4); K2 Knot represented by 9 crossings sage: K2.determinant() @@ -650,12 +666,14 @@ def from_table(self, n, k): sage: K2.signature() 2 + sage: # needs sage.groups sage: K3 = Knots().from_table(10,56); K3 Knot represented by 11 crossings sage: K3.jones_polynomial() t^10 - 3*t^9 + 6*t^8 - 9*t^7 + 10*t^6 - 11*t^5 + 10*t^4 - 7*t^3 + 5*t^2 - 2*t + 1 + sage: # needs sage.groups sage: K4 = Knots().from_table(10,100) sage: K4.genus() 4 @@ -678,9 +696,11 @@ def from_table(self, n, k): """ if n > 10: raise ValueError('more than 10 crossings, not in the knot table') - from sage.groups.braid import BraidGroup if (n, k) in small_knots_table: m, word = small_knots_table[(n, k)] + + from sage.groups.braid import BraidGroup + G = BraidGroup(m) return Knot(G(word)) else: diff --git a/src/sage/knots/knotinfo.py b/src/sage/knots/knotinfo.py index 611d502a3d0..e07d13d00a1 100644 --- a/src/sage/knots/knotinfo.py +++ b/src/sage/knots/knotinfo.py @@ -81,9 +81,9 @@ Obtaining an instance of :class:`~sage.groups.braid.Braid`:: - sage: L.braid() + sage: L.braid() # needs sage.groups s1^-2*s0^-1*s1*s0^-1 - sage: type(_) + sage: type(_) # needs sage.groups Obtaining an instance of :class:`Link`:: @@ -127,9 +127,9 @@ Obtaining the HOMFLY-PT polynomial:: - sage: L.homfly_polynomial() + sage: L.homfly_polynomial() # needs sage.groups -v^-1*z - v^-3*z - v^-3*z^-1 + v^-5*z^-1 - sage: _ == l.homfly_polynomial(normalization='vz') + sage: _ == l.homfly_polynomial(normalization='vz') # needs sage.groups True @@ -156,7 +156,7 @@ True sage: K.is_amphicheiral() True - sage: K.jones_polynomial() + sage: K.jones_polynomial() # needs sage.symbolic t^2 - t - 1/t + 1/t^2 + 1 sage: K.kauffman_polynomial() a^2*z^2 + a*z^3 - a^2 - a*z + 2*z^2 + a^-1*z^3 - 1 - a^-1*z + a^-2*z^2 - a^-2 @@ -504,7 +504,7 @@ def _braid_group(self): EXAMPLES:: sage: L = KnotInfo.L4a1_0 - sage: L._braid_group() + sage: L._braid_group() # needs sage.groups Braid group on 3 strands """ try: @@ -527,7 +527,7 @@ def _homfly_pol_ring(self, var1, var2): EXAMPLES:: sage: L = KnotInfo.L4a1_1 - sage: L._homfly_pol_ring('u', 'v') + sage: L._homfly_pol_ring('u', 'v') # needs sage.groups Multivariate Laurent Polynomial Ring in u, v over Integer Ring """ K3_1 = Knots().from_table(3,1) @@ -777,7 +777,7 @@ def braid(self): EXAMPLES:: sage: K = KnotInfo.K3_1 - sage: K.braid() + sage: K.braid() # needs sage.groups s^3 sage: K.braid_notation() (1, 1, 1) @@ -817,7 +817,7 @@ def crossing_number(self): 4 sage: KnotInfo.K3_1.crossing_number() 3 - sage: Link(KnotInfo.L4a1_0.braid()) + sage: Link(KnotInfo.L4a1_0.braid()) # needs sage.groups Link with 2 components represented by 5 crossings """ return knotinfo_int(self[self.items.crossing_number]) @@ -871,14 +871,14 @@ def three_genus(self): EXAMPLES:: - sage: KnotInfo.K5_2.three_genus() # optional - databsase_knotinfo + sage: KnotInfo.K5_2.three_genus() # optional - database_knotinfo 1 Note that this differs from the corresponding result in Sage since the latter is obtained for a Seifert surface that does not have the minimal genus:: - sage: KnotInfo.K5_2.link().genus() + sage: KnotInfo.K5_2.link().genus() # needs sage.groups 3 """ return knotinfo_int(self[self.items.three_genus]) @@ -899,7 +899,7 @@ def signature(self): EXAMPLES:: - sage: KnotInfo.K5_2.signature() # optional - databsase_knotinfo + sage: KnotInfo.K5_2.signature() # optional - database_knotinfo 1 """ return knotinfo_int(self[self.items.signature]) @@ -1047,7 +1047,7 @@ def is_amphicheiral(self, positive=False): True sage: Kn.is_amphicheiral(positive=True) False - sage: KnotInfo.L4a1_0.is_amphicheiral() + sage: KnotInfo.L4a1_0.is_amphicheiral() # needs sage.groups False sage: KnotInfo.L10n59_1.is_amphicheiral() True @@ -1263,6 +1263,7 @@ def homfly_polynomial(self, var1='v', var2='z', original=False): EXAMPLES:: + sage: # needs sage.groups sage: K3_1 = KnotInfo.K3_1 sage: PK3_1 = K3_1.homfly_polynomial(); PK3_1 -v^4 + v^2*z^2 + 2*v^2 @@ -1273,6 +1274,7 @@ def homfly_polynomial(self, var1='v', var2='z', original=False): for proper links:: + sage: # needs sage.groups sage: L4a1_1 = KnotInfo.L4a1_1 sage: PL4a1_1 = L4a1_1.homfly_polynomial(var1='x', var2='y'); PL4a1_1 -x^5*y + x^3*y^3 - x^5*y^-1 + 3*x^3*y + x^3*y^-1 @@ -1282,6 +1284,7 @@ def homfly_polynomial(self, var1='v', var2='z', original=False): check the skein-relation from the KnotInfo description page (applied to one of the positive crossings of the right-handed trefoil):: + sage: # needs sage.groups sage: R = PK3_1.parent() sage: PO = R.one() sage: L2a1_1 = KnotInfo.L2a1_1 @@ -1292,6 +1295,7 @@ def homfly_polynomial(self, var1='v', var2='z', original=False): TESTS:: + sage: # needs sage.groups sage: H = KnotInfo.L11n459_1_1_1.homfly_polynomial() # optional - database_knotinfo sage: all(L.homfly_polynomial() == L.link().homfly_polynomial(normalization='vz')\ for L in KnotInfo if L.crossing_number() < 7) @@ -1360,6 +1364,7 @@ def kauffman_polynomial(self, var1='a', var2='z', original=False): EXAMPLES:: + sage: # needs sage.modules sage: L = KnotInfo.L2a1_1 sage: L.kauffman_polynomial() a^-1*z - a^-1*z^-1 + a^-2 + a^-3*z - a^-3*z^-1 @@ -1467,7 +1472,7 @@ def jones_polynomial(self, variab=None, skein_normalization=False, puiseux=False EXAMPLES:: sage: K = KnotInfo.K4_1 - sage: Kj = K.jones_polynomial(); Kj + sage: Kj = K.jones_polynomial(); Kj # needs sage.symbolic t^2 - t - 1/t + 1/t^2 + 1 sage: Kjs = K.jones_polynomial(skein_normalization=True); Kjs A^-8 - A^-4 + 1 - A^4 + A^8 @@ -1477,17 +1482,17 @@ def jones_polynomial(self, variab=None, skein_normalization=False, puiseux=False for proper links:: sage: L = KnotInfo.L2a1_1 - sage: Lj = L.jones_polynomial(); Lj + sage: Lj = L.jones_polynomial(); Lj # needs sage.symbolic -x^5 - x - sage: Ljt = L.jones_polynomial(use_sqrt=True); Ljt + sage: Ljt = L.jones_polynomial(use_sqrt=True); Ljt # needs sage.symbolic -t^(5/2) - sqrt(t) sage: Ljp = L.jones_polynomial(puiseux=True); Ljp -t^(1/2) - t^(5/2) sage: Ljs = L.jones_polynomial(skein_normalization=True); Ljs -A^2 - A^10 - sage: Lj.parent() + sage: Lj.parent() # needs sage.symbolic Symbolic Ring - sage: Ljt.parent() + sage: Ljt.parent() # needs sage.symbolic Symbolic Ring sage: Ljp.parent() Puiseux Series Ring in t over Integer Ring @@ -1497,17 +1502,17 @@ def jones_polynomial(self, variab=None, skein_normalization=False, puiseux=False Comparison with Sage's results:: sage: k = K.link() - sage: kj = k.jones_polynomial() - sage: bool(Kj == kj) + sage: kj = k.jones_polynomial() # needs sage.symbolic + sage: bool(Kj == kj) # needs sage.symbolic True sage: kjs = k.jones_polynomial(skein_normalization=True) sage: Kjs == kjs True sage: l = L.link() - sage: lj = l.jones_polynomial() - sage: bool(Lj == lj) + sage: lj = l.jones_polynomial() # needs sage.symbolic + sage: bool(Lj == lj) # needs sage.symbolic False - sage: bool(Ljt == lj) # see note above + sage: bool(Ljt == lj) # see note above # needs sage.symbolic True sage: ljs = l.jones_polynomial(skein_normalization=True) sage: Ljs == ljs @@ -1516,6 +1521,7 @@ def jones_polynomial(self, variab=None, skein_normalization=False, puiseux=False Check the skein-relation from the KnotInfo description page (applied to one of the positive crossings of the right-handed trefoil):: + sage: # needs sage.symbolic sage: K3_1 = KnotInfo.K3_1 sage: K3_1j = K3_1.jones_polynomial() sage: L2a1_1j = Ljt # see note above @@ -1650,11 +1656,11 @@ def alexander_polynomial(self, var='t', original=False, laurent_poly=False): Comparison with Sage's results:: sage: k = K.link() - sage: ka = k.alexander_polynomial(); ka + sage: ka = k.alexander_polynomial(); ka # needs sage.groups -t^-1 + 3 - t - sage: K.alexander_polynomial(laurent_poly=True) + sage: K.alexander_polynomial(laurent_poly=True) # needs sage.groups t^-1 - 3 + t - sage: _ == -ka + sage: _ == -ka # needs sage.groups True Launch the KnotInfo description web-page:: @@ -1725,16 +1731,16 @@ def conway_polynomial(self, var='t', original=False): sage: Lc = L.conway_polynomial(); Lc t^3 - Comparision to Sage's results:: + Comparison to Sage's results:: - sage: Kc == K.link().conway_polynomial() + sage: Kc == K.link().conway_polynomial() # needs sage.groups True - sage: Lc == L.link().conway_polynomial() + sage: Lc == L.link().conway_polynomial() # needs sage.groups True Launch the KnotInfo description web-page:: - sage: K.items.conway_polynomial.description_webpage() # not tested + sage: K.items.conway_polynomial.description_webpage() # not tested True """ conway_polynomial = self[self.items.conway_polynomial] @@ -1791,6 +1797,7 @@ def khovanov_polynomial(self, var1='q', var2='t', base_ring=ZZ, original=False, EXAMPLES:: + sage: # needs sage.modules sage: K = KnotInfo.K6_3 sage: Kk = K.khovanov_polynomial(); Kk q^7*t^3 + q^5*t^2 + q^3*t^2 + q^3*t + q*t + 2*q + 2*q^-1 + q^-1*t^-1 @@ -1798,6 +1805,7 @@ def khovanov_polynomial(self, var1='q', var2='t', base_ring=ZZ, original=False, sage: Kk2 = K.khovanov_polynomial(var1='p', base_ring=GF(2)); Kk2 p^7*t^3 + p^5*t^3 + p^5*t^2 + p^3*t + p^-1 + p^-1*t^-1 + p^-3*t^-2 + p^-7*t^-3 + sage: # needs sage.modules sage: L = KnotInfo.L5a1_0 sage: Lk = L.khovanov_polynomial(); Lk q^4*t^2 + t + 2 + 2*q^-2 + q^-2*t^-1 + q^-4*t^-2 + q^-6*t^-2 + q^-8*t^-3 @@ -1806,6 +1814,7 @@ def khovanov_polynomial(self, var1='q', var2='t', base_ring=ZZ, original=False, Obtaining the reduced homology (for knots only):: + sage: # needs sage.modules sage: Kkr = K.khovanov_polynomial(reduced=True); Kkr q^6*t^3 + 2*q^4*t^2 + 2*q^2*t + 3 + 2*q^-2*t^-1 + 2*q^-4*t^-2 + q^-6*t^-3 sage: K.khovanov_polynomial(base_ring=QQ, reduced=True) == Kkr @@ -1819,6 +1828,7 @@ def khovanov_polynomial(self, var1='q', var2='t', base_ring=ZZ, original=False, Obtaining the odd Khovanov homology (for knots only):: + sage: # needs sage.modules sage: K.khovanov_polynomial(odd=True) == Kkr True sage: K.khovanov_polynomial(base_ring=QQ, odd=True) == Kkr @@ -1831,8 +1841,9 @@ def khovanov_polynomial(self, var1='q', var2='t', base_ring=ZZ, original=False, False - Comparision to Sage's results:: + Comparison to Sage's results:: + sage: # needs sage.modules sage: Kk == K.link().khovanov_polynomial() True sage: Kk2 == K.link().khovanov_polynomial(var1='p', base_ring=GF(2)) @@ -1842,6 +1853,7 @@ def khovanov_polynomial(self, var1='q', var2='t', base_ring=ZZ, original=False, TESTS:: + sage: # needs sage.modules sage: KnotInfo.K0_1.inject() Defining K0_1 sage: K0_1.khovanov_polynomial() @@ -1988,16 +2000,16 @@ def link(self, use_item=db.columns().pd_notation, snappy=False): sage: K = KnotInfo.K3_1 sage: K.link() Knot represented by 3 crossings - sage: _.braid() + sage: _.braid() # needs sage.groups s^3 - sage: _ == K.braid() + sage: _ == K.braid() # needs sage.groups True using ``dt_notation``:: sage: K.link(use_item=K.items.dt_notation) Knot represented by 3 crossings - sage: _.braid() + sage: _.braid() # needs sage.groups s^3 sage: L = KnotInfo.L4a1_0 @@ -2032,16 +2044,16 @@ def link(self, use_item=db.columns().pd_notation, snappy=False): using ``braid_notation``:: - sage: L2.link(use_item=L.items.braid_notation) == l2 + sage: L2.link(use_item=L.items.braid_notation) == l2 # needs sage.groups True observe:: - sage: L.link(use_item=L.items.braid_notation) + sage: L.link(use_item=L.items.braid_notation) # needs sage.groups Link with 2 components represented by 5 crossings sage: K6_1 = KnotInfo.K6_1 - sage: K6_1.link().braid() == K6_1.braid() + sage: K6_1.link().braid() == K6_1.braid() # needs sage.groups False also observe:: @@ -2052,6 +2064,7 @@ def link(self, use_item=db.columns().pd_notation, snappy=False): sage: K4_1.pd_notation() [[4, 2, 5, 1], [8, 6, 1, 5], [6, 3, 7, 4], [2, 7, 3, 8]] + sage: # needs sage.groups sage: K5_1 = KnotInfo.K5_1 sage: K5_1.link().braid() s^5 @@ -2102,6 +2115,7 @@ def is_unique(self): EXAMPLES:: + sage: # needs sage.groups sage: KnotInfo.L4a1_0.is_unique() True sage: KnotInfo.L5a1_0.is_unique() @@ -2155,6 +2169,7 @@ def is_recoverable(self, unique=True): EXAMPLES:: + sage: # needs sage.groups sage: KnotInfo.L4a1_0.inject() Defining L4a1_0 sage: L4a1_0.is_recoverable() @@ -2661,6 +2676,7 @@ def is_recoverable(self, unique=True, max_samples=8): EXAMPLES:: + sage: # needs sage.groups sage: KnotInfo.L4a1_0.series().inject() Defining L4a sage: L4a.is_recoverable() @@ -2689,20 +2705,24 @@ def _test_recover(self, **options): EXAMPLES:: - sage: TestSuite(KnotInfo.L5a1_0.series()).run(verbose=True) # indirec doctest + sage: # needs sage.groups + sage: TestSuite(KnotInfo.L5a1_0.series()).run(verbose=True) # indirect doctest running ._test_category() . . . pass running ._test_new() . . . pass running ._test_not_implemented_methods() . . . pass running ._test_pickling() . . . pass running ._test_recover() . . . pass - sage: TestSuite(KnotInfo.K6_1.series()).run(max_samples=infinity) # indirec doctest + sage: TestSuite(KnotInfo.K6_1.series()).run(max_samples=infinity) # indirect doctest """ tester = options['tester'] max_samples = tester._max_samples - if max_samples: - tester.assertTrue(self.is_recoverable(unique=False, max_samples=max_samples)) - else: - tester.assertTrue(self.is_recoverable(unique=False)) + try: + if max_samples: + tester.assertTrue(self.is_recoverable(unique=False, max_samples=max_samples)) + else: + tester.assertTrue(self.is_recoverable(unique=False)) + except ImportError: + pass def inject(self, verbose=True): r""" @@ -2716,7 +2736,6 @@ def inject(self, verbose=True): EXAMPLES:: - sage: from sage.knots.knotinfo import KnotInfoSeries sage: KnotInfoSeries(6, True, True).inject() Defining K6 sage: K6(2) diff --git a/src/sage/knots/link.py b/src/sage/knots/link.py index 7470d8c2837..4a6bc009e3a 100644 --- a/src/sage/knots/link.py +++ b/src/sage/knots/link.py @@ -55,22 +55,26 @@ # https://www.gnu.org/licenses/ # **************************************************************************** -from sage.matrix.constructor import matrix +from copy import deepcopy, copy +from itertools import combinations + from sage.rings.integer_ring import ZZ from sage.graphs.digraph import DiGraph from sage.graphs.graph import Graph from sage.rings.polynomial.laurent_polynomial_ring import LaurentPolynomialRing -from sage.symbolic.ring import SR +from sage.misc.lazy_import import lazy_import from sage.rings.integer import Integer -from sage.numerical.mip import MixedIntegerLinearProgram -from sage.functions.generalized import sign -from sage.homology.chain_complex import ChainComplex from sage.misc.flatten import flatten from sage.misc.cachefunc import cached_method -from copy import deepcopy, copy -from itertools import combinations from sage.structure.sage_object import SageObject +lazy_import("sage.functions.generalized", "sign") +lazy_import('sage.groups.braid', ['Braid', 'BraidGroup']) +lazy_import('sage.homology.chain_complex', 'ChainComplex') +lazy_import('sage.matrix.constructor', 'matrix') +lazy_import('sage.numerical.mip', 'MixedIntegerLinearProgram') +lazy_import("sage.symbolic.ring", "SR") + class Link(SageObject): r""" @@ -87,12 +91,11 @@ class Link(SageObject): - The closure of a braid is a link:: + sage: # needs sage.groups sage: B = BraidGroup(8) - sage: L = Link(B([-1, -1, -1, -2, 1, -2, 3, -2, 3])) - sage: L + sage: L = Link(B([-1, -1, -1, -2, 1, -2, 3, -2, 3])); L Link with 1 component represented by 9 crossings - sage: L = Link(B([1, 2, 1, -2, -1])) - sage: L + sage: L = Link(B([1, 2, 1, -2, -1])); L Link with 2 components represented by 5 crossings .. NOTE:: @@ -163,9 +166,9 @@ class Link(SageObject): We can construct links from the braid group:: + sage: # needs sage.groups sage: B = BraidGroup(4) - sage: L = Link(B([-1, -1, -1, -2, 1, -2, 3, -2])) - sage: L + sage: L = Link(B([-1, -1, -1, -2, 1, -2, 3, -2])); L Link with 2 components represented by 8 crossings .. PLOT:: @@ -177,8 +180,7 @@ class Link(SageObject): :: - sage: L = Link(B([1, 2, 1, 3])) - sage: L + sage: L = Link(B([1, 2, 1, 3])); L # needs sage.groups Link with 2 components represented by 4 crossings .. PLOT:: @@ -197,7 +199,7 @@ class Link(SageObject): sage: L.oriented_gauss_code() [[[1, -4, 3, -1, 10, -9, 6, -7, 8, 5, 4, -3, 2, -6, 7, -8, 9, -10, -5, -2]], [1, -1, 1, 1, 1, -1, -1, -1, -1, -1]] - sage: L.braid() + sage: L.braid() # needs sage.groups s0*s1^-3*s2^-1*s1*s3*s2^2*s1^-1*s0^-1*s2*s1^-1*s3^-1*s2*s1^-1 .. PLOT:: @@ -229,6 +231,7 @@ class Link(SageObject): We construct the knot `7_1` and compute some invariants:: + sage: # needs sage.groups sage: B = BraidGroup(2) sage: L = Link(B([1]*7)) @@ -241,6 +244,7 @@ class Link(SageObject): :: + sage: # needs sage.groups sage: L.alexander_polynomial() t^-3 - t^-2 + t^-1 - 1 + t - t^2 + t^3 sage: L.jones_polynomial() @@ -252,6 +256,7 @@ class Link(SageObject): The links here have removed components in which no strand is used:: + sage: # needs sage.groups sage: B = BraidGroup(8) sage: b = B([1]) sage: L = Link(b) @@ -286,15 +291,16 @@ def __init__(self, data): TESTS:: + sage: # needs sage.groups sage: B = BraidGroup(8) sage: L = Link(B([-1, -1, -1, -2,1, -2, 3, -2])) sage: TestSuite(L).run() sage: L = Link(B([1, 2, 1])) sage: TestSuite(L).run() + sage: L = Link(B.one()) + sage: L = Link([[1, 1, 2, 2]]) sage: TestSuite(L).run() - - sage: L = Link(B.one()) sage: L = Link([]) sage: L = Link([[], []]) @@ -328,9 +334,9 @@ def __init__(self, data): Verify that :issue:`29692` is fixed:: + sage: # needs sage.groups sage: B = BraidGroup(5) - sage: L = Link(B([3,4,3,-4])) - sage: L + sage: L = Link(B([3,4,3,-4])); L Link with 1 component represented by 4 crossings sage: L.braid() s0*s1*s0*s1^-1 @@ -338,7 +344,7 @@ def __init__(self, data): PD code can be a list of 4-tuples:: sage: code = [(2, 5, 3, 6), (4, 1, 5, 2), (6, 3, 1, 4)] - sage: K = Knot(code); K.alexander_polynomial() + sage: K = Knot(code); K.alexander_polynomial() # needs sage.groups t^-1 - 1 + t """ if isinstance(data, list): @@ -367,7 +373,6 @@ def __init__(self, data): self._braid = None else: - from sage.groups.braid import Braid, BraidGroup if isinstance(data, Braid): # Remove all unused strands support = sorted(set().union(*((abs(x), abs(x) + 1) for x in data.Tietze()))) @@ -483,6 +488,7 @@ def fundamental_group(self, presentation='wirtinger'): EXAMPLES:: + sage: # needs sage.groups sage: L = Link([[1, 4, 3, 2], [3, 4, 1, 2]]) sage: L.fundamental_group() Finitely presented group < x0, x1, x2 | x1*x0^-1*x2^-1*x0, x2*x0*x1^-1*x0^-1 > @@ -492,21 +498,23 @@ def fundamental_group(self, presentation='wirtinger'): We can see, for instance, that the two presentations of the group of the figure eight knot correspond to isomorphic groups:: + sage: # needs sage.groups sage: K8 = Knot([[[1, -2, 4, -3, 2, -1, 3, -4]], [1, 1, -1, -1]]) - sage: GA = K8.fundamental_group() - sage: GA + sage: GA = K8.fundamental_group(); GA Finitely presented group < x0, x1, x2, x3 | x2*x0*x3^-1*x0^-1, x0*x2*x1^-1*x2^-1, x1*x3^-1*x2^-1*x3, x3*x1^-1*x0^-1*x1 > - sage: GB = K8.fundamental_group(presentation='braid') - sage: GB - Finitely presented group < x0, x1, x2 | x1*x2^-1*x1^-1*x0*x1*x2*x1*x2^-1*x1^-1*x0^-1*x1*x2*x1^-1*x0^-1, x1*x2^-1*x1^-1*x0*x1*x2*x1^-1*x2^-1*x1^-1*x0^-1*x1*x2*x1^-1*x0*x1*x2*x1*x2^-1*x1^-1*x0^-1*x1*x2*x1^-2, x1*x2^-1*x1^-1*x0*x1*x2*x1^-1*x2^-1 > + sage: GB = K8.fundamental_group(presentation='braid'); GB + Finitely presented group + < x0, x1, x2 | x1*x2^-1*x1^-1*x0*x1*x2*x1*x2^-1*x1^-1*x0^-1*x1*x2*x1^-1*x0^-1, + x1*x2^-1*x1^-1*x0*x1*x2*x1^-1*x2^-1*x1^-1*x0^-1*x1*x2*x1^-1*x0*x1*x2*x1*x2^-1*x1^-1*x0^-1*x1*x2*x1^-2, + x1*x2^-1*x1^-1*x0*x1*x2*x1^-1*x2^-1 > sage: GA.simplified() - Finitely presented group < x0, x1 | - x1^-1*x0*x1*x0^-1*x1*x0*x1^-1*x0^-1*x1*x0^-1 > + Finitely presented group + < x0, x1 | x1^-1*x0*x1*x0^-1*x1*x0*x1^-1*x0^-1*x1*x0^-1 > sage: GB.simplified() - Finitely presented group < x0, x2 | - x2^-1*x0*x2^-1*x0^-1*x2*x0*x2^-1*x0*x2*x0^-1 > + Finitely presented group + < x0, x2 | x2^-1*x0*x2^-1*x0^-1*x2*x0*x2^-1*x0*x2*x0^-1 > """ from sage.groups.free_group import FreeGroup if presentation == 'braid': @@ -538,10 +546,11 @@ def _repr_(self): EXAMPLES:: + sage: # needs sage.groups sage: B = BraidGroup(8) - sage: L = Link(B([1, 2, 1, 2])) - sage: L + sage: L = Link(B([1, 2, 1, 2])); L Link with 1 component represented by 4 crossings + sage: L = Link([[[-1, 2], [-3, 4], [1, 3, -4, -2]], [-1, -1, 1, 1]]) sage: L Link with 3 components represented by 4 crossings @@ -560,6 +569,7 @@ def __eq__(self, other): TESTS:: + sage: # needs sage.groups sage: B = BraidGroup(8) sage: L1 = Link(B([-1, -1, -1, -2, 1, -2, 3, -2, 5, 4])) sage: L2 = Link(B([-1, -1, -1, -2, 1, -2, 3, -2, 5, 4])) @@ -585,6 +595,7 @@ def __hash__(self): EXAMPLES:: + sage: # needs sage.groups sage: B = BraidGroup(8) sage: L1 = Link(B([-1, -1, -1, -2, 1, -2, 3, -2, 5, 4])) sage: H = hash(L1) @@ -597,6 +608,7 @@ def __ne__(self, other): TESTS:: + sage: # needs sage.groups sage: B = BraidGroup(8) sage: L1 = Link(B([-1, -1, -1, -2, 1, -2, 3, -2, 5, 4])) sage: L2 = Link(B([-1, -1, -1, -2, 1, -2, 3, -2, 5, 4])) @@ -629,6 +641,7 @@ def braid(self, remove_loops=False): EXAMPLES:: + sage: # needs sage.groups sage: L = Link([[2, 4, 1, 3], [4, 2, 3, 1]]) sage: L.braid() s^2 @@ -649,6 +662,7 @@ def braid(self, remove_loops=False): TESTS:: + sage: # needs sage.groups sage: L = Link([]) sage: L.braid() 1 @@ -658,6 +672,7 @@ def braid(self, remove_loops=False): Check that :issue:`25050` is solved:: + sage: # needs sage.groups sage: A = Link([[[1, 2, -2, -1, -3, -4, 4, 3]], [1, 1, 1, 1]]) sage: A.braid() s0*s1*s2*s3 @@ -1168,13 +1183,13 @@ def _khovanov_homology_cached(self, height, ring=ZZ): EXAMPLES:: sage: K = Link([[[1, -2, 3, -1, 2, -3]],[-1, -1, -1]]) - sage: K._khovanov_homology_cached(-5) + sage: K._khovanov_homology_cached(-5) # needs sage.modules ((-3, 0), (-2, Z), (-1, 0), (0, 0)) The figure eight knot:: sage: L = Link([[1, 6, 2, 7], [5, 2, 6, 3], [3, 1, 4, 8], [7, 5, 8, 4]]) - sage: L._khovanov_homology_cached(-1) + sage: L._khovanov_homology_cached(-1) # needs sage.modules ((-2, 0), (-1, Z), (0, Z), (1, 0), (2, 0)) """ crossings = self.pd_code() @@ -1233,7 +1248,7 @@ def khovanov_homology(self, ring=ZZ, height=None, degree=None): EXAMPLES:: sage: K = Link([[[1, -2, 3, -1, 2, -3]],[-1, -1, -1]]) - sage: K.khovanov_homology() + sage: K.khovanov_homology() # needs sage.modules {-9: {-3: Z}, -7: {-3: 0, -2: C2}, -5: {-3: 0, -2: Z, -1: 0, 0: 0}, @@ -1243,21 +1258,23 @@ def khovanov_homology(self, ring=ZZ, height=None, degree=None): The figure eight knot:: sage: L = Link([[1, 6, 2, 7], [5, 2, 6, 3], [3, 1, 4, 8], [7, 5, 8, 4]]) - sage: L.khovanov_homology(height=-1) + sage: L.khovanov_homology(height=-1) # needs sage.modules {-1: {-2: 0, -1: Z, 0: Z, 1: 0, 2: 0}} The Hopf link:: + sage: # needs sage.groups sage.modules sage: B = BraidGroup(2) sage: b = B([1, 1]) sage: K = Link(b) - sage: K.khovanov_homology(degree = 2) + sage: K.khovanov_homology(degree=2) {2: {2: 0}, 4: {2: Z}, 6: {2: Z}} TESTS: Check that :issue:`31001` is fixed:: + sage: # needs sage.modules sage: L = Link([]) sage: L.khovanov_homology() {-1: {0: Z}, 1: {0: Z}} @@ -1332,12 +1349,15 @@ def oriented_gauss_code(self): EXAMPLES:: - sage: L = Link([[1, 10, 2, 11], [6, 3, 7, 2], [3, 9, 4, 12], [9, 6, 10, 5], [8, 4, 5, 1], [11, 7, 12, 8]]) + sage: L = Link([[1, 10, 2, 11], [6, 3, 7, 2], [3, 9, 4, 12], + ....: [9, 6, 10, 5], [8, 4, 5, 1], [11, 7, 12, 8]]) sage: L.oriented_gauss_code() [[[-1, 2, -3, 5], [4, -2, 6, -5], [-4, 1, -6, 3]], [-1, 1, 1, 1, -1, -1]] sage: L = Link([[1, 3, 2, 4], [6, 2, 3, 1], [7, 5, 8, 4], [5, 7, 6, 8]]) sage: L.oriented_gauss_code() [[[-1, 2], [-3, 4], [1, 3, -4, -2]], [-1, -1, 1, 1]] + + sage: # needs sage.groups sage: B = BraidGroup(8) sage: b = B([1, 1, 1, 1, 1]) sage: L = Link(b) @@ -1349,6 +1369,8 @@ def oriented_gauss_code(self): sage: L = Link([]) sage: L.oriented_gauss_code() [[], []] + + sage: # needs sage.groups sage: L = Link(BraidGroup(2).one()) sage: L.oriented_gauss_code() [[], []] @@ -1415,6 +1437,8 @@ def pd_code(self): sage: L = Link([[[1, -2, 3, -4, 2, -1, 4, -3]], [1, 1, -1, -1]]) sage: L.pd_code() [[6, 2, 7, 1], [2, 6, 3, 5], [8, 3, 1, 4], [4, 7, 5, 8]] + + sage: # needs sage.groups sage: B = BraidGroup(2) sage: b = B([1, 1, 1, 1, 1]) sage: L = Link(b) @@ -1432,6 +1456,8 @@ def pd_code(self): sage: L = Link([[], []]) sage: L.pd_code() [] + + sage: # needs sage.groups sage: L = Link(BraidGroup(2).one()) sage: L.pd_code() [] @@ -1520,10 +1546,13 @@ def gauss_code(self): sage: L = Link([[1, 4, 2, 3], [4, 1, 3, 2]]) sage: L.gauss_code() [[-1, 2], [1, -2]] + + sage: # needs sage.groups sage: B = BraidGroup(8) sage: L = Link(B([1, -2, 1, -2, -2])) sage: L.gauss_code() [[-1, 3, -4, 5], [1, -2, 4, -5, 2, -3]] + sage: L = Link([[[-1, 2], [-3, 4], [1, 3, -4, -2]], [-1, -1, 1, 1]]) sage: L.gauss_code() [[-1, 2], [-3, 4], [1, 3, -4, -2]] @@ -1547,9 +1576,12 @@ def dowker_notation(self): EXAMPLES:: - sage: L = Link([[[-1, 2, -3, 4, 5, 1, -2, 6, 7, 3, -4, -7, -6,-5]], [-1, -1, -1, -1, 1, -1, 1]]) + sage: L = Link([[[-1, 2, -3, 4, 5, 1, -2, 6, 7, 3, -4, -7, -6,-5]], + ....: [-1, -1, -1, -1, 1, -1, 1]]) sage: L.dowker_notation() [(1, 6), (7, 2), (3, 10), (11, 4), (14, 5), (13, 8), (12, 9)] + + sage: # needs sage.groups sage: B = BraidGroup(4) sage: L = Link(B([1, 2, 1, 2])) sage: L.dowker_notation() @@ -1580,6 +1612,7 @@ def _braid_word_components(self): EXAMPLES:: + sage: # needs sage.groups sage: B = BraidGroup(4) sage: L = Link(B([-1, 3, 1, 3])) sage: L._braid_word_components() @@ -1622,6 +1655,7 @@ def _braid_word_components_vector(self): EXAMPLES:: + sage: # needs sage.groups sage: B = BraidGroup(4) sage: L = Link(B([-1, 3, 1, 3])) sage: L._braid_word_components_vector() @@ -1655,6 +1689,7 @@ def _homology_generators(self): EXAMPLES:: + sage: # needs sage.groups sage.modules sage: B = BraidGroup(4) sage: L = Link(B([-1, 3, 1, 3])) sage: L._homology_generators() @@ -1694,6 +1729,7 @@ def seifert_matrix(self): EXAMPLES:: + sage: # needs sage.groups sage.modules sage: B = BraidGroup(4) sage: L = Link(B([-1, 3, 1, 3])) sage: L.seifert_matrix() @@ -1743,6 +1779,7 @@ def number_of_components(self): EXAMPLES:: + sage: # needs sage.groups sage: B = BraidGroup(4) sage: L = Link(B([-1, 3, 1, 3])) sage: L.number_of_components() @@ -1776,6 +1813,7 @@ def is_knot(self): EXAMPLES:: + sage: # needs sage.groups sage: B = BraidGroup(4) sage: L = Link(B([1, 3, 1, -3])) sage: L.is_knot() @@ -1793,6 +1831,7 @@ def genus(self): EXAMPLES:: + sage: # needs sage.groups sage: B = BraidGroup(4) sage: L = Link(B([-1, 3, 1, 3])) sage: L.genus() @@ -1856,6 +1895,7 @@ def signature(self): EXAMPLES:: + sage: # needs sage.groups sage.modules sage: B = BraidGroup(4) sage: L = Link(B([-1, 3, 1, 3])) sage: L.signature() @@ -1898,6 +1938,7 @@ def omega_signature(self, omega): EXAMPLES:: + sage: # needs sage.groups sage.modules sage.rings.number_field sage: B = BraidGroup(4) sage: K = Knot(B([1,1,1,2,-1,2,-3,2,-3])) sage: omega = QQbar.zeta(3) @@ -1923,6 +1964,7 @@ def alexander_polynomial(self, var='t'): We begin by computing the Alexander polynomial for the figure-eight knot:: + sage: # needs sage.groups sage.modules sage: B = BraidGroup(3) sage: L = Link(B([1, -2, 1, -2])) sage: L.alexander_polynomial() @@ -1933,11 +1975,12 @@ def alexander_polynomial(self, var='t'): sage: L = Link([[3,1,2,4],[8,9,1,7],[5,6,7,3],[4,18,6,5], ....: [17,19,8,18],[9,10,11,14],[10,12,13,11], ....: [12,19,15,13],[20,16,14,15],[16,20,17,2]]) - sage: L.alexander_polynomial() + sage: L.alexander_polynomial() # needs sage.groups sage.modules 1 Some additional examples:: + sage: # needs sage.groups sage.modules sage: B = BraidGroup(2) sage: L = Link(B([1])) sage: L.alexander_polynomial() @@ -1953,6 +1996,7 @@ def alexander_polynomial(self, var='t'): When the Seifert surface is disconnected, the Alexander polynomial is defined to be `0`:: + sage: # needs sage.groups sage.modules sage: B = BraidGroup(4) sage: L = Link(B([1,3])) sage: L.alexander_polynomial() @@ -1960,6 +2004,7 @@ def alexander_polynomial(self, var='t'): TESTS:: + sage: # needs sage.groups sage.modules sage: B = BraidGroup(4) sage: L = Link(B([-1, 3, 1, 3])) sage: L.alexander_polynomial() @@ -1997,6 +2042,7 @@ def conway_polynomial(self): EXAMPLES:: + sage: # needs sage.groups sage.modules sage: B = BraidGroup(3) sage: L = Link(B([1, -2, 1, -2])) sage: L.conway_polynomial() @@ -2057,25 +2103,26 @@ def khovanov_polynomial(self, var1='q', var2='t', base_ring=ZZ): EXAMPLES:: sage: K = Link([[[1, -2, 3, -1, 2, -3]],[-1, -1, -1]]) - sage: K.khovanov_polynomial() + sage: K.khovanov_polynomial() # needs sage.modules q^-1 + q^-3 + q^-5*t^-2 + q^-9*t^-3 - sage: K.khovanov_polynomial(base_ring=GF(2)) + sage: K.khovanov_polynomial(base_ring=GF(2)) # needs sage.modules q^-1 + q^-3 + q^-5*t^-2 + q^-7*t^-2 + q^-9*t^-3 The figure eight knot:: sage: L = Link([[1, 6, 2, 7], [5, 2, 6, 3], [3, 1, 4, 8], [7, 5, 8, 4]]) - sage: L.khovanov_polynomial(var1='p') + sage: L.khovanov_polynomial(var1='p') # needs sage.modules p^5*t^2 + p*t + p + p^-1 + p^-1*t^-1 + p^-5*t^-2 - sage: L.khovanov_polynomial(var1='p', var2='s', base_ring=GF(4)) + sage: L.khovanov_polynomial(var1='p', var2='s', base_ring=GF(4)) # needs sage.modules sage.rings.finite_rings p^5*s^2 + p^3*s^2 + p*s + p + p^-1 + p^-1*s^-1 + p^-3*s^-1 + p^-5*s^-2 The Hopf link:: + sage: # needs sage.groups sage: B = BraidGroup(2) sage: b = B([1, 1]) sage: K = Link(b) - sage: K.khovanov_polynomial() + sage: K.khovanov_polynomial() # needs sage.modules q^6*t^2 + q^4*t^2 + q^2 + 1 .. SEEALSO:: :meth:`khovanov_homology` @@ -2100,6 +2147,7 @@ def determinant(self): EXAMPLES:: + sage: # needs sage.groups sage.modules sage: B = BraidGroup(4) sage: L = Link(B([-1, 2, 1, 2])) sage: L.determinant() @@ -2117,6 +2165,7 @@ def determinant(self): TESTS:: + sage: # needs sage.groups sage.modules sage: B = BraidGroup(3) sage: Link(B([1, 2, 1, -2, -1])).determinant() 0 @@ -2152,6 +2201,7 @@ def is_alternating(self): EXAMPLES:: + sage: # needs sage.groups sage: B = BraidGroup(4) sage: L = Link(B([-1, -1, -1, -1])) sage: L.is_alternating() @@ -2177,6 +2227,7 @@ def is_alternating(self): sage: K5_2.is_alternating() True + sage: # needs sage.groups sage: K5_2b = Link(K5_2.braid()) sage: K5_2b.is_alternating() False @@ -2205,10 +2256,12 @@ def orientation(self): EXAMPLES:: - sage: L = Link([[1, 2, 5, 4], [3, 7, 6, 5], [4, 6, 9, 8], [7, 11, 10, 9], [8, 10, 13, 1], [11, 3, 2, 13]]) + sage: L = Link([[1, 2, 5, 4], [3, 7, 6, 5], [4, 6, 9, 8], [7, 11, 10, 9], + ....: [8, 10, 13, 1], [11, 3, 2, 13]]) sage: L.orientation() [-1, 1, -1, 1, -1, 1] - sage: L = Link([[1, 6, 2, 7], [7, 2, 8, 3], [3, 10, 4, 11], [11, 4, 12, 5], [14, 6, 1, 5], [13, 8, 14, 9], [12, 10, 13, 9]]) + sage: L = Link([[1, 6, 2, 7], [7, 2, 8, 3], [3, 10, 4, 11], [11, 4, 12, 5], + ....: [14, 6, 1, 5], [13, 8, 14, 9], [12, 10, 13, 9]]) sage: L.orientation() [-1, -1, -1, -1, 1, -1, 1] sage: L = Link([[1, 3, 3, 2], [2, 5, 5, 4], [4, 7, 7, 1]]) @@ -2243,18 +2296,24 @@ def seifert_circles(self): sage: L = Link([[[1, -2, 3, -4, 2, -1, 4, -3]], [1, 1, -1, -1]]) sage: L.seifert_circles() [[1, 7, 5, 3], [2, 6], [4, 8]] - sage: L = Link([[[-1, 2, 3, -4, 5, -6, 7, 8, -2, -5, 6, 1, -8, -3, 4, -7]], [-1, -1, -1, -1, 1, 1, -1, 1]]) + sage: L = Link([[[-1, 2, 3, -4, 5, -6, 7, 8, -2, -5, 6, 1, -8, -3, 4, -7]], + ....: [-1, -1, -1, -1, 1, 1, -1, 1]]) sage: L.seifert_circles() [[1, 13, 9, 3, 15, 5, 11, 7], [2, 10, 6, 12], [4, 16, 8, 14]] - sage: L = Link([[[-1, 2, -3, 4, 5, 1, -2, 6, 7, 3, -4, -7, -6, -5]], [-1, -1, -1, -1, 1, -1, 1]]) + sage: L = Link([[[-1, 2, -3, 4, 5, 1, -2, 6, 7, 3, -4, -7, -6, -5]], + ....: [-1, -1, -1, -1, 1, -1, 1]]) sage: L.seifert_circles() [[1, 7, 3, 11, 5], [2, 8, 14, 6], [4, 12, 10], [9, 13]] - sage: L = Link([[1, 7, 2, 6], [7, 3, 8, 2], [3, 11, 4, 10], [11, 5, 12, 4], [14, 5, 1, 6], [13, 9, 14, 8], [12, 9, 13, 10]]) + sage: L = Link([[1, 7, 2, 6], [7, 3, 8, 2], [3, 11, 4, 10], [11, 5, 12, 4], + ....: [14, 5, 1, 6], [13, 9, 14, 8], [12, 9, 13, 10]]) sage: L.seifert_circles() [[1, 7, 3, 11, 5], [2, 8, 14, 6], [4, 12, 10], [9, 13]] - sage: L = Link([[[-1, 2, -3, 5], [4, -2, 6, -5], [-4, 1, -6, 3]], [-1, 1, 1, 1, -1, -1]]) + sage: L = Link([[[-1, 2, -3, 5], [4, -2, 6, -5], [-4, 1, -6, 3]], + ....: [-1, 1, 1, 1, -1, -1]]) sage: L.seifert_circles() [[1, 11, 8], [2, 7, 12, 4, 5, 10], [3, 9, 6]] + + sage: # needs sage.groups sage: B = BraidGroup(2) sage: L = Link(B([1, 1, 1])) sage: L.seifert_circles() @@ -2310,22 +2369,30 @@ def regions(self): EXAMPLES:: - sage: L = Link([[[-1, +2, -3, 4, +5, +1, -2, +6, +7, 3, -4, -7, -6,-5]],[-1, -1, -1, -1, 1, -1, 1]]) + sage: L = Link([[[-1, +2, -3, 4, +5, +1, -2, +6, +7, 3, -4, -7, -6,-5]], + ....: [-1, -1, -1, -1, 1, -1, 1]]) sage: L.regions() - [[14, -5, 12, -9], [13, 9], [11, 5, 1, 7, 3], [10, -3, 8, -13], [6, -1], [4, -11], [2, -7], [-2, -6, -14, -8], [-4, -10, -12]] + [[14, -5, 12, -9], [13, 9], [11, 5, 1, 7, 3], [10, -3, 8, -13], + [6, -1], [4, -11], [2, -7], [-2, -6, -14, -8], [-4, -10, -12]] sage: L = Link([[[1, -2, 3, -4, 2, -1, 4, -3]],[1, 1, -1, -1]]) sage: L.regions() [[8, 4], [7, -4, 1], [6, -1, -3], [5, 3, -8], [2, -5, -7], [-2, -6]] - sage: L = Link([[[-1, +2, 3, -4, 5, -6, 7, 8, -2, -5, +6, +1, -8, -3, 4, -7]],[-1, -1, -1, -1, 1, 1, -1, 1]]) + sage: L = Link([[[-1, +2, 3, -4, 5, -6, 7, 8, -2, -5, +6, +1, -8, -3, 4, -7]], + ....: [-1, -1, -1, -1, 1, 1, -1, 1]]) sage: L.regions() - [[16, 8, 14, 4], [15, -4], [13, -8, 1], [12, -1, -7], [11, 7, -16, 5], [10, -5, -15, -3], [9, 3, -14], [6, -11], [2, -9, -13], [-2, -12, -6, -10]] + [[16, 8, 14, 4], [15, -4], [13, -8, 1], [12, -1, -7], [11, 7, -16, 5], + [10, -5, -15, -3], [9, 3, -14], [6, -11], [2, -9, -13], [-2, -12, -6, -10]] + + sage: # needs sage.groups sage: B = BraidGroup(2) sage: L = Link(B([-1, -1, -1])) sage: L.regions() [[6, -5], [5, 1, 3], [4, -3], [2, -1], [-2, -6, -4]] - sage: L = Link([[[1, -2, 3, -4], [-1, 5, -3, 2, -5, 4]], [-1, 1, 1, -1, -1]]) + sage: L = Link([[[1, -2, 3, -4], [-1, 5, -3, 2, -5, 4]], + ....: [-1, 1, 1, -1, -1]]) sage: L.regions() - [[10, -4, -7], [9, 7, -3], [8, 3], [6, -9, -2], [5, 2, -8, 4], [1, -5], [-1, -10, -6]] + [[10, -4, -7], [9, 7, -3], [8, 3], [6, -9, -2], [5, 2, -8, 4], + [1, -5], [-1, -10, -6]] sage: L = Link([[1, 3, 3, 2], [2, 4, 4, 5], [5, 6, 6, 7], [7, 8, 8, 1]]) sage: L.regions() [[-3], [-4], [-6], [-8], [7, 1, 2, 5], [-1, 8, -7, 6, -5, 4, -2, 3]] @@ -2338,6 +2405,7 @@ def regions(self): TESTS:: + sage: # needs sage.groups sage: B = BraidGroup(6) sage: L = Link(B([1, 3, 5])) sage: L.regions() @@ -2449,6 +2517,7 @@ def mirror_image(self): EXAMPLES:: + sage: # needs sage.groups sage: g = BraidGroup(2).gen(0) sage: K = Link(g^3) sage: K2 = K.mirror_image(); K2 @@ -2543,33 +2612,34 @@ def reverse(self): sage: K3 = Knot([[5, 2, 4, 1], [3, 6, 2, 5], [1, 4, 6, 3]]) sage: K3r = K3.reverse(); K3r.pd_code() [[4, 1, 5, 2], [2, 5, 3, 6], [6, 3, 1, 4]] - sage: K3 == K3r + sage: K3 == K3r # needs sage.groups True a non reversable knot:: - sage: K8_17 = Knot([[6, 1, 7, 2], [14, 7, 15, 8], [8, 4, 9, 3], - ....: [2, 14, 3, 13], [12, 6, 13, 5], [4, 10, 5, 9], - ....: [16, 11, 1, 12], [10, 15, 11, 16]]) - sage: K8_17r = K8_17.reverse() - sage: b = K8_17.braid(); b - s0^2*s1^-1*(s1^-1*s0)^2*s1^-1 - sage: br = K8_17r.braid(); br - s0^-1*s1*s0^-2*s1^2*s0^-1*s1 - sage: b.is_conjugated(br) - False - sage: b == br.reverse() - False - sage: b.is_conjugated(br.reverse()) - True - sage: K8_17b = Link(b) - sage: K8_17br = K8_17b.reverse() - sage: bbr = K8_17br.braid(); bbr - (s1^-1*s0)^2*s1^-2*s0^2 - sage: br == bbr - False - sage: br.is_conjugated(bbr) - True + sage: # needs sage.groups + sage: K8_17 = Knot([[6, 1, 7, 2], [14, 7, 15, 8], [8, 4, 9, 3], + ....: [2, 14, 3, 13], [12, 6, 13, 5], [4, 10, 5, 9], + ....: [16, 11, 1, 12], [10, 15, 11, 16]]) + sage: K8_17r = K8_17.reverse() + sage: b = K8_17.braid(); b + s0^2*s1^-1*(s1^-1*s0)^2*s1^-1 + sage: br = K8_17r.braid(); br + s0^-1*s1*s0^-2*s1^2*s0^-1*s1 + sage: b.is_conjugated(br) + False + sage: b == br.reverse() + False + sage: b.is_conjugated(br.reverse()) + True + sage: K8_17b = Link(b) + sage: K8_17br = K8_17b.reverse() + sage: bbr = K8_17br.braid(); bbr + (s1^-1*s0)^2*s1^-2*s0^2 + sage: br == bbr + False + sage: br.is_conjugated(bbr) + True """ if self._reverse: return self._reverse @@ -2665,6 +2735,7 @@ def jones_polynomial(self, variab=None, skein_normalization=False, algorithm='jo The unknot:: + sage: # needs sage.groups sage: B = BraidGroup(9) sage: b = B([1, 2, 3, 4, 5, 6, 7, 8]) sage: Link(b).jones_polynomial() @@ -2675,7 +2746,7 @@ def jones_polynomial(self, variab=None, skein_normalization=False, algorithm='jo sage: L = Link([[3,1,2,4],[8,9,1,7],[5,6,7,3],[4,18,6,5], ....: [17,19,8,18],[9,10,11,14],[10,12,13,11], ....: [12,19,15,13],[20,16,14,15],[16,20,17,2]]) - sage: L.jones_polynomial() + sage: L.jones_polynomial() # needs sage.symbolic 1 The Ochiai unknot:: @@ -2683,25 +2754,28 @@ def jones_polynomial(self, variab=None, skein_normalization=False, algorithm='jo sage: L = Link([[[1,-2,-3,-8,-12,13,-14,15,-7,-1,2,-4,10,11,-13,12, ....: -11,-16,4,3,-5,6,-9,7,-15,14,16,-10,8,9,-6,5]], ....: [-1,-1,1,1,1,1,-1,1,1,-1,1,-1,-1,-1,-1,-1]]) - sage: L.jones_polynomial() # long time + sage: L.jones_polynomial() # long time # needs sage.symbolic 1 Two unlinked unknots:: + sage: # needs sage.groups sage: B = BraidGroup(4) sage: b = B([1, 3]) - sage: Link(b).jones_polynomial() + sage: Link(b).jones_polynomial() # needs sage.symbolic -sqrt(t) - 1/sqrt(t) The Hopf link:: + sage: # needs sage.groups sage: B = BraidGroup(2) sage: b = B([-1,-1]) - sage: Link(b).jones_polynomial() + sage: Link(b).jones_polynomial() # needs sage.symbolic -1/sqrt(t) - 1/t^(5/2) Different representations of the trefoil and one of its mirror:: + sage: # needs sage.groups sage: B = BraidGroup(2) sage: b = B([-1, -1, -1]) sage: Link(b).jones_polynomial(skein_normalization=True) @@ -2723,15 +2797,17 @@ def jones_polynomial(self, variab=None, skein_normalization=False, algorithm='jo `K11n42` (the mirror of the "Kinoshita-Terasaka" knot) and `K11n34` (the mirror of the "Conway" knot) in [KnotAtlas]_:: + sage: # needs sage.groups sage: B = BraidGroup(4) sage: K11n42 = Link(B([1, -2, 3, -2, 3, -2, -2, -1, 2, -3, -3, 2, 2])) sage: K11n34 = Link(B([1, 1, 2, -3, 2, -3, 1, -2, -2, -3, -3])) - sage: bool(K11n42.jones_polynomial() == K11n34.jones_polynomial()) + sage: bool(K11n42.jones_polynomial() == K11n34.jones_polynomial()) # needs sage.symbolic True The two algorithms for computation give the same result when the trace closure of the braid representation is the link itself:: + sage: # needs sage.symbolic sage: L = Link([[[-1, 2, -3, 4, 5, 1, -2, 6, 7, 3, -4, -7, -6, -5]], ....: [-1, -1, -1, -1, 1, -1, 1]]) sage: jonesrep = L.jones_polynomial(algorithm='jonesrep') @@ -2743,6 +2819,7 @@ def jones_polynomial(self, variab=None, skein_normalization=False, algorithm='jo braid is not necessarily the link itself, this is only true up to a power of the Jones polynomial of the unknot:: + sage: # needs sage.groups sage: B = BraidGroup(3) sage: b = B([1]) sage: L = Link(b) @@ -2750,17 +2827,17 @@ def jones_polynomial(self, variab=None, skein_normalization=False, algorithm='jo 2 sage: L.number_of_components() 1 - sage: b.jones_polynomial() + sage: b.jones_polynomial() # needs sage.symbolic -sqrt(t) - 1/sqrt(t) - sage: L.jones_polynomial() + sage: L.jones_polynomial() # needs sage.symbolic 1 - sage: L.jones_polynomial(algorithm='statesum') + sage: L.jones_polynomial(algorithm='statesum') # needs sage.symbolic 1 TESTS:: sage: L = Link([]) - sage: L.jones_polynomial(algorithm='statesum') + sage: L.jones_polynomial(algorithm='statesum') # needs sage.symbolic 1 sage: L.jones_polynomial(algorithm='other') @@ -2770,7 +2847,7 @@ def jones_polynomial(self, variab=None, skein_normalization=False, algorithm='jo Check that :issue:`31001` is fixed:: - sage: L.jones_polynomial() + sage: L.jones_polynomial() # needs sage.groups 1 """ if algorithm == 'statesum': @@ -2947,15 +3024,16 @@ def homfly_polynomial(self, var1=None, var2=None, normalization='lm'): We give some examples:: + sage: # needs sage.groups sage: g = BraidGroup(2).gen(0) sage: K = Knot(g^5) - sage: K.homfly_polynomial() + sage: K.homfly_polynomial() # needs sage.libs.homfly L^-4*M^4 - 4*L^-4*M^2 + 3*L^-4 - L^-6*M^2 + 2*L^-6 The Hopf link:: sage: L = Link([[1,4,2,3],[4,1,3,2]]) - sage: L.homfly_polynomial('x', 'y') + sage: L.homfly_polynomial('x', 'y') # needs sage.libs.homfly -x^-1*y + x^-1*y^-1 + x^-3*y^-1 Another version of the Hopf link where the orientation @@ -2963,18 +3041,18 @@ def homfly_polynomial(self, var1=None, var2=None, normalization='lm'): and `y \mapsto M`:: sage: L = Link([[1,3,2,4], [4,2,3,1]]) - sage: L.homfly_polynomial() + sage: L.homfly_polynomial() # needs sage.libs.homfly L^3*M^-1 - L*M + L*M^-1 sage: L = Link([[1,3,2,4], [4,2,3,1]]) - sage: L.homfly_polynomial(normalization='az') + sage: L.homfly_polynomial(normalization='az') # needs sage.libs.homfly a^3*z^-1 - a*z - a*z^-1 The figure-eight knot:: sage: L = Link([[2,5,4,1], [5,3,7,6], [6,9,1,4], [9,7,3,2]]) - sage: L.homfly_polynomial() + sage: L.homfly_polynomial() # needs sage.libs.homfly -L^2 + M^2 - 1 - L^-2 - sage: L.homfly_polynomial('a', 'z', 'az') + sage: L.homfly_polynomial('a', 'z', 'az') # needs sage.libs.homfly a^2 - z^2 - 1 + a^-2 The "monster" unknot:: @@ -2982,18 +3060,19 @@ def homfly_polynomial(self, var1=None, var2=None, normalization='lm'): sage: L = Link([[3,1,2,4], [8,9,1,7], [5,6,7,3], [4,18,6,5], ....: [17,19,8,18], [9,10,11,14], [10,12,13,11], ....: [12,19,15,13], [20,16,14,15], [16,20,17,2]]) - sage: L.homfly_polynomial() + sage: L.homfly_polynomial() # needs sage.libs.homfly 1 Comparison with KnotInfo:: sage: KI, m = K.get_knotinfo(); KI, m (, ) - sage: K.homfly_polynomial(normalization='vz') == KI.homfly_polynomial() + sage: K.homfly_polynomial(normalization='vz') == KI.homfly_polynomial() # needs sage.libs.homfly True The knot `9_6`:: + sage: # needs sage.groups sage.libs.homfly sage: B = BraidGroup(3) sage: K = Knot(B([-1,-1,-1,-1,-1,-1,-2,1,-2,-2])) sage: K.homfly_polynomial() @@ -3007,6 +3086,7 @@ def homfly_polynomial(self, var1=None, var2=None, normalization='lm'): This works with isolated components:: + sage: # needs sage.libs.homfly sage: L = Link([[[1, -1], [2, -2]], [1, 1]]) sage: L2 = Link([[1, 4, 2, 3], [2, 4, 1, 3]]) sage: L2.homfly_polynomial() @@ -3025,7 +3105,7 @@ def homfly_polynomial(self, var1=None, var2=None, normalization='lm'): Check that :issue:`30346` is fixed:: sage: L = Link([]) - sage: L.homfly_polynomial() + sage: L.homfly_polynomial() # needs sage.libs.homfly 1 REFERENCES: @@ -3110,7 +3190,7 @@ def links_gould_polynomial(self, varnames='t0, t1'): EXAMPLES:: sage: Hopf = Link([[1, 3, 2, 4], [4, 2, 3, 1]]) - sage: Hopf.links_gould_polynomial() + sage: Hopf.links_gould_polynomial() # needs sage.groups -1 + t1^-1 + t0^-1 - t0^-1*t1^-1 """ return self.braid().links_gould_polynomial(varnames=varnames) @@ -3133,6 +3213,7 @@ def _coloring_matrix(self, n=None): EXAMPLES:: + sage: # needs sage.libs.pari sage.modules sage: K = Link([[[1, -2, 3, -1, 2, -3]], [1, 1, 1]]) sage: K._coloring_matrix(3) [2 2 2] @@ -3188,13 +3269,13 @@ def is_colorable(self, n=None): We show that the trefoil knot is 3-colorable:: sage: K = Link([[[1, -2, 3, -1, 2, -3]], [1, 1, 1]]) - sage: K.is_colorable(3) + sage: K.is_colorable(3) # needs sage.libs.pari sage.modules True But the figure eight knot is not:: sage: K8 = Link([[[1, -2, 4, -3, 2, -1, 3, -4]], [1, 1, -1, -1]]) - sage: K8.is_colorable(3) + sage: K8.is_colorable(3) # needs sage.libs.pari sage.modules False But it is colorable with respect to the value of its determinant:: @@ -3246,7 +3327,7 @@ def colorings(self, n=None): EXAMPLES:: sage: K = Link([[[1, -2, 3, -1, 2, -3]], [1, 1, 1]]) - sage: K.colorings(3) + sage: K.colorings(3) # needs sage.libs.pari sage.modules [{(1, 2): 0, (3, 4): 1, (5, 6): 2}, {(1, 2): 0, (3, 4): 2, (5, 6): 1}, {(1, 2): 1, (3, 4): 0, (5, 6): 2}, @@ -3406,7 +3487,7 @@ def plot(self, gap=0.1, component_gap=0.5, solver=None, We construct the simplest version of the unknot:: sage: L = Link([[2, 1, 1, 2]]) - sage: L.plot() + sage: L.plot() # needs sage.plot Graphics object consisting of ... graphics primitives .. PLOT:: @@ -3419,7 +3500,7 @@ def plot(self, gap=0.1, component_gap=0.5, solver=None, We construct a more interesting example of the unknot:: sage: L = Link([[2, 1, 4, 5], [3, 5, 6, 7], [4, 1, 9, 6], [9, 2, 3, 7]]) - sage: L.plot() + sage: L.plot() # needs sage.plot Graphics object consisting of ... graphics primitives .. PLOT:: @@ -3430,10 +3511,10 @@ def plot(self, gap=0.1, component_gap=0.5, solver=None, The "monster" unknot:: - sage: L = Link([[3,1,2,4],[8,9,1,7],[5,6,7,3],[4,18,6,5], - ....: [17,19,8,18],[9,10,11,14],[10,12,13,11], - ....: [12,19,15,13],[20,16,14,15],[16,20,17,2]]) - sage: L.plot() + sage: L = Link([[3,1,2,4], [8,9,1,7], [5,6,7,3], [4,18,6,5], + ....: [17,19,8,18], [9,10,11,14], [10,12,13,11], + ....: [12,19,15,13], [20,16,14,15], [16,20,17,2]]) + sage: L.plot() # needs sage.plot Graphics object consisting of ... graphics primitives .. PLOT:: @@ -3449,7 +3530,7 @@ def plot(self, gap=0.1, component_gap=0.5, solver=None, sage: L = Link([[[1,-2,-3,-8,-12,13,-14,15,-7,-1,2,-4,10,11,-13,12, ....: -11,-16,4,3,-5,6,-9,7,-15,14,16,-10,8,9,-6,5]], ....: [-1,-1,1,1,1,1,-1,1,1,-1,1,-1,-1,-1,-1,-1]]) - sage: L.plot() + sage: L.plot() # needs sage.plot Graphics object consisting of ... graphics primitives .. PLOT:: @@ -3463,7 +3544,7 @@ def plot(self, gap=0.1, component_gap=0.5, solver=None, One of the representations of the trefoil knot:: sage: L = Link([[1, 5, 2, 4], [5, 3, 6, 2], [3, 1, 4, 6]]) - sage: L.plot() + sage: L.plot() # needs sage.plot Graphics object consisting of 14 graphics primitives .. PLOT:: @@ -3475,7 +3556,7 @@ def plot(self, gap=0.1, component_gap=0.5, solver=None, The figure-eight knot:: sage: L = Link([[2, 1, 4, 5], [5, 6, 7, 3], [6, 4, 1, 9], [9, 2, 3, 7]]) - sage: L.plot() + sage: L.plot() # needs sage.plot Graphics object consisting of ... graphics primitives .. PLOT:: @@ -3489,7 +3570,7 @@ def plot(self, gap=0.1, component_gap=0.5, solver=None, sage: L = Link([[4,2,5,1], [10,3,11,4], [5,16,6,17], [7,12,8,13], ....: [18,9,19,10], [2,11,3,12], [13,20,14,21], [15,6,16,7], ....: [22,18,1,17], [8,19,9,20], [21,14,22,15]]) - sage: L.plot() + sage: L.plot() # needs sage.plot Graphics object consisting of ... graphics primitives .. PLOT:: @@ -3503,7 +3584,7 @@ def plot(self, gap=0.1, component_gap=0.5, solver=None, One of the representations of the Hopf link:: sage: L = Link([[1, 4, 2, 3], [4, 1, 3, 2]]) - sage: L.plot() + sage: L.plot() # needs sage.plot Graphics object consisting of ... graphics primitives .. PLOT:: @@ -3514,8 +3595,9 @@ def plot(self, gap=0.1, component_gap=0.5, solver=None, Plotting links with multiple isolated components:: - sage: L = Link([[[-1, 2, -3, 1, -2, 3], [4, -5, 6, -4, 5, -6]], [1, 1, 1, 1, 1, 1]]) - sage: L.plot() + sage: L = Link([[[-1, 2, -3, 1, -2, 3], [4, -5, 6, -4, 5, -6]], + ....: [1, 1, 1, 1, 1, 1]]) + sage: L.plot() # needs sage.plot Graphics object consisting of ... graphics primitives .. PLOT:: @@ -3527,10 +3609,11 @@ def plot(self, gap=0.1, component_gap=0.5, solver=None, If a coloring is passed, the different arcs are plotted with the corresponding colors (see :meth:`colorings`):: + sage: # needs sage.groups sage: B = BraidGroup(4) sage: b = B([1,2,3,1,2,-1,-3,2,3]) sage: L = Link(b) - sage: L.plot(color=L.colorings()[0]) + sage: L.plot(color=L.colorings()[0]) # needs sage.plot Graphics object consisting of ... graphics primitives .. PLOT:: @@ -3546,13 +3629,13 @@ def plot(self, gap=0.1, component_gap=0.5, solver=None, Check that :issue:`20315` is fixed:: sage: L = Link([[2,1,4,5], [5,6,7,3], [6,4,1,9], [9,2,3,7]]) - sage: L.plot(solver='GLPK') + sage: L.plot(solver='GLPK') # needs sage.plot Graphics object consisting of ... graphics primitives - sage: L.plot(solver='Coin') # optional - sage_numerical_backends_coin + sage: L.plot(solver='Coin') # optional - sage_numerical_backends_coin, needs sage.plot Graphics object consisting of ... graphics primitives - sage: L.plot(solver='CPLEX') # optional - CPLEX + sage: L.plot(solver='CPLEX') # optional - cplex # needs sage.plot Graphics object consisting of ... graphics primitives - sage: L.plot(solver='Gurobi') # optional - Gurobi + sage: L.plot(solver='Gurobi') # optional - gurobi # needs sage.plot Graphics object consisting of ... graphics primitives """ pd_code = self.pd_code() @@ -3884,6 +3967,7 @@ def _markov_move_cmp(self, braid): EXAMPLES:: + sage: # needs sage.groups sage: b = BraidGroup(4)((1, 2, -3, 2, 2, 2, 2, 2, 2, -1, 2, 3, 2)) sage: L = Link([[2, 5, 4, 1], [5, 7, 6, 4], [7, 9, 8, 6], [9, 11, 10, 8], ....: [11, 13, 12, 10], [13, 15, 14, 12], [15, 17, 16, 14], @@ -3949,7 +4033,7 @@ def _knotinfo_matching_list(self): sage: KnotInfo.L5a1_0.inject() Defining L5a1_0 - sage: ML = L5a1_0.link()._knotinfo_matching_list(); ML + sage: ML = L5a1_0.link()._knotinfo_matching_list(); ML # needs sage.libs.homfly ([, ], True) sage: ML == Link(L5a1_0.braid())._knotinfo_matching_list() True @@ -3959,7 +4043,7 @@ def _knotinfo_matching_list(self): sage: k4_1 = KnotInfo.K4_1.link() sage: k5_2 = KnotInfo.K5_2.link() sage: k = k4_1.connected_sum(k5_2) - sage: k._knotinfo_matching_list() # optional - database_knotinfo + sage: k._knotinfo_matching_list() # optional - database_knotinfo # needs sage.libs.homfly ([], False) """ @@ -4143,6 +4227,7 @@ def get_knotinfo(self, mirror_version=True, unique=True): cannot be identified. In addition non prime links or even links whose HOMFLY-PT polynomial is not irreducible cannot be identified:: + sage: # needs sage.groups sage: b, = BraidGroup(2).gens() sage: Link(b**13).get_knotinfo() # optional - database_knotinfo (, ) @@ -4151,9 +4236,10 @@ def get_knotinfo(self, mirror_version=True, unique=True): ... NotImplementedError: this link having more than 11 crossings cannot be determined - sage: Link([[1, 4, 2, 5], [3, 8, 4, 1], [5, 2, 6, 3], [6, 10, 7, 9], [10, 8, 9, 7]]) + sage: Link([[1, 4, 2, 5], [3, 8, 4, 1], [5, 2, 6, 3], + ....: [6, 10, 7, 9], [10, 8, 9, 7]]) Link with 2 components represented by 5 crossings - sage: _.get_knotinfo() + sage: _.get_knotinfo() # needs sage.libs.homfly Traceback (most recent call last): ... NotImplementedError: this (possibly non prime) link cannot be determined @@ -4200,7 +4286,8 @@ def get_knotinfo(self, mirror_version=True, unique=True): sage: l12.get_knotinfo() Traceback (most recent call last): ... - NotImplementedError: this link having more than 11 crossings cannot be uniquely determined + NotImplementedError: this link having more than 11 crossings + cannot be uniquely determined use keyword argument `unique` to obtain more details sage: l12.get_knotinfo(unique=False) [(, ), @@ -4216,6 +4303,7 @@ def get_knotinfo(self, mirror_version=True, unique=True): the same unoriented name (according to the note above) the option can be used to achieve more detailed information:: + sage: # needs sage.groups sage: L2a1 = Link(b**2) sage: L2a1.get_knotinfo() (Series of links L2a1, ) @@ -4490,11 +4578,11 @@ def is_isotopic(self, other): sage: l2 = Link([[1, 8, 2, 9], [9, 2, 10, 3], [3, 14, 4, 1], ....: [13, 4, 14, 5], [5, 12, 6, 13], [11, 6, 12, 7], ....: [7, 10, 8, 11]]) - sage: l1.is_isotopic(l2) + sage: l1.is_isotopic(l2) # needs sage.groups True sage: l3 = l2.mirror_image() - sage: l1.is_isotopic(l3) + sage: l1.is_isotopic(l3) # needs sage.groups False sage: # optional - database_knotinfo @@ -4504,13 +4592,13 @@ def is_isotopic(self, other): sage: L == L7a7(0) True sage: l = L.link() - sage: l.is_isotopic(L7a7(1).link()) + sage: l.is_isotopic(L7a7(1).link()) # needs sage.groups Traceback (most recent call last): ... NotImplementedError: comparison not possible! - sage: l.is_isotopic(L7a7(2).link()) + sage: l.is_isotopic(L7a7(2).link()) # needs sage.groups True - sage: l.is_isotopic(L7a7(3).link()) + sage: l.is_isotopic(L7a7(3).link()) # needs sage.groups False Using verbosity:: From 38b561667f4d7a7aede78f01b82276b63a388b17 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 30 May 2024 18:56:08 -0700 Subject: [PATCH 111/231] Add feature 'sage.libs.homfly' --- src/sage/features/sagemath.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/sage/features/sagemath.py b/src/sage/features/sagemath.py index fc54853bc9b..1e41ab758d9 100644 --- a/src/sage/features/sagemath.py +++ b/src/sage/features/sagemath.py @@ -538,6 +538,32 @@ def __init__(self): spkg='sagemath_ntl', type='standard') +class sage__libs__homfly(JoinFeature): + r""" + A :class:`sage.features.Feature` describing the presence of :mod:`sage.libs.homfly`. + + In addition to the modularization purposes that this tag serves, + it also provides attribution to the upstream project. + + TESTS:: + + sage: from sage.features.sagemath import sage__libs__homfly + sage: sage__libs__homfly().is_present() # needs sage.libs.homfly + FeatureTestResult('sage.libs.homfly', True) + """ + def __init__(self): + r""" + TESTS:: + + sage: from sage.features.sagemath import sage__libs__homfly + sage: isinstance(sage__libs__homfly(), sage__libs__homfly) + True + """ + JoinFeature.__init__(self, 'sage.libs.homfly', + [PythonModule('sage.libs.homfly')], + spkg='sagemath_homfly', type='standard') + + class sage__libs__pari(JoinFeature): r""" A :class:`~sage.features.Feature` describing the presence of :mod:`sage.libs.pari`. @@ -1130,6 +1156,7 @@ def all_features(): sage__libs__ecl(), sage__libs__flint(), sage__libs__gap(), + sage__libs__homfly(), sage__libs__linbox(), sage__libs__m4ri(), sage__libs__ntl(), From 0a333200428f9c906645cc6e6258a2413049f093 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 30 May 2024 23:17:35 -0700 Subject: [PATCH 112/231] src/sage/knots/link.py: Fix indent of doctest --- src/sage/knots/link.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/sage/knots/link.py b/src/sage/knots/link.py index 4a6bc009e3a..62731967f44 100644 --- a/src/sage/knots/link.py +++ b/src/sage/knots/link.py @@ -2609,11 +2609,11 @@ def reverse(self): EXAMPLES:: - sage: K3 = Knot([[5, 2, 4, 1], [3, 6, 2, 5], [1, 4, 6, 3]]) - sage: K3r = K3.reverse(); K3r.pd_code() - [[4, 1, 5, 2], [2, 5, 3, 6], [6, 3, 1, 4]] - sage: K3 == K3r # needs sage.groups - True + sage: K3 = Knot([[5, 2, 4, 1], [3, 6, 2, 5], [1, 4, 6, 3]]) + sage: K3r = K3.reverse(); K3r.pd_code() + [[4, 1, 5, 2], [2, 5, 3, 6], [6, 3, 1, 4]] + sage: K3 == K3r # needs sage.groups + True a non reversable knot:: From d6ccaefa0748cfad575efe63a7ca7bd51adb6130 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 4 Jun 2024 10:32:54 -0700 Subject: [PATCH 113/231] src/sage/knots/knotinfo.py: Fix # needs --- src/sage/knots/knotinfo.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/sage/knots/knotinfo.py b/src/sage/knots/knotinfo.py index e07d13d00a1..d0dd236a2ca 100644 --- a/src/sage/knots/knotinfo.py +++ b/src/sage/knots/knotinfo.py @@ -1364,16 +1364,18 @@ def kauffman_polynomial(self, var1='a', var2='z', original=False): EXAMPLES:: - sage: # needs sage.modules sage: L = KnotInfo.L2a1_1 + sage: K = KnotInfo.K4_1 + + sage: # needs sage.modules sage: L.kauffman_polynomial() a^-1*z - a^-1*z^-1 + a^-2 + a^-3*z - a^-3*z^-1 - sage: K = KnotInfo.K4_1 sage: K.kauffman_polynomial() a^2*z^2 + a*z^3 - a^2 - a*z + 2*z^2 + a^-1*z^3 - 1 - a^-1*z + a^-2*z^2 - a^-2 Comparison with Jones polynomial:: + sage: # needs sage.symbolic sage: k = _ sage: a, z = k.variables() sage: j = K.jones_polynomial(skein_normalization=True) @@ -1383,6 +1385,7 @@ def kauffman_polynomial(self, var1='a', var2='z', original=False): Check the skein relation:: + sage: # needs sage.modules sage: K3_1 = KnotInfo.K3_1 sage: FK3_1 = K3_1.kauffman_polynomial() sage: FL2a1_1 = L.kauffman_polynomial() @@ -1521,16 +1524,15 @@ def jones_polynomial(self, variab=None, skein_normalization=False, puiseux=False Check the skein-relation from the KnotInfo description page (applied to one of the positive crossings of the right-handed trefoil):: - sage: # needs sage.symbolic sage: K3_1 = KnotInfo.K3_1 - sage: K3_1j = K3_1.jones_polynomial() + sage: K3_1j = K3_1.jones_polynomial() # needs sage.symbolic sage: L2a1_1j = Ljt # see note above sage: R = L2a1_1j.parent() sage: Oj = R(1) sage: t = R('t') - sage: lhs = expand(~t*K3_1j - t*Oj) + sage: lhs = expand(~t*K3_1j - t*Oj) # needs sage.symbolic sage: rhs = expand((sqrt(t) - ~sqrt(t))*L2a1_1j) - sage: bool(lhs == rhs) + sage: bool(lhs == rhs) # needs sage.symbolic True The same with the Puiseux series version:: From f33e981cfe5e6de58010472b6bda85f4f93c62a1 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 4 Jun 2024 10:38:55 -0700 Subject: [PATCH 114/231] src/sage/knots/link.py: Fix # needs, use block tag --- src/sage/knots/link.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/sage/knots/link.py b/src/sage/knots/link.py index 62731967f44..857c08544e9 100644 --- a/src/sage/knots/link.py +++ b/src/sage/knots/link.py @@ -3065,9 +3065,10 @@ def homfly_polynomial(self, var1=None, var2=None, normalization='lm'): Comparison with KnotInfo:: + sage: # needs sage.groups sage.libs.homfly sage: KI, m = K.get_knotinfo(); KI, m (, ) - sage: K.homfly_polynomial(normalization='vz') == KI.homfly_polynomial() # needs sage.libs.homfly + sage: K.homfly_polynomial(normalization='vz') == KI.homfly_polynomial() True The knot `9_6`:: @@ -3628,14 +3629,15 @@ def plot(self, gap=0.1, component_gap=0.5, solver=None, Check that :issue:`20315` is fixed:: + sage: # needs sage.plot sage: L = Link([[2,1,4,5], [5,6,7,3], [6,4,1,9], [9,2,3,7]]) - sage: L.plot(solver='GLPK') # needs sage.plot + sage: L.plot(solver='GLPK') Graphics object consisting of ... graphics primitives - sage: L.plot(solver='Coin') # optional - sage_numerical_backends_coin, needs sage.plot + sage: L.plot(solver='Coin') # optional - sage_numerical_backends_coin Graphics object consisting of ... graphics primitives - sage: L.plot(solver='CPLEX') # optional - cplex # needs sage.plot + sage: L.plot(solver='CPLEX') # optional - CPLEX Graphics object consisting of ... graphics primitives - sage: L.plot(solver='Gurobi') # optional - gurobi # needs sage.plot + sage: L.plot(solver='Gurobi') # optional - Gurobi Graphics object consisting of ... graphics primitives """ pd_code = self.pd_code() @@ -4035,7 +4037,7 @@ def _knotinfo_matching_list(self): Defining L5a1_0 sage: ML = L5a1_0.link()._knotinfo_matching_list(); ML # needs sage.libs.homfly ([, ], True) - sage: ML == Link(L5a1_0.braid())._knotinfo_matching_list() + sage: ML == Link(L5a1_0.braid())._knotinfo_matching_list() # needs sage.libs.homfly True Care is needed for links having non irreducible HOMFLY-PT polynomials:: From c87a39bf6268765eac52b3b9bc08c8b2a7cb0fdd Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 5 Jun 2024 21:25:46 -0700 Subject: [PATCH 115/231] sage-fixdoctests --verbose: Show statistics on doctest tags --- src/bin/sage-fixdoctests | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/bin/sage-fixdoctests b/src/bin/sage-fixdoctests index 044170fac53..9877af91cc8 100755 --- a/src/bin/sage-fixdoctests +++ b/src/bin/sage-fixdoctests @@ -38,6 +38,7 @@ import subprocess import sys from argparse import ArgumentParser +from collections import defaultdict from pathlib import Path from sage.doctest.control import DocTestDefaults, DocTestController @@ -459,6 +460,8 @@ def process_grouped_blocks(grouped_iterator, distribution=None, venv=None, envir src_in_lines = src_in.splitlines() shallow_copy_of_src_in_lines = list(src_in_lines) file_optional_tags = set(parse_file_optional_tags(enumerate(src_in_lines))) + persistent_tags_counts = defaultdict(int) + tags_counts = defaultdict(int) for block in blocks: try: @@ -474,6 +477,7 @@ def process_grouped_blocks(grouped_iterator, distribution=None, venv=None, envir # Remove duplicate optional tags and rewrite all '# optional' that should be '# needs' persistent_optional_tags = {} + persistent_optional_tags_counted = False for i, line in enumerate(src_in_lines): if m := re.match(' *sage: *(.*)#', line): tags, line_sans_tags, is_persistent = parse_optional_tags(line, return_string_sans_tags=True) @@ -481,6 +485,7 @@ def process_grouped_blocks(grouped_iterator, distribution=None, venv=None, envir persistent_optional_tags = {tag: explanation for tag, explanation in tags.items() if explanation or tag not in file_optional_tags} + persistent_optional_tags_counted = False line = update_optional_tags(line, tags=persistent_optional_tags, force_rewrite='standard') if re.fullmatch(' *sage: *', line): # persistent (block-scoped or file-scoped) tag was removed, so remove the whole line @@ -491,9 +496,19 @@ def process_grouped_blocks(grouped_iterator, distribution=None, venv=None, envir if explanation or (tag not in file_optional_tags and tag not in persistent_optional_tags)} line = update_optional_tags(line, tags=tags, force_rewrite='standard') + if not persistent_optional_tags_counted: + persistent_tags_counts[frozenset(persistent_optional_tags)] += 1 + persistent_optional_tags_counted = True + tags_counts[frozenset(tags)] += 1 src_in_lines[i] = line elif line.strip() in ['', '"""', "'''"]: # Blank line or end of docstring persistent_optional_tags = {} + persistent_optional_tags_counted = False + elif re.match(' *sage: ', line): + if not persistent_optional_tags_counted: + persistent_tags_counts[frozenset(persistent_optional_tags)] += 1 + persistent_optional_tags_counted = True + tags_counts[frozenset()] += 1 if src_in_lines != shallow_copy_of_src_in_lines: if (output := output_filename(input)) is None: @@ -523,6 +538,21 @@ def process_grouped_blocks(grouped_iterator, distribution=None, venv=None, envir unprocessed_files.discard(input) + if args.verbose: + if file_optional_tags: + print(f"File tags: ") + print(f" {' '.join(sorted(file_optional_tags))}") + if persistent_tags_counts: + print(f"Doctest blocks by persistent tags: ") + for tags, count in sorted(persistent_tags_counts.items(), + key=lambda i: i[1], reverse=True): + print(f"{count:6} {' '.join(sorted(tags)) or '(untagged)'}") + if tags_counts: + print(f"Doctest examples by tags: ") + for tags, count in sorted(tags_counts.items(), + key=lambda i: i[1], reverse=True): + print(f"{count:6} {' '.join(sorted(tags)) or '(untagged)'}") + def fix_with_distribution(file_set, distribution=None, verbose=False): if verbose: From 784d0aad74fe578cf7e10c25772a1aca509702fc Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 5 Jun 2024 21:39:36 -0700 Subject: [PATCH 116/231] src/sage/knots: Add file-level doctest tag '# needs sage.graphs' --- src/sage/knots/gauss_code.py | 1 + src/sage/knots/knot.py | 1 + src/sage/knots/knotinfo.py | 1 + src/sage/knots/link.py | 1 + 4 files changed, 4 insertions(+) diff --git a/src/sage/knots/gauss_code.py b/src/sage/knots/gauss_code.py index 9d5a816d577..560b6831bfc 100644 --- a/src/sage/knots/gauss_code.py +++ b/src/sage/knots/gauss_code.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.graphs """ Helper functions related to Gauss codes of knots diff --git a/src/sage/knots/knot.py b/src/sage/knots/knot.py index 3593983ed4b..c084a7679c8 100644 --- a/src/sage/knots/knot.py +++ b/src/sage/knots/knot.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.graphs r""" Knots diff --git a/src/sage/knots/knotinfo.py b/src/sage/knots/knotinfo.py index d0dd236a2ca..0bd572223e3 100644 --- a/src/sage/knots/knotinfo.py +++ b/src/sage/knots/knotinfo.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.graphs r""" Access to the KnotInfo database diff --git a/src/sage/knots/link.py b/src/sage/knots/link.py index 857c08544e9..865d7aebbb7 100644 --- a/src/sage/knots/link.py +++ b/src/sage/knots/link.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.graphs r""" Links From 50c83dc189c92e58a8b874b7318de7d47a3b0dc2 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 6 Jun 2024 22:40:14 -0700 Subject: [PATCH 117/231] src/sage/knots/link.py: Use file-level # needs sage.groups --- src/sage/knots/link.py | 100 +++++++++++------------------------------ 1 file changed, 27 insertions(+), 73 deletions(-) diff --git a/src/sage/knots/link.py b/src/sage/knots/link.py index 865d7aebbb7..21af0859ea6 100644 --- a/src/sage/knots/link.py +++ b/src/sage/knots/link.py @@ -1,4 +1,4 @@ -# sage.doctest: needs sage.graphs +# sage.doctest: needs sage.graphs sage.groups r""" Links @@ -92,7 +92,6 @@ class Link(SageObject): - The closure of a braid is a link:: - sage: # needs sage.groups sage: B = BraidGroup(8) sage: L = Link(B([-1, -1, -1, -2, 1, -2, 3, -2, 3])); L Link with 1 component represented by 9 crossings @@ -167,7 +166,6 @@ class Link(SageObject): We can construct links from the braid group:: - sage: # needs sage.groups sage: B = BraidGroup(4) sage: L = Link(B([-1, -1, -1, -2, 1, -2, 3, -2])); L Link with 2 components represented by 8 crossings @@ -181,7 +179,7 @@ class Link(SageObject): :: - sage: L = Link(B([1, 2, 1, 3])); L # needs sage.groups + sage: L = Link(B([1, 2, 1, 3])); L Link with 2 components represented by 4 crossings .. PLOT:: @@ -200,7 +198,7 @@ class Link(SageObject): sage: L.oriented_gauss_code() [[[1, -4, 3, -1, 10, -9, 6, -7, 8, 5, 4, -3, 2, -6, 7, -8, 9, -10, -5, -2]], [1, -1, 1, 1, 1, -1, -1, -1, -1, -1]] - sage: L.braid() # needs sage.groups + sage: L.braid() s0*s1^-3*s2^-1*s1*s3*s2^2*s1^-1*s0^-1*s2*s1^-1*s3^-1*s2*s1^-1 .. PLOT:: @@ -232,7 +230,6 @@ class Link(SageObject): We construct the knot `7_1` and compute some invariants:: - sage: # needs sage.groups sage: B = BraidGroup(2) sage: L = Link(B([1]*7)) @@ -245,7 +242,6 @@ class Link(SageObject): :: - sage: # needs sage.groups sage: L.alexander_polynomial() t^-3 - t^-2 + t^-1 - 1 + t - t^2 + t^3 sage: L.jones_polynomial() @@ -257,7 +253,6 @@ class Link(SageObject): The links here have removed components in which no strand is used:: - sage: # needs sage.groups sage: B = BraidGroup(8) sage: b = B([1]) sage: L = Link(b) @@ -292,7 +287,6 @@ def __init__(self, data): TESTS:: - sage: # needs sage.groups sage: B = BraidGroup(8) sage: L = Link(B([-1, -1, -1, -2,1, -2, 3, -2])) sage: TestSuite(L).run() @@ -335,7 +329,6 @@ def __init__(self, data): Verify that :issue:`29692` is fixed:: - sage: # needs sage.groups sage: B = BraidGroup(5) sage: L = Link(B([3,4,3,-4])); L Link with 1 component represented by 4 crossings @@ -345,7 +338,7 @@ def __init__(self, data): PD code can be a list of 4-tuples:: sage: code = [(2, 5, 3, 6), (4, 1, 5, 2), (6, 3, 1, 4)] - sage: K = Knot(code); K.alexander_polynomial() # needs sage.groups + sage: K = Knot(code); K.alexander_polynomial() t^-1 - 1 + t """ if isinstance(data, list): @@ -489,7 +482,6 @@ def fundamental_group(self, presentation='wirtinger'): EXAMPLES:: - sage: # needs sage.groups sage: L = Link([[1, 4, 3, 2], [3, 4, 1, 2]]) sage: L.fundamental_group() Finitely presented group < x0, x1, x2 | x1*x0^-1*x2^-1*x0, x2*x0*x1^-1*x0^-1 > @@ -499,7 +491,6 @@ def fundamental_group(self, presentation='wirtinger'): We can see, for instance, that the two presentations of the group of the figure eight knot correspond to isomorphic groups:: - sage: # needs sage.groups sage: K8 = Knot([[[1, -2, 4, -3, 2, -1, 3, -4]], [1, 1, -1, -1]]) sage: GA = K8.fundamental_group(); GA Finitely presented group < x0, x1, x2, x3 | @@ -547,7 +538,6 @@ def _repr_(self): EXAMPLES:: - sage: # needs sage.groups sage: B = BraidGroup(8) sage: L = Link(B([1, 2, 1, 2])); L Link with 1 component represented by 4 crossings @@ -570,7 +560,6 @@ def __eq__(self, other): TESTS:: - sage: # needs sage.groups sage: B = BraidGroup(8) sage: L1 = Link(B([-1, -1, -1, -2, 1, -2, 3, -2, 5, 4])) sage: L2 = Link(B([-1, -1, -1, -2, 1, -2, 3, -2, 5, 4])) @@ -596,7 +585,6 @@ def __hash__(self): EXAMPLES:: - sage: # needs sage.groups sage: B = BraidGroup(8) sage: L1 = Link(B([-1, -1, -1, -2, 1, -2, 3, -2, 5, 4])) sage: H = hash(L1) @@ -609,7 +597,6 @@ def __ne__(self, other): TESTS:: - sage: # needs sage.groups sage: B = BraidGroup(8) sage: L1 = Link(B([-1, -1, -1, -2, 1, -2, 3, -2, 5, 4])) sage: L2 = Link(B([-1, -1, -1, -2, 1, -2, 3, -2, 5, 4])) @@ -642,7 +629,6 @@ def braid(self, remove_loops=False): EXAMPLES:: - sage: # needs sage.groups sage: L = Link([[2, 4, 1, 3], [4, 2, 3, 1]]) sage: L.braid() s^2 @@ -663,7 +649,6 @@ def braid(self, remove_loops=False): TESTS:: - sage: # needs sage.groups sage: L = Link([]) sage: L.braid() 1 @@ -673,7 +658,6 @@ def braid(self, remove_loops=False): Check that :issue:`25050` is solved:: - sage: # needs sage.groups sage: A = Link([[[1, 2, -2, -1, -3, -4, 4, 3]], [1, 1, 1, 1]]) sage: A.braid() s0*s1*s2*s3 @@ -1264,7 +1248,7 @@ def khovanov_homology(self, ring=ZZ, height=None, degree=None): The Hopf link:: - sage: # needs sage.groups sage.modules + sage: # needs sage.modules sage: B = BraidGroup(2) sage: b = B([1, 1]) sage: K = Link(b) @@ -1358,7 +1342,6 @@ def oriented_gauss_code(self): sage: L.oriented_gauss_code() [[[-1, 2], [-3, 4], [1, 3, -4, -2]], [-1, -1, 1, 1]] - sage: # needs sage.groups sage: B = BraidGroup(8) sage: b = B([1, 1, 1, 1, 1]) sage: L = Link(b) @@ -1371,7 +1354,6 @@ def oriented_gauss_code(self): sage: L.oriented_gauss_code() [[], []] - sage: # needs sage.groups sage: L = Link(BraidGroup(2).one()) sage: L.oriented_gauss_code() [[], []] @@ -1439,7 +1421,6 @@ def pd_code(self): sage: L.pd_code() [[6, 2, 7, 1], [2, 6, 3, 5], [8, 3, 1, 4], [4, 7, 5, 8]] - sage: # needs sage.groups sage: B = BraidGroup(2) sage: b = B([1, 1, 1, 1, 1]) sage: L = Link(b) @@ -1458,7 +1439,6 @@ def pd_code(self): sage: L.pd_code() [] - sage: # needs sage.groups sage: L = Link(BraidGroup(2).one()) sage: L.pd_code() [] @@ -1548,7 +1528,6 @@ def gauss_code(self): sage: L.gauss_code() [[-1, 2], [1, -2]] - sage: # needs sage.groups sage: B = BraidGroup(8) sage: L = Link(B([1, -2, 1, -2, -2])) sage: L.gauss_code() @@ -1582,7 +1561,6 @@ def dowker_notation(self): sage: L.dowker_notation() [(1, 6), (7, 2), (3, 10), (11, 4), (14, 5), (13, 8), (12, 9)] - sage: # needs sage.groups sage: B = BraidGroup(4) sage: L = Link(B([1, 2, 1, 2])) sage: L.dowker_notation() @@ -1613,7 +1591,6 @@ def _braid_word_components(self): EXAMPLES:: - sage: # needs sage.groups sage: B = BraidGroup(4) sage: L = Link(B([-1, 3, 1, 3])) sage: L._braid_word_components() @@ -1656,7 +1633,6 @@ def _braid_word_components_vector(self): EXAMPLES:: - sage: # needs sage.groups sage: B = BraidGroup(4) sage: L = Link(B([-1, 3, 1, 3])) sage: L._braid_word_components_vector() @@ -1690,7 +1666,7 @@ def _homology_generators(self): EXAMPLES:: - sage: # needs sage.groups sage.modules + sage: # needs sage.modules sage: B = BraidGroup(4) sage: L = Link(B([-1, 3, 1, 3])) sage: L._homology_generators() @@ -1730,7 +1706,7 @@ def seifert_matrix(self): EXAMPLES:: - sage: # needs sage.groups sage.modules + sage: # needs sage.modules sage: B = BraidGroup(4) sage: L = Link(B([-1, 3, 1, 3])) sage: L.seifert_matrix() @@ -1780,7 +1756,6 @@ def number_of_components(self): EXAMPLES:: - sage: # needs sage.groups sage: B = BraidGroup(4) sage: L = Link(B([-1, 3, 1, 3])) sage: L.number_of_components() @@ -1814,7 +1789,6 @@ def is_knot(self): EXAMPLES:: - sage: # needs sage.groups sage: B = BraidGroup(4) sage: L = Link(B([1, 3, 1, -3])) sage: L.is_knot() @@ -1832,7 +1806,6 @@ def genus(self): EXAMPLES:: - sage: # needs sage.groups sage: B = BraidGroup(4) sage: L = Link(B([-1, 3, 1, 3])) sage: L.genus() @@ -1896,7 +1869,7 @@ def signature(self): EXAMPLES:: - sage: # needs sage.groups sage.modules + sage: # needs sage.modules sage: B = BraidGroup(4) sage: L = Link(B([-1, 3, 1, 3])) sage: L.signature() @@ -1939,7 +1912,7 @@ def omega_signature(self, omega): EXAMPLES:: - sage: # needs sage.groups sage.modules sage.rings.number_field + sage: # needs sage.modules sage.rings.number_field sage: B = BraidGroup(4) sage: K = Knot(B([1,1,1,2,-1,2,-3,2,-3])) sage: omega = QQbar.zeta(3) @@ -1965,7 +1938,7 @@ def alexander_polynomial(self, var='t'): We begin by computing the Alexander polynomial for the figure-eight knot:: - sage: # needs sage.groups sage.modules + sage: # needs sage.modules sage: B = BraidGroup(3) sage: L = Link(B([1, -2, 1, -2])) sage: L.alexander_polynomial() @@ -1976,12 +1949,12 @@ def alexander_polynomial(self, var='t'): sage: L = Link([[3,1,2,4],[8,9,1,7],[5,6,7,3],[4,18,6,5], ....: [17,19,8,18],[9,10,11,14],[10,12,13,11], ....: [12,19,15,13],[20,16,14,15],[16,20,17,2]]) - sage: L.alexander_polynomial() # needs sage.groups sage.modules + sage: L.alexander_polynomial() # needs sage.modules 1 Some additional examples:: - sage: # needs sage.groups sage.modules + sage: # needs sage.modules sage: B = BraidGroup(2) sage: L = Link(B([1])) sage: L.alexander_polynomial() @@ -1997,7 +1970,7 @@ def alexander_polynomial(self, var='t'): When the Seifert surface is disconnected, the Alexander polynomial is defined to be `0`:: - sage: # needs sage.groups sage.modules + sage: # needs sage.modules sage: B = BraidGroup(4) sage: L = Link(B([1,3])) sage: L.alexander_polynomial() @@ -2005,7 +1978,7 @@ def alexander_polynomial(self, var='t'): TESTS:: - sage: # needs sage.groups sage.modules + sage: # needs sage.modules sage: B = BraidGroup(4) sage: L = Link(B([-1, 3, 1, 3])) sage: L.alexander_polynomial() @@ -2043,7 +2016,7 @@ def conway_polynomial(self): EXAMPLES:: - sage: # needs sage.groups sage.modules + sage: # needs sage.modules sage: B = BraidGroup(3) sage: L = Link(B([1, -2, 1, -2])) sage: L.conway_polynomial() @@ -2119,7 +2092,6 @@ def khovanov_polynomial(self, var1='q', var2='t', base_ring=ZZ): The Hopf link:: - sage: # needs sage.groups sage: B = BraidGroup(2) sage: b = B([1, 1]) sage: K = Link(b) @@ -2148,7 +2120,7 @@ def determinant(self): EXAMPLES:: - sage: # needs sage.groups sage.modules + sage: # needs sage.modules sage: B = BraidGroup(4) sage: L = Link(B([-1, 2, 1, 2])) sage: L.determinant() @@ -2166,7 +2138,7 @@ def determinant(self): TESTS:: - sage: # needs sage.groups sage.modules + sage: # needs sage.modules sage: B = BraidGroup(3) sage: Link(B([1, 2, 1, -2, -1])).determinant() 0 @@ -2202,7 +2174,6 @@ def is_alternating(self): EXAMPLES:: - sage: # needs sage.groups sage: B = BraidGroup(4) sage: L = Link(B([-1, -1, -1, -1])) sage: L.is_alternating() @@ -2228,7 +2199,6 @@ def is_alternating(self): sage: K5_2.is_alternating() True - sage: # needs sage.groups sage: K5_2b = Link(K5_2.braid()) sage: K5_2b.is_alternating() False @@ -2314,7 +2284,6 @@ def seifert_circles(self): sage: L.seifert_circles() [[1, 11, 8], [2, 7, 12, 4, 5, 10], [3, 9, 6]] - sage: # needs sage.groups sage: B = BraidGroup(2) sage: L = Link(B([1, 1, 1])) sage: L.seifert_circles() @@ -2384,7 +2353,6 @@ def regions(self): [[16, 8, 14, 4], [15, -4], [13, -8, 1], [12, -1, -7], [11, 7, -16, 5], [10, -5, -15, -3], [9, 3, -14], [6, -11], [2, -9, -13], [-2, -12, -6, -10]] - sage: # needs sage.groups sage: B = BraidGroup(2) sage: L = Link(B([-1, -1, -1])) sage: L.regions() @@ -2406,7 +2374,6 @@ def regions(self): TESTS:: - sage: # needs sage.groups sage: B = BraidGroup(6) sage: L = Link(B([1, 3, 5])) sage: L.regions() @@ -2518,7 +2485,6 @@ def mirror_image(self): EXAMPLES:: - sage: # needs sage.groups sage: g = BraidGroup(2).gen(0) sage: K = Link(g^3) sage: K2 = K.mirror_image(); K2 @@ -2613,12 +2579,11 @@ def reverse(self): sage: K3 = Knot([[5, 2, 4, 1], [3, 6, 2, 5], [1, 4, 6, 3]]) sage: K3r = K3.reverse(); K3r.pd_code() [[4, 1, 5, 2], [2, 5, 3, 6], [6, 3, 1, 4]] - sage: K3 == K3r # needs sage.groups + sage: K3 == K3r True a non reversable knot:: - sage: # needs sage.groups sage: K8_17 = Knot([[6, 1, 7, 2], [14, 7, 15, 8], [8, 4, 9, 3], ....: [2, 14, 3, 13], [12, 6, 13, 5], [4, 10, 5, 9], ....: [16, 11, 1, 12], [10, 15, 11, 16]]) @@ -2736,7 +2701,6 @@ def jones_polynomial(self, variab=None, skein_normalization=False, algorithm='jo The unknot:: - sage: # needs sage.groups sage: B = BraidGroup(9) sage: b = B([1, 2, 3, 4, 5, 6, 7, 8]) sage: Link(b).jones_polynomial() @@ -2760,7 +2724,6 @@ def jones_polynomial(self, variab=None, skein_normalization=False, algorithm='jo Two unlinked unknots:: - sage: # needs sage.groups sage: B = BraidGroup(4) sage: b = B([1, 3]) sage: Link(b).jones_polynomial() # needs sage.symbolic @@ -2768,7 +2731,6 @@ def jones_polynomial(self, variab=None, skein_normalization=False, algorithm='jo The Hopf link:: - sage: # needs sage.groups sage: B = BraidGroup(2) sage: b = B([-1,-1]) sage: Link(b).jones_polynomial() # needs sage.symbolic @@ -2776,7 +2738,6 @@ def jones_polynomial(self, variab=None, skein_normalization=False, algorithm='jo Different representations of the trefoil and one of its mirror:: - sage: # needs sage.groups sage: B = BraidGroup(2) sage: b = B([-1, -1, -1]) sage: Link(b).jones_polynomial(skein_normalization=True) @@ -2798,7 +2759,6 @@ def jones_polynomial(self, variab=None, skein_normalization=False, algorithm='jo `K11n42` (the mirror of the "Kinoshita-Terasaka" knot) and `K11n34` (the mirror of the "Conway" knot) in [KnotAtlas]_:: - sage: # needs sage.groups sage: B = BraidGroup(4) sage: K11n42 = Link(B([1, -2, 3, -2, 3, -2, -2, -1, 2, -3, -3, 2, 2])) sage: K11n34 = Link(B([1, 1, 2, -3, 2, -3, 1, -2, -2, -3, -3])) @@ -2820,7 +2780,6 @@ def jones_polynomial(self, variab=None, skein_normalization=False, algorithm='jo braid is not necessarily the link itself, this is only true up to a power of the Jones polynomial of the unknot:: - sage: # needs sage.groups sage: B = BraidGroup(3) sage: b = B([1]) sage: L = Link(b) @@ -2848,7 +2807,7 @@ def jones_polynomial(self, variab=None, skein_normalization=False, algorithm='jo Check that :issue:`31001` is fixed:: - sage: L.jones_polynomial() # needs sage.groups + sage: L.jones_polynomial() 1 """ if algorithm == 'statesum': @@ -3025,7 +2984,6 @@ def homfly_polynomial(self, var1=None, var2=None, normalization='lm'): We give some examples:: - sage: # needs sage.groups sage: g = BraidGroup(2).gen(0) sage: K = Knot(g^5) sage: K.homfly_polynomial() # needs sage.libs.homfly @@ -3066,7 +3024,7 @@ def homfly_polynomial(self, var1=None, var2=None, normalization='lm'): Comparison with KnotInfo:: - sage: # needs sage.groups sage.libs.homfly + sage: # needs sage.libs.homfly sage: KI, m = K.get_knotinfo(); KI, m (, ) sage: K.homfly_polynomial(normalization='vz') == KI.homfly_polynomial() @@ -3074,7 +3032,7 @@ def homfly_polynomial(self, var1=None, var2=None, normalization='lm'): The knot `9_6`:: - sage: # needs sage.groups sage.libs.homfly + sage: # needs sage.libs.homfly sage: B = BraidGroup(3) sage: K = Knot(B([-1,-1,-1,-1,-1,-1,-2,1,-2,-2])) sage: K.homfly_polynomial() @@ -3192,7 +3150,7 @@ def links_gould_polynomial(self, varnames='t0, t1'): EXAMPLES:: sage: Hopf = Link([[1, 3, 2, 4], [4, 2, 3, 1]]) - sage: Hopf.links_gould_polynomial() # needs sage.groups + sage: Hopf.links_gould_polynomial() -1 + t1^-1 + t0^-1 - t0^-1*t1^-1 """ return self.braid().links_gould_polynomial(varnames=varnames) @@ -3611,7 +3569,6 @@ def plot(self, gap=0.1, component_gap=0.5, solver=None, If a coloring is passed, the different arcs are plotted with the corresponding colors (see :meth:`colorings`):: - sage: # needs sage.groups sage: B = BraidGroup(4) sage: b = B([1,2,3,1,2,-1,-3,2,3]) sage: L = Link(b) @@ -3970,7 +3927,6 @@ def _markov_move_cmp(self, braid): EXAMPLES:: - sage: # needs sage.groups sage: b = BraidGroup(4)((1, 2, -3, 2, 2, 2, 2, 2, 2, -1, 2, 3, 2)) sage: L = Link([[2, 5, 4, 1], [5, 7, 6, 4], [7, 9, 8, 6], [9, 11, 10, 8], ....: [11, 13, 12, 10], [13, 15, 14, 12], [15, 17, 16, 14], @@ -4230,7 +4186,6 @@ def get_knotinfo(self, mirror_version=True, unique=True): cannot be identified. In addition non prime links or even links whose HOMFLY-PT polynomial is not irreducible cannot be identified:: - sage: # needs sage.groups sage: b, = BraidGroup(2).gens() sage: Link(b**13).get_knotinfo() # optional - database_knotinfo (, ) @@ -4306,7 +4261,6 @@ def get_knotinfo(self, mirror_version=True, unique=True): the same unoriented name (according to the note above) the option can be used to achieve more detailed information:: - sage: # needs sage.groups sage: L2a1 = Link(b**2) sage: L2a1.get_knotinfo() (Series of links L2a1, ) @@ -4581,11 +4535,11 @@ def is_isotopic(self, other): sage: l2 = Link([[1, 8, 2, 9], [9, 2, 10, 3], [3, 14, 4, 1], ....: [13, 4, 14, 5], [5, 12, 6, 13], [11, 6, 12, 7], ....: [7, 10, 8, 11]]) - sage: l1.is_isotopic(l2) # needs sage.groups + sage: l1.is_isotopic(l2) True sage: l3 = l2.mirror_image() - sage: l1.is_isotopic(l3) # needs sage.groups + sage: l1.is_isotopic(l3) False sage: # optional - database_knotinfo @@ -4595,13 +4549,13 @@ def is_isotopic(self, other): sage: L == L7a7(0) True sage: l = L.link() - sage: l.is_isotopic(L7a7(1).link()) # needs sage.groups + sage: l.is_isotopic(L7a7(1).link()) Traceback (most recent call last): ... NotImplementedError: comparison not possible! - sage: l.is_isotopic(L7a7(2).link()) # needs sage.groups + sage: l.is_isotopic(L7a7(2).link()) True - sage: l.is_isotopic(L7a7(3).link()) # needs sage.groups + sage: l.is_isotopic(L7a7(3).link()) False Using verbosity:: From c7b36fa0121fed8f691a82b44d39dbb816aa0db6 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 22 Jun 2024 18:48:18 -0700 Subject: [PATCH 118/231] build/pkgs/sphinx: Update to 7.3.7 --- build/pkgs/sphinx/checksums.ini | 4 ++-- build/pkgs/sphinx/package-version.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build/pkgs/sphinx/checksums.ini b/build/pkgs/sphinx/checksums.ini index 5cd194279be..f46ca655b6d 100644 --- a/build/pkgs/sphinx/checksums.ini +++ b/build/pkgs/sphinx/checksums.ini @@ -1,4 +1,4 @@ tarball=sphinx-VERSION-py3-none-any.whl -sha1=d4155cf2dbd768db9431fddcb7f53dd67caf56e1 -sha256=1e09160a40b956dc623c910118fa636da93bd3ca0b9876a7b3df90f07d691560 +sha1=8128e17c3c013a91df4c08fc905db5a7e5f63dbf +sha256=413f75440be4cacf328f580b4274ada4565fb2187d696a84970c23f77b64d8c3 upstream_url=https://pypi.io/packages/py3/s/sphinx/sphinx-VERSION-py3-none-any.whl diff --git a/build/pkgs/sphinx/package-version.txt b/build/pkgs/sphinx/package-version.txt index ba6a7620d4e..704726ec86c 100644 --- a/build/pkgs/sphinx/package-version.txt +++ b/build/pkgs/sphinx/package-version.txt @@ -1 +1 @@ -7.2.6 +7.3.7 From cb5e95291f8ad0c3ad02f51cb8f586191b75d59a Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 22 Jun 2024 18:48:41 -0700 Subject: [PATCH 119/231] build/pkgs/furo: Update to 2024.5.6 --- build/pkgs/furo/checksums.ini | 4 ++-- build/pkgs/furo/package-version.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build/pkgs/furo/checksums.ini b/build/pkgs/furo/checksums.ini index b6feae79dad..861c13f47b0 100644 --- a/build/pkgs/furo/checksums.ini +++ b/build/pkgs/furo/checksums.ini @@ -1,4 +1,4 @@ tarball=furo-VERSION-py3-none-any.whl -sha1=21afca1ac0f309541bfd5b89e61097a1bd4b681e -sha256=513092538537dc5c596691da06e3c370714ec99bc438680edc1debffb73e5bfc +sha1=f43dad408126f23ec5c480ad993e42335ca47713 +sha256=490a00d08c0a37ecc90de03ae9227e8eb5d6f7f750edf9807f398a2bdf2358de upstream_url=https://pypi.io/packages/py3/f/furo/furo-VERSION-py3-none-any.whl diff --git a/build/pkgs/furo/package-version.txt b/build/pkgs/furo/package-version.txt index 0b9bb54f90d..eedc5a2915f 100644 --- a/build/pkgs/furo/package-version.txt +++ b/build/pkgs/furo/package-version.txt @@ -1 +1 @@ -2023.9.10 +2024.5.6 From 7d3a5f02e80ffeeaa4320af0c10192792b500787 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 22 Jun 2024 18:49:08 -0700 Subject: [PATCH 120/231] build/pkgs/docutils: Update to 0.21.2 --- build/pkgs/docutils/checksums.ini | 4 ++-- build/pkgs/docutils/package-version.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build/pkgs/docutils/checksums.ini b/build/pkgs/docutils/checksums.ini index ebcc15cc5a1..472701e55d7 100644 --- a/build/pkgs/docutils/checksums.ini +++ b/build/pkgs/docutils/checksums.ini @@ -1,4 +1,4 @@ tarball=docutils-VERSION-py3-none-any.whl -sha1=2bac2b2e9f4cc6d832588457c5f69bac79d80239 -sha256=96f387a2c5562db4476f09f13bbab2192e764cac08ebbf3a34a95d9b1e4a59d6 +sha1=a2120453cdb1498128183696711261dd5f328068 +sha256=dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2 upstream_url=https://pypi.io/packages/py3/d/docutils/docutils-VERSION-py3-none-any.whl diff --git a/build/pkgs/docutils/package-version.txt b/build/pkgs/docutils/package-version.txt index 847e9aef6d1..59dad104b0b 100644 --- a/build/pkgs/docutils/package-version.txt +++ b/build/pkgs/docutils/package-version.txt @@ -1 +1 @@ -0.20.1 +0.21.2 From a9b2f4234cb5254a126411fb8f081570f4537d90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sun, 23 Jun 2024 08:51:42 +0200 Subject: [PATCH 121/231] partial care for empty lines in pyx in rings ; activate E302 check in pyx --- src/sage/rings/complex_interval.pyx | 1 - src/sage/rings/finite_rings/element_base.pyx | 1 + src/sage/rings/finite_rings/element_givaro.pyx | 1 + src/sage/rings/finite_rings/element_ntl_gf2e.pyx | 2 +- .../rings/finite_rings/hom_finite_field_givaro.pyx | 3 --- src/sage/rings/fraction_field_element.pyx | 2 +- src/sage/rings/laurent_series_ring_element.pyx | 5 ----- src/sage/rings/polynomial/cyclotomic.pyx | 1 + src/sage/rings/polynomial/hilbert.pyx | 2 ++ .../multi_polynomial_ideal_libsingular.pyx | 5 +++-- .../polynomial/multi_polynomial_libsingular.pyx | 1 + src/sage/rings/polynomial/polynomial_compiled.pyx | 2 -- src/sage/rings/polynomial/polynomial_element.pyx | 5 ++++- src/sage/rings/polynomial/polynomial_gf2x.pyx | 2 ++ .../rings/polynomial/polynomial_number_field.pyx | 3 ++- .../rings/polynomial/polynomial_rational_flint.pyx | 1 - src/sage/rings/polynomial/weil/weil_polynomials.pyx | 1 + src/sage/rings/power_series_mpoly.pyx | 1 - src/sage/rings/power_series_ring_element.pyx | 2 -- src/sage/rings/rational.pyx | 6 ++---- src/sage/rings/sum_of_squares.pyx | 8 ++++++-- src/sage/rings/tate_algebra_element.pyx | 12 +----------- src/sage/rings/tate_algebra_ideal.pyx | 2 ++ src/tox.ini | 2 +- 24 files changed, 32 insertions(+), 39 deletions(-) diff --git a/src/sage/rings/complex_interval.pyx b/src/sage/rings/complex_interval.pyx index 5b3064688b0..7ff9dc9d452 100644 --- a/src/sage/rings/complex_interval.pyx +++ b/src/sage/rings/complex_interval.pyx @@ -1002,7 +1002,6 @@ cdef class ComplexIntervalFieldElement(FieldElement): """ raise TypeError - def _sage_input_(self, sib, coerce): r""" Produce an expression which will reproduce this value when evaluated. diff --git a/src/sage/rings/finite_rings/element_base.pyx b/src/sage/rings/finite_rings/element_base.pyx index 18b0db173b5..7d98b99b95f 100755 --- a/src/sage/rings/finite_rings/element_base.pyx +++ b/src/sage/rings/finite_rings/element_base.pyx @@ -24,6 +24,7 @@ from sage.rings.integer_ring import ZZ from sage.rings.integer import Integer from sage.misc.superseded import deprecated_function_alias + def is_FiniteFieldElement(x): """ Return ``True`` if ``x`` is a finite field element. diff --git a/src/sage/rings/finite_rings/element_givaro.pyx b/src/sage/rings/finite_rings/element_givaro.pyx index 401f398ddee..2ef19972fb0 100644 --- a/src/sage/rings/finite_rings/element_givaro.pyx +++ b/src/sage/rings/finite_rings/element_givaro.pyx @@ -1729,6 +1729,7 @@ cdef class FiniteField_givaroElement(FinitePolyExtElement): """ return unpickle_FiniteField_givaroElement,(self.parent(),self.element) + def unpickle_FiniteField_givaroElement(parent, int x): """ TESTS:: diff --git a/src/sage/rings/finite_rings/element_ntl_gf2e.pyx b/src/sage/rings/finite_rings/element_ntl_gf2e.pyx index 32ffd192353..f8272336c8a 100644 --- a/src/sage/rings/finite_rings/element_ntl_gf2e.pyx +++ b/src/sage/rings/finite_rings/element_ntl_gf2e.pyx @@ -1021,7 +1021,6 @@ cdef class FiniteField_ntl_gf2eElement(FinitePolyExtElement): cdef int pow = n/d return f if pow == 1 else f**pow - def minpoly(self, var='x'): r""" Return the minimal polynomial of ``self``, which is the smallest @@ -1302,6 +1301,7 @@ cdef class FiniteField_ntl_gf2eElement(FinitePolyExtElement): x = pari.fflog(self, base, (base_order, fac)) return Integer(x) + def unpickleFiniteField_ntl_gf2eElement(parent, elem): """ EXAMPLES:: diff --git a/src/sage/rings/finite_rings/hom_finite_field_givaro.pyx b/src/sage/rings/finite_rings/hom_finite_field_givaro.pyx index bf3e69f56a7..81b7045b8f6 100644 --- a/src/sage/rings/finite_rings/hom_finite_field_givaro.pyx +++ b/src/sage/rings/finite_rings/hom_finite_field_givaro.pyx @@ -99,7 +99,6 @@ cdef class SectionFiniteFieldHomomorphism_givaro(SectionFiniteFieldHomomorphism_ self._codomain_cache = ((self._codomain.gen()))._cache - cpdef Element _call_(self, x): """ TESTS:: @@ -181,7 +180,6 @@ cdef class FiniteFieldHomomorphism_givaro(FiniteFieldHomomorphism_generic): self._order_domain = domain.cardinality() - 1 self._order_codomain = codomain.cardinality() - 1 - cpdef Element _call_(self, x): """ TESTS:: @@ -228,7 +226,6 @@ cdef class FrobeniusEndomorphism_givaro(FrobeniusEndomorphism_finite_field): raise TypeError("The domain is not an instance of FiniteField_givaro") FrobeniusEndomorphism_finite_field.__init__(self, domain, power) - def fixed_field(self): """ Return the fixed field of ``self``. diff --git a/src/sage/rings/fraction_field_element.pyx b/src/sage/rings/fraction_field_element.pyx index e651a0bf560..38abe60b094 100644 --- a/src/sage/rings/fraction_field_element.pyx +++ b/src/sage/rings/fraction_field_element.pyx @@ -264,7 +264,6 @@ cdef class FractionFieldElement(FieldElement): """ return self._denominator - def is_square(self,root=False): """ Return whether or not ``self`` is a perfect square. @@ -1286,6 +1285,7 @@ cdef class FractionFieldElement_1poly_field(FractionFieldElement): super(self.__class__, self).reduce() self.normalize_leading_coefficients() + def make_element(parent, numerator, denominator): """ Used for unpickling :class:`FractionFieldElement` objects (and subclasses). diff --git a/src/sage/rings/laurent_series_ring_element.pyx b/src/sage/rings/laurent_series_ring_element.pyx index 62c244d1669..f03ad5a3fd5 100644 --- a/src/sage/rings/laurent_series_ring_element.pyx +++ b/src/sage/rings/laurent_series_ring_element.pyx @@ -149,7 +149,6 @@ cdef class LaurentSeries(AlgebraElement): elif parent is not f.parent(): f = parent._power_series_ring(f) - # self is that t^n * u: if not f: if n is infinity: @@ -822,7 +821,6 @@ cdef class LaurentSeries(AlgebraElement): # 3. Subtract return type(self)(self._parent, f1 - f2, m) - def add_bigoh(self, prec): """ Return the truncated series at chosen precision ``prec``. @@ -1564,7 +1562,6 @@ cdef class LaurentSeries(AlgebraElement): """ return multi_derivative(self, args) - def _derivative(self, var=None): """ The formal derivative of this Laurent series with respect to var. @@ -1624,7 +1621,6 @@ cdef class LaurentSeries(AlgebraElement): u = self._parent._power_series_ring(v, self.__u.prec()) return type(self)(self._parent, u, n-1) - def integral(self): r""" The formal integral of this Laurent series with 0 constant term. @@ -1682,7 +1678,6 @@ cdef class LaurentSeries(AlgebraElement): raise ArithmeticError("Coefficients of integral cannot be coerced into the base ring") return type(self)(self._parent, u, n+1) - def nth_root(self, long n, prec=None): r""" Return the ``n``-th root of this Laurent power series. diff --git a/src/sage/rings/polynomial/cyclotomic.pyx b/src/sage/rings/polynomial/cyclotomic.pyx index 84f85104cc3..4d1c44c5ec0 100644 --- a/src/sage/rings/polynomial/cyclotomic.pyx +++ b/src/sage/rings/polynomial/cyclotomic.pyx @@ -40,6 +40,7 @@ try: except ImportError: pass + def cyclotomic_coeffs(nn, sparse=None): """ Return the coefficients of the `n`-th cyclotomic polynomial diff --git a/src/sage/rings/polynomial/hilbert.pyx b/src/sage/rings/polynomial/hilbert.pyx index 198a0940b95..59ba9bc1304 100644 --- a/src/sage/rings/polynomial/hilbert.pyx +++ b/src/sage/rings/polynomial/hilbert.pyx @@ -421,6 +421,7 @@ cdef make_children(Node D, tuple w): # It may be a good idea to form the product of some of the most # frequent variables. But this isn't implemented yet. TODO? + def first_hilbert_series(I, grading=None, return_grading=False): """ Return the first Hilbert series of the given monomial ideal. @@ -550,6 +551,7 @@ def first_hilbert_series(I, grading=None, return_grading=False): fmpz_poly_add(fhs._poly, AN.LMult, AN.RMult) got_result = True + def hilbert_poincare_series(I, grading=None): r""" Return the Hilbert Poincaré series of the given monomial ideal. diff --git a/src/sage/rings/polynomial/multi_polynomial_ideal_libsingular.pyx b/src/sage/rings/polynomial/multi_polynomial_ideal_libsingular.pyx index 14820418454..e01f181be1d 100644 --- a/src/sage/rings/polynomial/multi_polynomial_ideal_libsingular.pyx +++ b/src/sage/rings/polynomial/multi_polynomial_ideal_libsingular.pyx @@ -145,6 +145,7 @@ cdef ideal *sage_ideal_to_singular_ideal(I) except NULL: raise TypeError("All generators must be of type MPolynomial_libsingular.") return i + def kbase_libsingular(I, degree=None): """ SINGULAR's ``kbase()`` algorithm. @@ -201,6 +202,7 @@ def kbase_libsingular(I, degree=None): return res + def std_libsingular(I): """ SINGULAR's ``std()`` algorithm. @@ -224,7 +226,6 @@ def std_libsingular(I): idSkipZeroes(result) - id_Delete(&i,r) res = singular_ideal_to_sage_sequence(result,r,I.ring()) @@ -272,6 +273,7 @@ def slimgb_libsingular(I): id_Delete(&result,r) return res + def interred_libsingular(I): """ SINGULAR's ``interred()`` command. @@ -318,7 +320,6 @@ def interred_libsingular(I): sig_off() singular_options = bck - # divide head by coefficients if r.cf.type != n_Z and r.cf.type != n_Znm and r.cf.type != n_Zn and r.cf.type != n_Z2m : for j from 0 <= j < IDELEMS(result): diff --git a/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx b/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx index 6b838190c52..ce239335523 100644 --- a/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx +++ b/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx @@ -1877,6 +1877,7 @@ cdef class MPolynomialRing_libsingular(MPolynomialRing_base): M.append(new_MP(self, p_Copy(tempvector, _ring))) return M + def unpickle_MPolynomialRing_libsingular(base_ring, names, term_order): """ inverse function for ``MPolynomialRing_libsingular.__reduce__`` diff --git a/src/sage/rings/polynomial/polynomial_compiled.pyx b/src/sage/rings/polynomial/polynomial_compiled.pyx index 01fac1e932f..f17122814de 100644 --- a/src/sage/rings/polynomial/polynomial_compiled.pyx +++ b/src/sage/rings/polynomial/polynomial_compiled.pyx @@ -232,8 +232,6 @@ cdef class CompiledPolynomialFunction: The r == 0 case in step 3 is equivalent to binary exponentiation. """ - - cdef int m,n,k,r,half cdef generic_pd T,N,H cdef dummy_pd M diff --git a/src/sage/rings/polynomial/polynomial_element.pyx b/src/sage/rings/polynomial/polynomial_element.pyx index dcf2af7cdf2..5d2fc9df65f 100644 --- a/src/sage/rings/polynomial/polynomial_element.pyx +++ b/src/sage/rings/polynomial/polynomial_element.pyx @@ -11554,7 +11554,6 @@ cdef class Polynomial(CommutativePolynomial): phi = SpecializationMorphism(self._parent,D) return phi(self) - def _log_series(self, long n): r""" Return the power series expansion of logarithm of this polynomial, @@ -11711,6 +11710,7 @@ cdef class Polynomial(CommutativePolynomial): """ raise NotImplementedError + # ----------------- inner functions ------------- # Cython can't handle function definitions inside other function @@ -11766,6 +11766,7 @@ cdef list do_schoolbook_product(list x, list y, Py_ssize_t deg): coeffs[k] = sum return coeffs + @cython.boundscheck(False) @cython.wraparound(False) @cython.overflowcheck(False) @@ -11848,6 +11849,7 @@ cdef list do_karatsuba_different_size(list left, list right, Py_ssize_t K_thresh output.extend(carry[n-1:]) return output + @cython.boundscheck(False) @cython.wraparound(False) @cython.overflowcheck(False) @@ -12581,6 +12583,7 @@ cdef class Polynomial_generic_dense(Polynomial): self._coeffs = self._coeffs[:n] return self + def make_generic_polynomial(parent, coeffs): return parent(coeffs) diff --git a/src/sage/rings/polynomial/polynomial_gf2x.pyx b/src/sage/rings/polynomial/polynomial_gf2x.pyx index c3bafe951ca..fceadf66d6b 100644 --- a/src/sage/rings/polynomial/polynomial_gf2x.pyx +++ b/src/sage/rings/polynomial/polynomial_gf2x.pyx @@ -310,6 +310,7 @@ def GF2X_BuildIrred_list(n): GF2X_BuildIrred(f, int(n)) return [GF2(not GF2_IsZero(GF2X_coeff(f, i))) for i in range(n + 1)] + def GF2X_BuildSparseIrred_list(n): """ Return the list of coefficients of an irreducible polynomial of @@ -330,6 +331,7 @@ def GF2X_BuildSparseIrred_list(n): GF2X_BuildSparseIrred(f, int(n)) return [GF2(not GF2_IsZero(GF2X_coeff(f, i))) for i in range(n + 1)] + def GF2X_BuildRandomIrred_list(n): """ Return the list of coefficients of an irreducible polynomial of diff --git a/src/sage/rings/polynomial/polynomial_number_field.pyx b/src/sage/rings/polynomial/polynomial_number_field.pyx index 80d7af0e4b1..6386f624d05 100644 --- a/src/sage/rings/polynomial/polynomial_number_field.pyx +++ b/src/sage/rings/polynomial/polynomial_number_field.pyx @@ -69,7 +69,7 @@ We can also construct polynomials over relative number fields:: # Distributed under the terms of the GNU General Public License (GPL) # as published by the Free Software Foundation; either version 2 of # the License, or (at your option) any later version. -# http://www.gnu.org/licenses/ +# https://www.gnu.org/licenses/ #***************************************************************************** from sage.rings.polynomial.polynomial_element_generic import Polynomial_generic_dense_field @@ -77,6 +77,7 @@ from sage.rings.rational_field import QQ from sage.structure.element import coerce_binop from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing + class Polynomial_absolute_number_field_dense(Polynomial_generic_dense_field): """ Class of dense univariate polynomials over an absolute number field. diff --git a/src/sage/rings/polynomial/polynomial_rational_flint.pyx b/src/sage/rings/polynomial/polynomial_rational_flint.pyx index a43e34a3fc9..84d6ed56596 100644 --- a/src/sage/rings/polynomial/polynomial_rational_flint.pyx +++ b/src/sage/rings/polynomial/polynomial_rational_flint.pyx @@ -165,7 +165,6 @@ cdef class Polynomial_rational_flint(Polynomial): fmpq_poly_set_si(res._poly, int(x)) return res - def __cinit__(self): """ Initialises the underlying data structure. diff --git a/src/sage/rings/polynomial/weil/weil_polynomials.pyx b/src/sage/rings/polynomial/weil/weil_polynomials.pyx index f9d61a2a352..ca5288a963f 100755 --- a/src/sage/rings/polynomial/weil/weil_polynomials.pyx +++ b/src/sage/rings/polynomial/weil/weil_polynomials.pyx @@ -231,6 +231,7 @@ cdef class dfs_manager: raise RuntimeError("Node limit ({0:%d}) exceeded".format(self.node_limit)) return ans + class WeilPolynomials_iter(): r""" Iterator created by WeilPolynomials. diff --git a/src/sage/rings/power_series_mpoly.pyx b/src/sage/rings/power_series_mpoly.pyx index 714d939c30b..f7a298e8410 100644 --- a/src/sage/rings/power_series_mpoly.pyx +++ b/src/sage/rings/power_series_mpoly.pyx @@ -116,7 +116,6 @@ cdef class PowerSeries_mpoly(PowerSeries): prec = prec, check =True) - def __iter__(self): """ Return an iterator over the coefficients of this power series. diff --git a/src/sage/rings/power_series_ring_element.pyx b/src/sage/rings/power_series_ring_element.pyx index 8e1b76a7cc9..30055b75453 100644 --- a/src/sage/rings/power_series_ring_element.pyx +++ b/src/sage/rings/power_series_ring_element.pyx @@ -794,7 +794,6 @@ cdef class PowerSeries(AlgebraElement): s += " + %s"%bigoh return s.lstrip(" ") - def truncate(self, prec=infinity): """ The polynomial obtained from power series by truncation. @@ -2725,7 +2724,6 @@ cdef class PowerSeries(AlgebraElement): """ return multi_derivative(self, args) - def __setitem__(self, n, value): """ Called when an attempt is made to change a power series. diff --git a/src/sage/rings/rational.pyx b/src/sage/rings/rational.pyx index 819a85dbc35..8a591520d98 100644 --- a/src/sage/rings/rational.pyx +++ b/src/sage/rings/rational.pyx @@ -82,6 +82,7 @@ from sage.structure.richcmp cimport rich_to_bool_sgn RealNumber_classes = () + def _register_real_number_class(cls): r""" Register ``cls``. @@ -1580,7 +1581,6 @@ cdef class Rational(sage.structure.element.FieldElement): a, b = K.pari_bnf(proof=proof).bnfisnorm(self, flag=extra_primes) return K(a), Rational(b) - def is_perfect_power(self, expected_value=False): r""" Return ``True`` if ``self`` is a perfect power. @@ -3560,7 +3560,6 @@ cdef class Rational(sage.structure.element.FieldElement): else: return sage.rings.infinity.infinity - def multiplicative_order(self): """ Return the multiplicative order of ``self``. @@ -3633,10 +3632,9 @@ cdef class Rational(sage.structure.element.FieldElement): """ return True - #Function alias for checking if the number is a integer. Added to solve issue 15500 + # Function alias for checking if the number is a integer. Added to solve issue 15500 is_integer = is_integral - def is_S_integral(self, S=[]): r""" Determine if the rational number is ``S``-integral. diff --git a/src/sage/rings/sum_of_squares.pyx b/src/sage/rings/sum_of_squares.pyx index 5cd916690de..a1f06964719 100644 --- a/src/sage/rings/sum_of_squares.pyx +++ b/src/sage/rings/sum_of_squares.pyx @@ -130,6 +130,7 @@ cdef int three_squares_c(uint_fast32_t n, uint_fast32_t res[3]) noexcept: return 1 + def two_squares_pyx(uint32_t n): r""" Return a pair of non-negative integers ``(i,j)`` such that `i^2 + j^2 = n`. @@ -184,7 +185,8 @@ def two_squares_pyx(uint32_t n): return (integer.smallInteger(i[0]), integer.smallInteger(i[1])) sig_off() - raise ValueError("%d is not a sum of 2 squares"%n) + raise ValueError("%d is not a sum of 2 squares" % n) + def is_sum_of_two_squares_pyx(uint32_t n): r""" @@ -214,6 +216,7 @@ def is_sum_of_two_squares_pyx(uint32_t n): sig_off() return False + def three_squares_pyx(uint32_t n): r""" If ``n`` is a sum of three squares return a 3-tuple ``(i,j,k)`` of Sage integers @@ -266,7 +269,8 @@ def three_squares_pyx(uint32_t n): return (integer.smallInteger(i[0]), integer.smallInteger(i[1]), integer.smallInteger(i[2])) sig_off() - raise ValueError("%d is not a sum of 3 squares"%n) + raise ValueError("%d is not a sum of 3 squares" % n) + def four_squares_pyx(uint32_t n): r""" diff --git a/src/sage/rings/tate_algebra_element.pyx b/src/sage/rings/tate_algebra_element.pyx index 86b0a4dba52..6b606881399 100644 --- a/src/sage/rings/tate_algebra_element.pyx +++ b/src/sage/rings/tate_algebra_element.pyx @@ -1013,7 +1013,6 @@ cdef class TateAlgebraTerm(MonoidElement): raise ValueError("the division is not exact") return (self)._floordiv_c(other) - cdef TateAlgebraTerm _floordiv_c(self, TateAlgebraTerm other): r""" Return the result of the exact division of this term by ``other``. @@ -1664,7 +1663,6 @@ cdef class TateAlgebraElement(CommutativeAlgebraElement): """ return self.nth_root(2, prec) - def sqrt(self, prec=None): r""" Return the square root of this series. @@ -1705,7 +1703,6 @@ cdef class TateAlgebraElement(CommutativeAlgebraElement): """ return self.nth_root(2, prec) - def nth_root(self, n=2, prec=None): r""" Return the ``n``-th root of this series. @@ -1791,7 +1788,6 @@ cdef class TateAlgebraElement(CommutativeAlgebraElement): root += scalar * root * (1 - a * root**n) return root - cpdef _richcmp_(self, other, int op): r""" Compare this series with ``other`` according to @@ -2801,7 +2797,6 @@ cdef class TateAlgebraElement(CommutativeAlgebraElement): series += nfactorial return series / nfactorial - def leading_term(self, secure=False): r""" Return the leading term of this series. @@ -2885,7 +2880,6 @@ cdef class TateAlgebraElement(CommutativeAlgebraElement): else: raise ValueError("zero has no leading term") - def leading_coefficient(self, secure=False): """ Return the leading coefficient of this series. @@ -3026,15 +3020,11 @@ cdef class TateAlgebraElement(CommutativeAlgebraElement): ...00000000010 + ...0000000001*x*y sage: g.is_monic() False - """ if self.valuation() != 0: return False c = self.leading_coefficient() - if c != 0 and c.unit_part() == 1: - return True - return False - + return c != 0 and c.unit_part() == 1 def weierstrass_degree(self): r""" diff --git a/src/sage/rings/tate_algebra_ideal.pyx b/src/sage/rings/tate_algebra_ideal.pyx index acad1be5fd3..5d72155f97c 100644 --- a/src/sage/rings/tate_algebra_ideal.pyx +++ b/src/sage/rings/tate_algebra_ideal.pyx @@ -35,6 +35,7 @@ from heapq import heappush, heappop from cysignals.signals cimport sig_check + class TateAlgebraIdeal(Ideal_generic): r""" Initialize a class for ideals in a Tate series algebra @@ -785,6 +786,7 @@ def print_pair(p, verbose): s, v = p return "(sign = %s, series = %s + ...)" % (s, v.leading_term()) + def groebner_basis_pote(I, prec, verbose=0): r""" Run the PoTe algorithm to compute the Groebner basis of ``I`` diff --git a/src/tox.ini b/src/tox.ini index c270270ff52..dd8b51409ef 100644 --- a/src/tox.ini +++ b/src/tox.ini @@ -181,7 +181,7 @@ description = # See https://pycodestyle.pycqa.org/en/latest/intro.html#error-codes deps = pycodestyle commands = pycodestyle --select E111,E21,E221,E222,E225,E227,E228,E25,E271,E303,E305,E306,E401,E502,E701,E702,E703,E71,E72,W291,W293,W391,W605 {posargs:{toxinidir}/sage/} - pycodestyle --select E111,E271,E301,E305,E306,E401,E502,E703,E712,E713,E714,E72,W29,W391,W605, --filename *.pyx {posargs:{toxinidir}/sage/} + pycodestyle --select E111,E271,E301,E302,E305,E306,E401,E502,E703,E712,E713,E714,E72,W29,W391,W605, --filename *.pyx {posargs:{toxinidir}/sage/} [pycodestyle] max-line-length = 160 From ed0efcfa79c929e332c1dc468422ba9ead397995 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sun, 23 Jun 2024 09:41:37 +0200 Subject: [PATCH 122/231] some care for pep E272 (spurious white spaces) --- src/sage/categories/bimodules.py | 2 +- src/sage/categories/finite_enumerated_sets.py | 2 +- src/sage/categories/group_algebras.py | 2 +- src/sage/categories/poor_man_map.py | 2 +- src/sage/categories/semigroups.py | 2 +- src/sage/crypto/mq/sr.py | 4 ++-- src/sage/geometry/ribbon_graph.py | 4 ++-- src/sage/graphs/generic_graph.py | 4 ++-- src/sage/groups/cubic_braid.py | 4 ++-- src/sage/knots/link.py | 2 +- src/sage/matrix/symplectic_basis.py | 4 ++-- src/sage/modular/abvar/cuspidal_subgroup.py | 16 ++++++------- src/sage/modular/local_comp/local_comp.py | 22 ++++++++--------- .../modular/modform/cuspidal_submodule.py | 2 +- src/sage/modular/modform/numerical.py | 24 +++++++++---------- src/sage/numerical/optimize.py | 4 +++- src/sage/schemes/elliptic_curves/mod_poly.py | 2 +- src/sage/tensor/modules/comp.py | 4 ++-- 18 files changed, 54 insertions(+), 52 deletions(-) diff --git a/src/sage/categories/bimodules.py b/src/sage/categories/bimodules.py index 52f83bfefd4..5cf247fd6b5 100644 --- a/src/sage/categories/bimodules.py +++ b/src/sage/categories/bimodules.py @@ -102,7 +102,7 @@ def _make_named_class_key(self, name): sage: Bimodules(Fields(), Rings())._make_named_class_key('element_class') (Category of fields, Category of rings) """ - return (self._left_base_ring if isinstance(self._left_base_ring, Category) else self._left_base_ring.category(), + return (self._left_base_ring if isinstance(self._left_base_ring, Category) else self._left_base_ring.category(), self._right_base_ring if isinstance(self._right_base_ring, Category) else self._right_base_ring.category()) @classmethod diff --git a/src/sage/categories/finite_enumerated_sets.py b/src/sage/categories/finite_enumerated_sets.py index b3b9ede2deb..0cb4aabb650 100644 --- a/src/sage/categories/finite_enumerated_sets.py +++ b/src/sage/categories/finite_enumerated_sets.py @@ -13,7 +13,7 @@ from sage.categories.enumerated_sets import EnumeratedSets from sage.categories.sets_cat import Sets from sage.categories.cartesian_product import CartesianProductsCategory -from sage.categories.isomorphic_objects import IsomorphicObjectsCategory +from sage.categories.isomorphic_objects import IsomorphicObjectsCategory from sage.misc.cachefunc import cached_method from sage.misc.lazy_import import lazy_import from sage.cpython.getattr import raw_getattr diff --git a/src/sage/categories/group_algebras.py b/src/sage/categories/group_algebras.py index b0700b004de..e02d01b8803 100644 --- a/src/sage/categories/group_algebras.py +++ b/src/sage/categories/group_algebras.py @@ -209,7 +209,7 @@ def center_basis(self): - :meth:`Groups.Algebras.ElementMethods.central_form` - :meth:`Monoids.Algebras.ElementMethods.is_central` """ - return tuple([self.sum_of_monomials(conj) for conj in + return tuple([self.sum_of_monomials(conj) for conj in self.basis().keys().conjugacy_classes()]) # Hopf algebra structure diff --git a/src/sage/categories/poor_man_map.py b/src/sage/categories/poor_man_map.py index ccbc32ecaca..11d206eefbc 100644 --- a/src/sage/categories/poor_man_map.py +++ b/src/sage/categories/poor_man_map.py @@ -94,7 +94,7 @@ def _repr_(self): """ return ((self._name if self._name is not None else "A map") + - (" from %s" % (self._domain,) if self._domain is not None else "" ) + + (" from %s" % (self._domain,) if self._domain is not None else "" ) + (" to %s" % (self._codomain,) if self._codomain is not None else "" )) def domain(self): diff --git a/src/sage/categories/semigroups.py b/src/sage/categories/semigroups.py index 658b77c96b2..744be185fb8 100644 --- a/src/sage/categories/semigroups.py +++ b/src/sage/categories/semigroups.py @@ -344,7 +344,7 @@ def cayley_graph(self, side="right", simple=False, elements=None, generators = self.semigroup_generators() if isinstance(generators, (list, tuple)): generators = {self(g): self(g) for g in generators} - left = (side == "left" or side == "twosided") + left = (side == "left" or side == "twosided") right = (side == "right" or side == "twosided") def add_edge(source, target, label, side_label): diff --git a/src/sage/crypto/mq/sr.py b/src/sage/crypto/mq/sr.py index 514d9df9c94..01753004526 100644 --- a/src/sage/crypto/mq/sr.py +++ b/src/sage/crypto/mq/sr.py @@ -2478,7 +2478,7 @@ def field_polynomials(self, name, i, l=None): l = r*c _vars = self.vars(name, i, l, e) - return [_vars[e*j+k]**2 - _vars[e*j+(k+1) % e] for j in range(l) for k in range(e)] + return [_vars[e*j+k]**2 - _vars[e*j+(k+1) % e] for j in range(l) for k in range(e)] class SR_gf2(SR_generic): def __init__(self, n=1, r=1, c=1, e=4, star=False, **kwargs): @@ -3200,7 +3200,7 @@ def field_polynomials(self, name, i, l=None): if self._polybori: return [] _vars = self.vars(name, i, l, e) - return [_vars[e*j+k]**2 - _vars[e*j+k] for j in range(l) for k in range(e)] + return [_vars[e*j+k]**2 - _vars[e*j+k] for j in range(l) for k in range(e)] class SR_gf2_2(SR_gf2): """ diff --git a/src/sage/geometry/ribbon_graph.py b/src/sage/geometry/ribbon_graph.py index 12918ae29b5..77128b94ad7 100644 --- a/src/sage/geometry/ribbon_graph.py +++ b/src/sage/geometry/ribbon_graph.py @@ -1210,10 +1210,10 @@ def bipartite_ribbon_graph(p, q): sigma = [] rho = [] for i in range(p): - aux_tuple = [i*q + j + 1 for j in range(q)] + aux_tuple = [i*q + j + 1 for j in range(q)] sigma += [aux_tuple] for i in range(q): - aux_tuple = [p*q + i*p + j + 1 for j in range(p)] + aux_tuple = [p*q + i*p + j + 1 for j in range(p)] sigma += [aux_tuple] for i in range(p*q): if (i+1) % q == 0: diff --git a/src/sage/graphs/generic_graph.py b/src/sage/graphs/generic_graph.py index 063931ae274..af03afbe9ec 100644 --- a/src/sage/graphs/generic_graph.py +++ b/src/sage/graphs/generic_graph.py @@ -19586,8 +19586,8 @@ def union(self, other, immutable=None): raise TypeError('both arguments must be of the same class') multiedges = self.allows_multiple_edges() or other.allows_multiple_edges() - loops = self.allows_loops() or other.allows_loops() - weighted = self.weighted() and other.weighted() + loops = self.allows_loops() or other.allows_loops() + weighted = self.weighted() and other.weighted() if self._directed: from sage.graphs.digraph import DiGraph diff --git a/src/sage/groups/cubic_braid.py b/src/sage/groups/cubic_braid.py index 6f357c91b58..a6f7c88d60d 100644 --- a/src/sage/groups/cubic_braid.py +++ b/src/sage/groups/cubic_braid.py @@ -995,7 +995,7 @@ def _test_matrix_group(self, **options): matrix_grpF4 = self.as_matrix_group(root_bur=r64) self._internal_test_attached_group(matrix_grpF4, tester) - if self.strands() < 5 or self._cbg_type == CubicBraidGroup.type.Coxeter: + if self.strands() < 5 or self._cbg_type == CubicBraidGroup.type.Coxeter: matrix_grpF5 = self.as_matrix_group(characteristic=5) self._internal_test_attached_group(matrix_grpF5, tester) @@ -1180,7 +1180,7 @@ def create_sympl_realization(self, m): # to the invariant bilinear form. # ----------------------------------------------------------- xbas = [bas[mhalf - i - 1] for i in range(mhalf)] - ybas = [bas[mhalf + i] for i in range(mhalf)] + ybas = [bas[mhalf + i] for i in range(mhalf)] # ----------------------------------------------------------- # computing the List of transvection vectors according to diff --git a/src/sage/knots/link.py b/src/sage/knots/link.py index 7470d8c2837..c4af6e0fc65 100644 --- a/src/sage/knots/link.py +++ b/src/sage/knots/link.py @@ -4396,7 +4396,7 @@ def answer_unori(S): if all(i is SymmetryMutant.mirror_image for i in sym_mut): # all matching links are mirrored to self return S, SymmetryMutant.mirror_image - if all(i is SymmetryMutant.itself for i in sym_mut): + if all(i is SymmetryMutant.itself for i in sym_mut): # all matching links are self itself return S, SymmetryMutant.itself if any(i is SymmetryMutant.unknown for i in sym_mut): diff --git a/src/sage/matrix/symplectic_basis.py b/src/sage/matrix/symplectic_basis.py index db38f5f3611..bc2e9de7687 100644 --- a/src/sage/matrix/symplectic_basis.py +++ b/src/sage/matrix/symplectic_basis.py @@ -533,8 +533,8 @@ def symplectic_basis_over_ZZ(M): pivot += 2 ps.sort() - es = [ p[1] for p in ps ] - fs = [ p[1]+1 for p in ps ] + es = [p[1] for p in ps] + fs = [p[1] + 1 for p in ps] C = B.matrix_from_rows(es + fs + zeroes) F = C * M * C.transpose() return F, C diff --git a/src/sage/modular/abvar/cuspidal_subgroup.py b/src/sage/modular/abvar/cuspidal_subgroup.py index 1df78b66f66..1cff9c4704e 100644 --- a/src/sage/modular/abvar/cuspidal_subgroup.py +++ b/src/sage/modular/abvar/cuspidal_subgroup.py @@ -69,14 +69,14 @@ # http://www.gnu.org/licenses/ #***************************************************************************** -from sage.matrix.constructor import matrix -from sage.modular.arithgroup.all import Gamma0_class -from sage.modular.cusps import Cusp -from sage.rings.infinity import infinity -from sage.rings.integer_ring import ZZ -from sage.rings.rational_field import QQ - -from .finite_subgroup import FiniteSubgroup +from sage.matrix.constructor import matrix +from sage.modular.arithgroup.all import Gamma0_class +from sage.modular.cusps import Cusp +from sage.rings.infinity import infinity +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ + +from .finite_subgroup import FiniteSubgroup class CuspidalSubgroup_generic(FiniteSubgroup): diff --git a/src/sage/modular/local_comp/local_comp.py b/src/sage/modular/local_comp/local_comp.py index 0fb990c17de..5432d111049 100644 --- a/src/sage/modular/local_comp/local_comp.py +++ b/src/sage/modular/local_comp/local_comp.py @@ -20,22 +20,22 @@ - Jared Weinstein """ -from sage.structure.sage_object import SageObject -from sage.rings.integer_ring import ZZ +from sage.structure.sage_object import SageObject +from sage.rings.integer_ring import ZZ from sage.rings.polynomial.polynomial_ring import polygen from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing -from sage.misc.abstract_method import abstract_method -from sage.misc.cachefunc import cached_method -from sage.misc.lazy_import import lazy_import -from sage.misc.verbose import verbose -from sage.misc.flatten import flatten -from sage.modular.modform.element import Newform -from sage.structure.sequence import Sequence +from sage.misc.abstract_method import abstract_method +from sage.misc.cachefunc import cached_method +from sage.misc.lazy_import import lazy_import +from sage.misc.verbose import verbose +from sage.misc.flatten import flatten +from sage.modular.modform.element import Newform +from sage.structure.sequence import Sequence lazy_import('sage.rings.qqbar', 'QQbar') -from .type_space import TypeSpace -from .smoothchar import SmoothCharacterGroupQp, SmoothCharacterGroupUnramifiedQuadratic, SmoothCharacterGroupRamifiedQuadratic +from .type_space import TypeSpace +from .smoothchar import SmoothCharacterGroupQp, SmoothCharacterGroupUnramifiedQuadratic, SmoothCharacterGroupRamifiedQuadratic def LocalComponent(f, p, twist_factor=None): r""" diff --git a/src/sage/modular/modform/cuspidal_submodule.py b/src/sage/modular/modform/cuspidal_submodule.py index 0bf53873ed3..80356227f93 100644 --- a/src/sage/modular/modform/cuspidal_submodule.py +++ b/src/sage/modular/modform/cuspidal_submodule.py @@ -43,7 +43,7 @@ from sage.matrix.special import identity_matrix from sage.misc.cachefunc import cached_method from sage.misc.lazy_import import lazy_import -from sage.misc.verbose import verbose +from sage.misc.verbose import verbose from sage.rings.integer import Integer from sage.rings.rational_field import QQ diff --git a/src/sage/modular/modform/numerical.py b/src/sage/modular/modform/numerical.py index 847859a70fb..775cf222099 100644 --- a/src/sage/modular/modform/numerical.py +++ b/src/sage/modular/modform/numerical.py @@ -13,20 +13,20 @@ # http://www.gnu.org/licenses/ #***************************************************************************** -from sage.rings.fast_arith import prime_range -from sage.matrix.constructor import matrix -from sage.misc.verbose import verbose -from sage.misc.cachefunc import cached_method -from sage.misc.prandom import randint +from sage.rings.fast_arith import prime_range +from sage.matrix.constructor import matrix +from sage.misc.verbose import verbose +from sage.misc.cachefunc import cached_method +from sage.misc.prandom import randint from sage.modular.arithgroup.all import Gamma0 -from sage.modular.modsym.all import ModularSymbols +from sage.modular.modsym.all import ModularSymbols from sage.modules.free_module_element import free_module_element as vector -from sage.rings.complex_double import CDF -from sage.rings.integer import Integer -from sage.rings.rational_field import QQ -from sage.structure.richcmp import richcmp_method, richcmp -from sage.structure.sage_object import SageObject -from sage.structure.sequence import Sequence +from sage.rings.complex_double import CDF +from sage.rings.integer import Integer +from sage.rings.rational_field import QQ +from sage.structure.richcmp import richcmp_method, richcmp +from sage.structure.sage_object import SageObject +from sage.structure.sequence import Sequence # This variable controls importing the SciPy library sparingly scipy = None diff --git a/src/sage/numerical/optimize.py b/src/sage/numerical/optimize.py index e3d94d1746e..d603f878d07 100644 --- a/src/sage/numerical/optimize.py +++ b/src/sage/numerical/optimize.py @@ -400,7 +400,9 @@ def minimize(func, x0, gradient=None, hessian=None, algorithm="default", fast_f = fast_callable(func, vars=var_names, domain=float) f = lambda p: fast_f(*p) gradient_list = func.gradient() - fast_gradient_functions = [fast_callable(gradient_list[i], vars=var_names, domain=float) for i in range(len(gradient_list))] + fast_gradient_functions = [fast_callable(gradient_list[i], + vars=var_names, domain=float) + for i in range(len(gradient_list))] gradient = lambda p: numpy.array([ a(*p) for a in fast_gradient_functions]) else: f = func diff --git a/src/sage/schemes/elliptic_curves/mod_poly.py b/src/sage/schemes/elliptic_curves/mod_poly.py index 580e2aa7598..58232132421 100644 --- a/src/sage/schemes/elliptic_curves/mod_poly.py +++ b/src/sage/schemes/elliptic_curves/mod_poly.py @@ -136,7 +136,7 @@ def classical_modular_polynomial(l, j=None): # If the generic polynomial is in the cache or the database, evaluating # it directly should always be faster than recomputing it from scratch. - if l in _cache: + if l in _cache: return _cache[l](j, Y) try: Phi = _db[l] diff --git a/src/sage/tensor/modules/comp.py b/src/sage/tensor/modules/comp.py index 6021997c3b0..775e7e5a667 100644 --- a/src/sage/tensor/modules/comp.py +++ b/src/sage/tensor/modules/comp.py @@ -1895,8 +1895,8 @@ def paral_mul(a, local_list_ind): if nproc != 1: # Parallel computation lol = lambda lst, sz: [lst[i:i+sz] for i in range(0, len(lst), sz)] - ind_list = [ind for ind in self._comp] - ind_step = max(1, int(len(ind_list)/nproc)) + ind_list = list(self._comp) + ind_step = max(1, int(len(ind_list) / nproc)) local_list = lol(ind_list, ind_step) # list of input parameters: listParalInput = [(self, other, ind_part) for ind_part in local_list] From 7ba93346487a33364a0cdffe93f2dc0e06d356cc Mon Sep 17 00:00:00 2001 From: Cyril Bouvier Date: Sun, 23 Jun 2024 15:12:13 +0200 Subject: [PATCH 123/231] graphs: in traversals algorithm, set the copy of the graph to immutable --- src/sage/graphs/traversals.pyx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/sage/graphs/traversals.pyx b/src/sage/graphs/traversals.pyx index 93fdaa8e73f..19bd88ea51c 100644 --- a/src/sage/graphs/traversals.pyx +++ b/src/sage/graphs/traversals.pyx @@ -87,7 +87,7 @@ def _is_valid_lex_BFS_order(G, L): """ # Convert G to a simple undirected graph if G.has_loops() or G.has_multiple_edges() or G.is_directed(): - G = G.to_simple(immutable=False, to_undirected=True) + G = G.to_simple(immutable=True, to_undirected=True) cdef int n = G.order() @@ -422,7 +422,7 @@ def lex_BFS(G, reverse=False, tree=False, initial_vertex=None, algorithm="fast") # Convert G to a simple undirected graph if G.has_loops() or G.has_multiple_edges() or G.is_directed(): - G = G.to_simple(immutable=False, to_undirected=True) + G = G.to_simple(immutable=True, to_undirected=True) cdef size_t n = G.order() if not n: @@ -600,7 +600,7 @@ def lex_UP(G, reverse=False, tree=False, initial_vertex=None): # Loops and multiple edges are not needed in Lex UP if G.allows_loops() or G.allows_multiple_edges(): - G = G.to_simple(immutable=False) + G = G.to_simple(immutable=True) cdef int nV = G.order() @@ -772,7 +772,7 @@ def lex_DFS(G, reverse=False, tree=False, initial_vertex=None): # Loops and multiple edges are not needed in Lex DFS if G.allows_loops() or G.allows_multiple_edges(): - G = G.to_simple(immutable=False) + G = G.to_simple(immutable=True) cdef int nV = G.order() @@ -946,7 +946,7 @@ def lex_DOWN(G, reverse=False, tree=False, initial_vertex=None): # Loops and multiple edges are not needed in Lex DOWN if G.allows_loops() or G.allows_multiple_edges(): - G = G.to_simple(immutable=False) + G = G.to_simple(immutable=True) cdef int nV = G.order() From cc80c801aa8e62b61af79a17266128b8dfbe69eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sun, 23 Jun 2024 15:41:22 +0200 Subject: [PATCH 124/231] fix suggested details --- src/sage/categories/poor_man_map.py | 7 +++---- src/sage/tensor/modules/comp.py | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/sage/categories/poor_man_map.py b/src/sage/categories/poor_man_map.py index 11d206eefbc..ac05114699c 100644 --- a/src/sage/categories/poor_man_map.py +++ b/src/sage/categories/poor_man_map.py @@ -91,15 +91,14 @@ def _repr_(self): A map from (1, 2, 3) sage: PoorManMap(lambda x: x+2, codomain=(3,4,5)) A map to (3, 4, 5) - """ return ((self._name if self._name is not None else "A map") + - (" from %s" % (self._domain,) if self._domain is not None else "" ) + - (" to %s" % (self._codomain,) if self._codomain is not None else "" )) + (" from %s" % (self._domain,) if self._domain is not None else "") + + (" to %s" % (self._codomain,) if self._codomain is not None else "")) def domain(self): """ - Returns the domain of ``self`` + Return the domain of ``self``. EXAMPLES:: diff --git a/src/sage/tensor/modules/comp.py b/src/sage/tensor/modules/comp.py index 775e7e5a667..d6a3572c143 100644 --- a/src/sage/tensor/modules/comp.py +++ b/src/sage/tensor/modules/comp.py @@ -1896,7 +1896,7 @@ def paral_mul(a, local_list_ind): # Parallel computation lol = lambda lst, sz: [lst[i:i+sz] for i in range(0, len(lst), sz)] ind_list = list(self._comp) - ind_step = max(1, int(len(ind_list) / nproc)) + ind_step = max(1, len(ind_list) // nproc) local_list = lol(ind_list, ind_step) # list of input parameters: listParalInput = [(self, other, ind_part) for ind_part in local_list] From dd4b51dc3caa4445c7e4a8b7d852bbbb5141bb4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sun, 23 Jun 2024 15:43:05 +0200 Subject: [PATCH 125/231] Update polynomial_number_field.pyx --- src/sage/rings/polynomial/polynomial_number_field.pyx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/rings/polynomial/polynomial_number_field.pyx b/src/sage/rings/polynomial/polynomial_number_field.pyx index 6386f624d05..54bddc4e203 100644 --- a/src/sage/rings/polynomial/polynomial_number_field.pyx +++ b/src/sage/rings/polynomial/polynomial_number_field.pyx @@ -63,14 +63,14 @@ We can also construct polynomials over relative number fields:: 1 """ -#***************************************************************************** +# **************************************************************************** # Copyright (C) 2014 Luis Felipe Tabera Alonso # # Distributed under the terms of the GNU General Public License (GPL) # as published by the Free Software Foundation; either version 2 of # the License, or (at your option) any later version. # https://www.gnu.org/licenses/ -#***************************************************************************** +# **************************************************************************** from sage.rings.polynomial.polynomial_element_generic import Polynomial_generic_dense_field from sage.rings.rational_field import QQ From 4bf041bc0c7daf28948183c975f5f437dec2c78e Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 23 Jun 2024 09:18:50 -0700 Subject: [PATCH 126/231] src/sage/doctest/external.py: mathics is not external --- src/sage/doctest/external.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/sage/doctest/external.py b/src/sage/doctest/external.py index ceec70230d0..aa158c76671 100644 --- a/src/sage/doctest/external.py +++ b/src/sage/doctest/external.py @@ -356,7 +356,9 @@ def external_features(): import sage.features.ffmpeg yield from sage.features.ffmpeg.all_features() import sage.features.interfaces - yield from sage.features.interfaces.all_features() + for feature in sage.features.interfaces.all_features(): + if feature.name != 'mathics': + yield feature from sage.features.mip_backends import CPLEX, Gurobi yield CPLEX() yield Gurobi() @@ -398,7 +400,6 @@ class AvailableSoftware(): 'magma', 'maple', 'mathematica', - 'mathics', 'matlab', 'octave', 'pdflatex', From 52a15229cc9f3f891bcd69536601e9ed55d9cc50 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 23 Jun 2024 09:20:41 -0700 Subject: [PATCH 127/231] build/pkgs/mathics/requirements.txt: Use mathics-scanner from git --- build/pkgs/mathics/requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/build/pkgs/mathics/requirements.txt b/build/pkgs/mathics/requirements.txt index 5335f5690e1..88f2f65c22c 100644 --- a/build/pkgs/mathics/requirements.txt +++ b/build/pkgs/mathics/requirements.txt @@ -1,2 +1,3 @@ Mathics3 @ git+https://github.com/Mathics3/mathics-core +mathics-scanner @ git+https://github.com/Mathics3/mathics-scanner -c ${SAGE_VENV}/var/lib/sage/scripts/numpy/spkg-requirements.txt From 1b87ce0f7210abcc145c11f2c8c0956c28f2f878 Mon Sep 17 00:00:00 2001 From: Cyril Bouvier Date: Mon, 24 Jun 2024 09:18:03 +0200 Subject: [PATCH 128/231] graphs: fix lex_UP, lex_DOWN and lex_DFS for DiGraph --- src/sage/graphs/traversals.pyx | 42 ++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/src/sage/graphs/traversals.pyx b/src/sage/graphs/traversals.pyx index 19bd88ea51c..af78c3c8572 100644 --- a/src/sage/graphs/traversals.pyx +++ b/src/sage/graphs/traversals.pyx @@ -509,6 +509,9 @@ def lex_UP(G, reverse=False, tree=False, initial_vertex=None): - ``initial_vertex`` -- (default: ``None``); the first vertex to consider + Loops and multiple edges are ignored during the computation of lex_UP and + directed graphs are converted to undirected graphs. + ALGORITHM: This algorithm maintains for each vertex left in the graph a code @@ -549,8 +552,9 @@ def lex_UP(G, reverse=False, tree=False, initial_vertex=None): The method also works for directed graphs:: sage: G = DiGraph([(1, 2), (2, 3), (1, 3)]) - sage: G.lex_UP(initial_vertex=2) - [2, 3, 1] + sage: correct_anwsers = [[2, 1, 3], [2, 3, 1]] + sage: G.lex_UP(initial_vertex=2) in correct_anwsers + True Different orderings for different traversals:: @@ -598,9 +602,9 @@ def lex_UP(G, reverse=False, tree=False, initial_vertex=None): if initial_vertex is not None and initial_vertex not in G: raise ValueError("'{}' is not a graph vertex".format(initial_vertex)) - # Loops and multiple edges are not needed in Lex UP - if G.allows_loops() or G.allows_multiple_edges(): - G = G.to_simple(immutable=True) + # Convert G to a simple undirected graph + if G.has_loops() or G.has_multiple_edges() or G.is_directed(): + G = G.to_simple(immutable=True, to_undirected=True) cdef int nV = G.order() @@ -682,6 +686,9 @@ def lex_DFS(G, reverse=False, tree=False, initial_vertex=None): - ``initial_vertex`` -- (default: ``None``); the first vertex to consider + Loops and multiple edges are ignored during the computation of lex_DFS and + directed graphs are converted to undirected graphs. + ALGORITHM: This algorithm maintains for each vertex left in the graph a code @@ -721,8 +728,9 @@ def lex_DFS(G, reverse=False, tree=False, initial_vertex=None): The method also works for directed graphs:: sage: G = DiGraph([(1, 2), (2, 3), (1, 3)]) - sage: G.lex_DFS(initial_vertex=2) - [2, 3, 1] + sage: correct_anwsers = [[2, 1, 3], [2, 3, 1]] + sage: G.lex_DFS(initial_vertex=2) in correct_anwsers + True Different orderings for different traversals:: @@ -770,9 +778,9 @@ def lex_DFS(G, reverse=False, tree=False, initial_vertex=None): if initial_vertex is not None and initial_vertex not in G: raise ValueError("'{}' is not a graph vertex".format(initial_vertex)) - # Loops and multiple edges are not needed in Lex DFS - if G.allows_loops() or G.allows_multiple_edges(): - G = G.to_simple(immutable=True) + # Convert G to a simple undirected graph + if G.has_loops() or G.has_multiple_edges() or G.is_directed(): + G = G.to_simple(immutable=True, to_undirected=True) cdef int nV = G.order() @@ -855,6 +863,9 @@ def lex_DOWN(G, reverse=False, tree=False, initial_vertex=None): - ``initial_vertex`` -- (default: ``None``); the first vertex to consider + Loops and multiple edges are ignored during the computation of lex_DOWN and + directed graphs are converted to undirected graphs. + ALGORITHM: This algorithm maintains for each vertex left in the graph a code @@ -895,8 +906,9 @@ def lex_DOWN(G, reverse=False, tree=False, initial_vertex=None): The method also works for directed graphs:: sage: G = DiGraph([(1, 2), (2, 3), (1, 3)]) - sage: G.lex_DOWN(initial_vertex=2) - [2, 3, 1] + sage: correct_anwsers = [[2, 1, 3], [2, 3, 1]] + sage: G.lex_DOWN(initial_vertex=2) in correct_anwsers + True Different orderings for different traversals:: @@ -944,9 +956,9 @@ def lex_DOWN(G, reverse=False, tree=False, initial_vertex=None): if initial_vertex is not None and initial_vertex not in G: raise ValueError("'{}' is not a graph vertex".format(initial_vertex)) - # Loops and multiple edges are not needed in Lex DOWN - if G.allows_loops() or G.allows_multiple_edges(): - G = G.to_simple(immutable=True) + # Convert G to a simple undirected graph + if G.has_loops() or G.has_multiple_edges() or G.is_directed(): + G = G.to_simple(immutable=True, to_undirected=True) cdef int nV = G.order() From 3b1afb1844fc985c7bb1208dcc5a5a9c417f5aec Mon Sep 17 00:00:00 2001 From: cyrilbouvier Date: Mon, 24 Jun 2024 10:49:05 +0200 Subject: [PATCH 129/231] graphs: traversals.pyx: update doc to use `` --- src/sage/graphs/traversals.pyx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/sage/graphs/traversals.pyx b/src/sage/graphs/traversals.pyx index af78c3c8572..f3fbc78cd44 100644 --- a/src/sage/graphs/traversals.pyx +++ b/src/sage/graphs/traversals.pyx @@ -267,8 +267,8 @@ def lex_BFS(G, reverse=False, tree=False, initial_vertex=None, algorithm="fast") algorithm is in `O(n + m)`, and our implementation follows that complexity. See [HMPV2000]_ and next section for more details. - Loops and multiple edges are ignored during the computation of lex_BFS and - directed graphs are converted to undirected graphs. + Loops and multiple edges are ignored during the computation of ``lex_BFS`` + and directed graphs are converted to undirected graphs. ALGORITHM: @@ -509,8 +509,8 @@ def lex_UP(G, reverse=False, tree=False, initial_vertex=None): - ``initial_vertex`` -- (default: ``None``); the first vertex to consider - Loops and multiple edges are ignored during the computation of lex_UP and - directed graphs are converted to undirected graphs. + Loops and multiple edges are ignored during the computation of ``lex_UP`` + and directed graphs are converted to undirected graphs. ALGORITHM: @@ -686,8 +686,8 @@ def lex_DFS(G, reverse=False, tree=False, initial_vertex=None): - ``initial_vertex`` -- (default: ``None``); the first vertex to consider - Loops and multiple edges are ignored during the computation of lex_DFS and - directed graphs are converted to undirected graphs. + Loops and multiple edges are ignored during the computation of ``lex_DFS`` + and directed graphs are converted to undirected graphs. ALGORITHM: @@ -863,8 +863,8 @@ def lex_DOWN(G, reverse=False, tree=False, initial_vertex=None): - ``initial_vertex`` -- (default: ``None``); the first vertex to consider - Loops and multiple edges are ignored during the computation of lex_DOWN and - directed graphs are converted to undirected graphs. + Loops and multiple edges are ignored during the computation of ``lex_DOWN`` + and directed graphs are converted to undirected graphs. ALGORITHM: From 2a0874e8fc6df8dce06e97a359b2e1ec31899d57 Mon Sep 17 00:00:00 2001 From: Sebastian Oehms <47305845+soehms@users.noreply.github.com> Date: Mon, 24 Jun 2024 19:58:35 +0200 Subject: [PATCH 130/231] 37395: Adjust doctests of Mathics interface (#45) --- src/sage/interfaces/mathics.py | 32 +++++++++++--------------------- 1 file changed, 11 insertions(+), 21 deletions(-) diff --git a/src/sage/interfaces/mathics.py b/src/sage/interfaces/mathics.py index 24b564f8f6a..473bb9dae71 100644 --- a/src/sage/interfaces/mathics.py +++ b/src/sage/interfaces/mathics.py @@ -341,7 +341,7 @@ :: sage: mathics('10.^80') # optional - mathics - 1.*^80 + 1.×10^80 sage: mathics('10.^80').sage() # optional - mathics 1.00000000000000e80 @@ -483,6 +483,7 @@ def __init__(self, self._seed = seed self._initialized = False # done lazily self._session = None + os.environ['MATHICS_CHARACTER_ENCODING'] = 'ASCII' # see :issue:`37395` def _lazy_init(self): r""" @@ -603,7 +604,7 @@ def get(self, var): sage: mathics.set('u', '2*x +E') # optional - mathics sage: mathics.get('u') # optional - mathics - 'E + 2 x' + '2 x + E' """ return self.eval(var) @@ -719,9 +720,9 @@ def _exponent_symbol(self): sage: bignum = mathics('10.^80') # optional - mathics sage: repr(bignum) # optional - mathics - '1.*^80' + '1.×10^80' sage: repr(bignum).replace(mathics._exponent_symbol(), 'e').strip() # optional - mathics - '1.e80' + '1.×10^80' """ return '*^' @@ -774,34 +775,25 @@ def help(self, cmd, long=False): EXAMPLES:: sage: mathics.help('Sin') # optional - mathics - "\n 'Sin[z]'\n returns the sine of z.\n" + 'sine function\n' sage: print(_) # optional - mathics - - 'Sin[z]' - returns the sine of z. + sine function sage: print(mathics.help('Sin', long=True)) # optional - mathics - - 'Sin[z]' - returns the sine of z. + sine function Attributes[Sin] = {Listable, NumericFunction, Protected} sage: print(mathics.Factorial.__doc__) # optional - mathics - - 'Factorial[n]' - 'n!' - computes the factorial of n. + factorial sage: u = mathics('Pi') # optional - mathics sage: print(u.Cos.__doc__) # optional - mathics - - 'Cos[z]' - returns the cosine of z. + cosine function """ if long: @@ -854,7 +846,7 @@ class MathicsElement(ExtraTabCompletion, InterfaceElement): sage: expr = res.last_eval; expr sage: type(expr) - + Applying Mathics methods:: @@ -865,8 +857,6 @@ class MathicsElement(ExtraTabCompletion, InterfaceElement): 'System`E' sage: me.is_inexact() False - sage: me.is_symbol() - True Conversion to Sage:: From acf9c5ae4579db36119ae98508e6d26bf596bcc4 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 24 Jun 2024 12:32:06 -0700 Subject: [PATCH 131/231] src/sage/knots/{knot,knotinfo}.py: Use file-level # needs sage.groups --- src/sage/knots/knot.py | 26 ++++------------ src/sage/knots/knotinfo.py | 61 ++++++++++++++------------------------ 2 files changed, 27 insertions(+), 60 deletions(-) diff --git a/src/sage/knots/knot.py b/src/sage/knots/knot.py index c084a7679c8..97d2d737e1b 100644 --- a/src/sage/knots/knot.py +++ b/src/sage/knots/knot.py @@ -1,4 +1,4 @@ -# sage.doctest: needs sage.graphs +# sage.doctest: needs sage.graphs sage.groups r""" Knots @@ -54,7 +54,6 @@ class Knot(Link, Element, metaclass=InheritComparisonClasscallMetaclass): We construct the knot `8_{14}` and compute some invariants:: - sage: # needs sage.groups sage: B = BraidGroup(4) sage: K = Knot(B([1,1,1,2,-1,2,-3,2,-3])) @@ -67,7 +66,6 @@ class Knot(Link, Element, metaclass=InheritComparisonClasscallMetaclass): :: - sage: # needs sage.groups sage: K.alexander_polynomial() -2*t^-2 + 8*t^-1 - 11 + 8*t - 2*t^2 sage: K.jones_polynomial() @@ -91,7 +89,6 @@ def __classcall_private__(self, data, check=True): EXAMPLES:: - sage: # needs sage.groups sage: B = BraidGroup(8) sage: K = Knot(B([-1, -1, -1, 2, 1, -2, 3, -2, 3])) sage: type(K) @@ -105,7 +102,6 @@ def __init__(self, data, check=True): TESTS:: - sage: # needs sage.groups sage: B = BraidGroup(8) sage: K = Knot(B([1, -2, 1, -2])) sage: TestSuite(K).run() @@ -135,7 +131,6 @@ def _repr_(self): EXAMPLES:: - sage: # needs sage.groups sage: B = BraidGroup(8) sage: K = Knot(B([1, 2, 1, 2])) sage: K @@ -275,10 +270,9 @@ def dt_code(self): EXAMPLES:: sage: K = Knot([[1,5,2,4],[5,3,6,2],[3,1,4,6]]) - sage: K.dt_code() # needs sage.groups + sage: K.dt_code() [4, 6, 2] - sage: # needs sage.groups sage: B = BraidGroup(4) sage: K = Knot(B([1, 2, 1, 2])) sage: K.dt_code() @@ -286,7 +280,7 @@ def dt_code(self): sage: K = Knot([[[1, -2, 3, -4, 5, -1, 2, -3, 4, -5]], ....: [1, 1, 1, 1, 1]]) - sage: K.dt_code() # needs sage.groups + sage: K.dt_code() [6, 8, 10, 2, 4] """ b = self.braid().Tietze() @@ -342,7 +336,6 @@ def arf_invariant(self): EXAMPLES:: - sage: # needs sage.groups sage: B = BraidGroup(4) sage: K = Knot(B([-1, 2, 1, 2])) sage: K.arf_invariant() @@ -381,7 +374,6 @@ def colored_jones_polynomial(self, N, variab=None, try_inverse=True): EXAMPLES:: - sage: # needs sage.groups sage: W = Knots() sage: K = W.from_dowker_code([-4,-6,-2]) sage: K.colored_jones_polynomial(2) @@ -393,7 +385,7 @@ def colored_jones_polynomial(self, N, variab=None, try_inverse=True): -t^-4 - t^-3 - t^-1 sage: R. = ZZ[] - sage: K.colored_jones_polynomial(2, t+1) # needs sage.groups + sage: K.colored_jones_polynomial(2, t+1) (t^3 + 3*t^2 + 4*t + 1)/(t^4 + 4*t^3 + 6*t^2 + 4*t + 1) """ return self.braid().colored_jones_polynomial(N=N, variab=variab, @@ -418,7 +410,6 @@ def connected_sum(self, other): EXAMPLES:: - sage: # needs sage.groups sage: B = BraidGroup(2) sage: trefoil = Knot(B([1,1,1])) sage: K = trefoil.connected_sum(trefoil); K @@ -436,7 +427,6 @@ def connected_sum(self, other): :: - sage: # needs sage.groups sage: rev_trefoil = Knot(B([-1,-1,-1])) sage: K2 = trefoil.connected_sum(rev_trefoil); K2 Knot represented by 6 crossings @@ -456,7 +446,6 @@ def connected_sum(self, other): the constructing from DT-code may not be unique for non prime knots, see :meth:`from_dowker_code`):: - sage: # needs sage.groups sage: K.dowker_notation() [(4, 1), (2, 5), (6, 3), (10, 7), (8, 11), (12, 9)] sage: K2.dowker_notation() @@ -466,7 +455,6 @@ def connected_sum(self, other): TESTS:: - sage: # needs sage.groups sage: B = BraidGroup(2) sage: trivial = Knots().one() sage: trivial * trivial @@ -567,7 +555,7 @@ def from_gauss_code(self, gauss): sage: W = Knots() sage: K1 = W.from_gauss_code([2, -1, 3, -2, 1, -3]) - sage: K1.alexander_polynomial() # needs sage.groups + sage: K1.alexander_polynomial() t^-1 - 1 + t """ orientations = recover_orientations(gauss)[3] @@ -653,13 +641,11 @@ def from_table(self, n, k): EXAMPLES:: - sage: # needs sage.groups sage: K1 = Knots().from_table(6,3); K1 Knot represented by 6 crossings sage: K1.alexander_polynomial() t^-2 - 3*t^-1 + 5 - 3*t + t^2 - sage: # needs sage.groups sage: K2 = Knots().from_table(8,4); K2 Knot represented by 9 crossings sage: K2.determinant() @@ -667,14 +653,12 @@ def from_table(self, n, k): sage: K2.signature() 2 - sage: # needs sage.groups sage: K3 = Knots().from_table(10,56); K3 Knot represented by 11 crossings sage: K3.jones_polynomial() t^10 - 3*t^9 + 6*t^8 - 9*t^7 + 10*t^6 - 11*t^5 + 10*t^4 - 7*t^3 + 5*t^2 - 2*t + 1 - sage: # needs sage.groups sage: K4 = Knots().from_table(10,100) sage: K4.genus() 4 diff --git a/src/sage/knots/knotinfo.py b/src/sage/knots/knotinfo.py index 0bd572223e3..6bc9c3a09cf 100644 --- a/src/sage/knots/knotinfo.py +++ b/src/sage/knots/knotinfo.py @@ -1,4 +1,4 @@ -# sage.doctest: needs sage.graphs +# sage.doctest: needs sage.graphs sage.groups r""" Access to the KnotInfo database @@ -82,9 +82,9 @@ Obtaining an instance of :class:`~sage.groups.braid.Braid`:: - sage: L.braid() # needs sage.groups + sage: L.braid() s1^-2*s0^-1*s1*s0^-1 - sage: type(_) # needs sage.groups + sage: type(_) Obtaining an instance of :class:`Link`:: @@ -128,9 +128,9 @@ Obtaining the HOMFLY-PT polynomial:: - sage: L.homfly_polynomial() # needs sage.groups + sage: L.homfly_polynomial() -v^-1*z - v^-3*z - v^-3*z^-1 + v^-5*z^-1 - sage: _ == l.homfly_polynomial(normalization='vz') # needs sage.groups + sage: _ == l.homfly_polynomial(normalization='vz') True @@ -505,7 +505,7 @@ def _braid_group(self): EXAMPLES:: sage: L = KnotInfo.L4a1_0 - sage: L._braid_group() # needs sage.groups + sage: L._braid_group() Braid group on 3 strands """ try: @@ -528,7 +528,7 @@ def _homfly_pol_ring(self, var1, var2): EXAMPLES:: sage: L = KnotInfo.L4a1_1 - sage: L._homfly_pol_ring('u', 'v') # needs sage.groups + sage: L._homfly_pol_ring('u', 'v') Multivariate Laurent Polynomial Ring in u, v over Integer Ring """ K3_1 = Knots().from_table(3,1) @@ -778,7 +778,7 @@ def braid(self): EXAMPLES:: sage: K = KnotInfo.K3_1 - sage: K.braid() # needs sage.groups + sage: K.braid() s^3 sage: K.braid_notation() (1, 1, 1) @@ -818,7 +818,7 @@ def crossing_number(self): 4 sage: KnotInfo.K3_1.crossing_number() 3 - sage: Link(KnotInfo.L4a1_0.braid()) # needs sage.groups + sage: Link(KnotInfo.L4a1_0.braid()) Link with 2 components represented by 5 crossings """ return knotinfo_int(self[self.items.crossing_number]) @@ -879,7 +879,7 @@ def three_genus(self): since the latter is obtained for a Seifert surface that does not have the minimal genus:: - sage: KnotInfo.K5_2.link().genus() # needs sage.groups + sage: KnotInfo.K5_2.link().genus() 3 """ return knotinfo_int(self[self.items.three_genus]) @@ -1048,7 +1048,7 @@ def is_amphicheiral(self, positive=False): True sage: Kn.is_amphicheiral(positive=True) False - sage: KnotInfo.L4a1_0.is_amphicheiral() # needs sage.groups + sage: KnotInfo.L4a1_0.is_amphicheiral() False sage: KnotInfo.L10n59_1.is_amphicheiral() True @@ -1264,7 +1264,6 @@ def homfly_polynomial(self, var1='v', var2='z', original=False): EXAMPLES:: - sage: # needs sage.groups sage: K3_1 = KnotInfo.K3_1 sage: PK3_1 = K3_1.homfly_polynomial(); PK3_1 -v^4 + v^2*z^2 + 2*v^2 @@ -1275,7 +1274,6 @@ def homfly_polynomial(self, var1='v', var2='z', original=False): for proper links:: - sage: # needs sage.groups sage: L4a1_1 = KnotInfo.L4a1_1 sage: PL4a1_1 = L4a1_1.homfly_polynomial(var1='x', var2='y'); PL4a1_1 -x^5*y + x^3*y^3 - x^5*y^-1 + 3*x^3*y + x^3*y^-1 @@ -1285,7 +1283,6 @@ def homfly_polynomial(self, var1='v', var2='z', original=False): check the skein-relation from the KnotInfo description page (applied to one of the positive crossings of the right-handed trefoil):: - sage: # needs sage.groups sage: R = PK3_1.parent() sage: PO = R.one() sage: L2a1_1 = KnotInfo.L2a1_1 @@ -1296,7 +1293,6 @@ def homfly_polynomial(self, var1='v', var2='z', original=False): TESTS:: - sage: # needs sage.groups sage: H = KnotInfo.L11n459_1_1_1.homfly_polynomial() # optional - database_knotinfo sage: all(L.homfly_polynomial() == L.link().homfly_polynomial(normalization='vz')\ for L in KnotInfo if L.crossing_number() < 7) @@ -1368,7 +1364,6 @@ def kauffman_polynomial(self, var1='a', var2='z', original=False): sage: L = KnotInfo.L2a1_1 sage: K = KnotInfo.K4_1 - sage: # needs sage.modules sage: L.kauffman_polynomial() a^-1*z - a^-1*z^-1 + a^-2 + a^-3*z - a^-3*z^-1 sage: K.kauffman_polynomial() @@ -1386,7 +1381,6 @@ def kauffman_polynomial(self, var1='a', var2='z', original=False): Check the skein relation:: - sage: # needs sage.modules sage: K3_1 = KnotInfo.K3_1 sage: FK3_1 = K3_1.kauffman_polynomial() sage: FL2a1_1 = L.kauffman_polynomial() @@ -1659,11 +1653,11 @@ def alexander_polynomial(self, var='t', original=False, laurent_poly=False): Comparison with Sage's results:: sage: k = K.link() - sage: ka = k.alexander_polynomial(); ka # needs sage.groups + sage: ka = k.alexander_polynomial(); ka -t^-1 + 3 - t - sage: K.alexander_polynomial(laurent_poly=True) # needs sage.groups + sage: K.alexander_polynomial(laurent_poly=True) t^-1 - 3 + t - sage: _ == -ka # needs sage.groups + sage: _ == -ka True Launch the KnotInfo description web-page:: @@ -1736,9 +1730,9 @@ def conway_polynomial(self, var='t', original=False): Comparison to Sage's results:: - sage: Kc == K.link().conway_polynomial() # needs sage.groups + sage: Kc == K.link().conway_polynomial() True - sage: Lc == L.link().conway_polynomial() # needs sage.groups + sage: Lc == L.link().conway_polynomial() True Launch the KnotInfo description web-page:: @@ -1800,7 +1794,6 @@ def khovanov_polynomial(self, var1='q', var2='t', base_ring=ZZ, original=False, EXAMPLES:: - sage: # needs sage.modules sage: K = KnotInfo.K6_3 sage: Kk = K.khovanov_polynomial(); Kk q^7*t^3 + q^5*t^2 + q^3*t^2 + q^3*t + q*t + 2*q + 2*q^-1 + q^-1*t^-1 @@ -1808,7 +1801,6 @@ def khovanov_polynomial(self, var1='q', var2='t', base_ring=ZZ, original=False, sage: Kk2 = K.khovanov_polynomial(var1='p', base_ring=GF(2)); Kk2 p^7*t^3 + p^5*t^3 + p^5*t^2 + p^3*t + p^-1 + p^-1*t^-1 + p^-3*t^-2 + p^-7*t^-3 - sage: # needs sage.modules sage: L = KnotInfo.L5a1_0 sage: Lk = L.khovanov_polynomial(); Lk q^4*t^2 + t + 2 + 2*q^-2 + q^-2*t^-1 + q^-4*t^-2 + q^-6*t^-2 + q^-8*t^-3 @@ -1817,7 +1809,6 @@ def khovanov_polynomial(self, var1='q', var2='t', base_ring=ZZ, original=False, Obtaining the reduced homology (for knots only):: - sage: # needs sage.modules sage: Kkr = K.khovanov_polynomial(reduced=True); Kkr q^6*t^3 + 2*q^4*t^2 + 2*q^2*t + 3 + 2*q^-2*t^-1 + 2*q^-4*t^-2 + q^-6*t^-3 sage: K.khovanov_polynomial(base_ring=QQ, reduced=True) == Kkr @@ -1831,7 +1822,6 @@ def khovanov_polynomial(self, var1='q', var2='t', base_ring=ZZ, original=False, Obtaining the odd Khovanov homology (for knots only):: - sage: # needs sage.modules sage: K.khovanov_polynomial(odd=True) == Kkr True sage: K.khovanov_polynomial(base_ring=QQ, odd=True) == Kkr @@ -1846,7 +1836,6 @@ def khovanov_polynomial(self, var1='q', var2='t', base_ring=ZZ, original=False, Comparison to Sage's results:: - sage: # needs sage.modules sage: Kk == K.link().khovanov_polynomial() True sage: Kk2 == K.link().khovanov_polynomial(var1='p', base_ring=GF(2)) @@ -1856,7 +1845,6 @@ def khovanov_polynomial(self, var1='q', var2='t', base_ring=ZZ, original=False, TESTS:: - sage: # needs sage.modules sage: KnotInfo.K0_1.inject() Defining K0_1 sage: K0_1.khovanov_polynomial() @@ -2003,16 +1991,16 @@ def link(self, use_item=db.columns().pd_notation, snappy=False): sage: K = KnotInfo.K3_1 sage: K.link() Knot represented by 3 crossings - sage: _.braid() # needs sage.groups + sage: _.braid() s^3 - sage: _ == K.braid() # needs sage.groups + sage: _ == K.braid() True using ``dt_notation``:: sage: K.link(use_item=K.items.dt_notation) Knot represented by 3 crossings - sage: _.braid() # needs sage.groups + sage: _.braid() s^3 sage: L = KnotInfo.L4a1_0 @@ -2047,16 +2035,16 @@ def link(self, use_item=db.columns().pd_notation, snappy=False): using ``braid_notation``:: - sage: L2.link(use_item=L.items.braid_notation) == l2 # needs sage.groups + sage: L2.link(use_item=L.items.braid_notation) == l2 True observe:: - sage: L.link(use_item=L.items.braid_notation) # needs sage.groups + sage: L.link(use_item=L.items.braid_notation) Link with 2 components represented by 5 crossings sage: K6_1 = KnotInfo.K6_1 - sage: K6_1.link().braid() == K6_1.braid() # needs sage.groups + sage: K6_1.link().braid() == K6_1.braid() False also observe:: @@ -2067,7 +2055,6 @@ def link(self, use_item=db.columns().pd_notation, snappy=False): sage: K4_1.pd_notation() [[4, 2, 5, 1], [8, 6, 1, 5], [6, 3, 7, 4], [2, 7, 3, 8]] - sage: # needs sage.groups sage: K5_1 = KnotInfo.K5_1 sage: K5_1.link().braid() s^5 @@ -2118,7 +2105,6 @@ def is_unique(self): EXAMPLES:: - sage: # needs sage.groups sage: KnotInfo.L4a1_0.is_unique() True sage: KnotInfo.L5a1_0.is_unique() @@ -2172,7 +2158,6 @@ def is_recoverable(self, unique=True): EXAMPLES:: - sage: # needs sage.groups sage: KnotInfo.L4a1_0.inject() Defining L4a1_0 sage: L4a1_0.is_recoverable() @@ -2679,7 +2664,6 @@ def is_recoverable(self, unique=True, max_samples=8): EXAMPLES:: - sage: # needs sage.groups sage: KnotInfo.L4a1_0.series().inject() Defining L4a sage: L4a.is_recoverable() @@ -2708,7 +2692,6 @@ def _test_recover(self, **options): EXAMPLES:: - sage: # needs sage.groups sage: TestSuite(KnotInfo.L5a1_0.series()).run(verbose=True) # indirect doctest running ._test_category() . . . pass running ._test_new() . . . pass From b79fd73fd4ca22c0cd9c091249f425a6658006fd Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 18 Dec 2023 18:58:03 -0800 Subject: [PATCH 132/231] build/bin/sage-spkg: Use sage-package --- build/bin/sage-spkg | 85 +++++++++++++++++++++------------------------ 1 file changed, 40 insertions(+), 45 deletions(-) diff --git a/build/bin/sage-spkg b/build/bin/sage-spkg index 790dbbeb232..e5d507b137e 100755 --- a/build/bin/sage-spkg +++ b/build/bin/sage-spkg @@ -149,14 +149,6 @@ exit_with_error_msg() exit 1 } -lookup_param() -{ - local param=$1 - local file=$2 - # Ignore errors if the file does not exist - sed -n "s/^${param} *= *//p" $file 2>/dev/null -} - write_to_tty() { # Try writing to terminal. Suppress the possible error message @@ -321,9 +313,11 @@ export SAGE_SPKG_WHEELS="$SAGE_INST_LOCAL/var/lib/sage/wheels" # VERSION, if provided, must match the version in build/pkgs. PKG_VER="${PKG_NAME#${PKG_BASE}}" PKG_VER="${PKG_VER#-}" -PKG_SCRIPTS="$SAGE_ROOT/build/pkgs/$PKG_BASE" -LOCAL_PKG_VER=`cat $PKG_SCRIPTS/package-version.txt 2>/dev/null || echo none` -PKG_VER="$LOCAL_PKG_VER" +eval $(sage-package properties $PKG_BASE) +eval PKG_SCRIPTS=\$path_$PKG_BASE \ + PKG_TYPE=\$type_$PKG_BASE \ + PKG_SRC_TYPE=\$source_$PKG_BASE \ + LOCAL_PKG_VER=\$version_with_patchlevel_$PKG_BASE if [ -n "$PKG_VER" -a "$PKG_VER" != "$LOCAL_PKG_VER" ]; then echo >&2 "Error: Selecting a different version of a package is no longer supported" exit 1 @@ -333,11 +327,6 @@ if [ -z "$PKG_VER" ]; then else PKG_NAME="${PKG_BASE}-${PKG_VER}" fi -PKG_BASE_VER=`echo $PKG_VER | sed 's/\.p[0-9][0-9]*$//'` -if [ -f "$PKG_SCRIPTS/checksums.ini" ]; then - # Normal/wheel package - PKG_NAME_UPSTREAM=`lookup_param tarball "$PKG_SCRIPTS/checksums.ini"` -fi # Set the $SAGE_DESTDIR variable to be passed to the spkg-install # script (the script itself could set this, but better to standardize @@ -356,20 +345,20 @@ WRAPPED_SCRIPTS="build install preinst pipinst postinst $INSTALLED_SCRIPTS" warning_for_experimental_packages() { ############################ -if [ x`cat "$PKG_SCRIPTS/type"` = x"experimental" ]; then - if [ $YES != 1 -a -n "$PKG_NAME_UPSTREAM" ]; then +case "$PKG_TYPE:$PKG_SRC_TYPE" in + experimental:normal|experimental:wheel) + if [ $YES != 1 ]; then echo "Error: The package $PKG_NAME is marked as experimental." echo "Use 'sage -i -y $PKG_BASE' to force installation of this package" echo "or use the configure option --enable-experimental-packages" exit 1 - fi -fi + fi;; +esac } ############################## warning_for_experimental_packages ensure_pkg_src() { ############################################### -if [ ! -f "$PKG_SRC" ]; then - if [ -n "$PKG_NAME_UPSTREAM" ]; then - # Normal or wheel package +case "$PKG_SRC_TYPE" in + normal|wheel) PKG_SRC=$(sage-package download $SAGE_DOWNLOAD_FILE_OPTIONS $PKG_BASE) || exit_with_error_msg "Error downloading tarball of $PKG_BASE" # Do a final check that PKG_SRC is a file with an absolute path cd / @@ -378,21 +367,21 @@ if [ ! -f "$PKG_SRC" ]; then echo >&2 "This shouldn't happen, it is a bug in the sage-spkg script." exit 1 fi - fi -fi - -# Go back to SAGE_ROOT where we have less chance of completely messing -# up the system if we do something wrong. -cd "$SAGE_ROOT" || exit $? -# If SAGE_SPKG_COPY_UPSTREAM is set, it should be the name of a directory -# to which all upstream files are copied. This is used in sage-sdist. -if [ -n "$SAGE_SPKG_COPY_UPSTREAM" -a -n "$PKG_NAME_UPSTREAM" ]; then - mkdir -p "$SAGE_SPKG_COPY_UPSTREAM" && cp -p "$PKG_SRC" "$SAGE_SPKG_COPY_UPSTREAM" - if [ $? -ne 0 ]; then - exit_with_error_msg "Error copying upstream tarball to directory '$SAGE_SPKG_COPY_UPSTREAM'" - fi -fi + # Go back to SAGE_ROOT where we have less chance of completely messing + # up the system if we do something wrong. + cd "$SAGE_ROOT" || exit $? + + # If SAGE_SPKG_COPY_UPSTREAM is set, it should be the name of a directory + # to which all upstream files are copied. This is used in sage-sdist. + if [ -n "$SAGE_SPKG_COPY_UPSTREAM" ]; then + mkdir -p "$SAGE_SPKG_COPY_UPSTREAM" && cp -p "$PKG_SRC" "$SAGE_SPKG_COPY_UPSTREAM" + if [ $? -ne 0 ]; then + error_msg "Error copying upstream tarball to directory '$SAGE_SPKG_COPY_UPSTREAM'" + exit 1 + fi + fi;; +esac } ################################################# ensure_pkg_src setup_directories() { ############################################ @@ -438,8 +427,8 @@ extract_the_package() { ########################################## cd "$SAGE_BUILD_DIR" || exit $? echo "Setting up build directory $SAGE_BUILD_DIR/$PKG_NAME" -if [ -z "$PKG_NAME_UPSTREAM" ]; then - # Not a normal or wheel package. +case "$PKG_SRC_TYPE" in + script) # Transplant the 'src' symlink, copy scripts. mkdir -p "$PKG_NAME" if [ -d "$PKG_SCRIPTS"/src ]; then @@ -453,8 +442,9 @@ if [ -z "$PKG_NAME_UPSTREAM" ]; then fi done cd "$PKG_NAME" || exit $? -else - # Normal or wheel package, copy whole directory, resolving symlinks + ;; + normal|wheel) + # Copy whole directory, resolving symlinks cp -RLp "$PKG_SCRIPTS" "$PKG_NAME" cd "$PKG_NAME" || exit $? case "$PKG_SRC" in @@ -476,7 +466,11 @@ else cd .. ;; esac -fi + ;; + *) + error_msg "Unhandled source type $PKG_SRC_TYPE" + ;; +esac if [ "$SAGE_KEEP_BUILT_SPKGS" = "yes" ]; then touch .keep fi @@ -604,13 +598,14 @@ esac # Poison the proxy variable to forbid downloads in spkg-install # for normal packages -if [ -n "$PKG_NAME_UPSTREAM" ]; then - # Normal/wheel package +case $PKG_SRC_TYPE in + normal|wheel) export http_proxy=http://192.0.2.0:5187/ export https_proxy=$http_proxy export ftp_proxy=$http_proxy export rsync_proxy=$http_proxy -fi + ;; +esac # Make sage-logger show the full logs unset SAGE_SILENT_BUILD From 8d6f11a1a5f718a0dc32dd58a464d74e95ab01c8 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 18 Dec 2023 20:33:08 -0800 Subject: [PATCH 133/231] build/bin/sage-spkg: Move handling of dummy packages here from build/make/Makefile.in --- build/bin/sage-spkg | 18 +++++++++++++++++- build/make/Makefile.in | 15 +-------------- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/build/bin/sage-spkg b/build/bin/sage-spkg index e5d507b137e..d4d5981b27f 100755 --- a/build/bin/sage-spkg +++ b/build/bin/sage-spkg @@ -380,7 +380,23 @@ case "$PKG_SRC_TYPE" in error_msg "Error copying upstream tarball to directory '$SAGE_SPKG_COPY_UPSTREAM'" exit 1 fi - fi;; + fi + ;; + none) + echo >&2 + echo >&2 "Note: $PKG_BASE is a dummy package that the Sage distribution uses" + echo >&2 "to provide information about equivalent system packages." + echo >&2 "It cannot be installed using the Sage distribution." + echo >&2 "Please install it manually, for example using the system packages" + echo >&2 "recommended at the end of a run of './configure'" + echo >&2 "See below for package-specific information." + echo >&2 + sage-spkg-info $PKG_BASE + echo >&2 + echo >&2 "Error: $PKG_BASE is a dummy package and " + echo >&2 "cannot be installed using the Sage distribution." + exit 1 + ;; esac } ################################################# ensure_pkg_src diff --git a/build/make/Makefile.in b/build/make/Makefile.in index 7a13e5a9e23..e6982a473b3 100644 --- a/build/make/Makefile.in +++ b/build/make/Makefile.in @@ -741,7 +741,7 @@ $(1)-$(4)-no-deps: echo "Error: The installation tree $(4) has been disabled" 2>&1; \ echo "$$($(4)_DISABLED_MESSAGE)" 2>&1; \ exit 1; \ - elif [ -x '$$(SAGE_ROOT)/build/pkgs/$(1)/spkg-install' -o -r '$$(SAGE_ROOT)/build/pkgs/$(1)/spkg-install.in' ]; then \ + else \ rm -rf '$$($(4))/var/lib/sage/scripts/$(1)'; \ cd '$$(SAGE_ROOT)/build/pkgs/$(1)' && \ . '$$(SAGE_ROOT)/src/bin/sage-src-env-config' && \ @@ -759,19 +759,6 @@ $(1)-$(4)-no-deps: sage-logger -p 'SAGE_CHECK=$$(SAGE_CHECK_$(1)) PATH=$$(SAGE_SRC)/bin:$$($(4))/bin:$$$$PATH $$(SAGE_SPKG) $$(SAGE_SPKG_OPTIONS) \ $(if $(filter $(1),$(TOOLCHAIN_DEPS)),--keep-existing) \ $(1)-$(2) $$($(4))' '$$(SAGE_LOGS)/$(1)-$(2).log'; \ - else ( \ - echo; \ - echo "Note: $(1) is a dummy package that the Sage distribution uses"; \ - echo "to provide information about equivalent system packages."; \ - echo "It cannot be installed using the Sage distribution."; \ - echo "Please install it manually, for example using the system packages"; \ - echo "recommended at the end of a run of './configure'"; \ - echo "See below for package-specific information."; \ - echo; \ - $$(SAGE_ROOT)/build/bin/sage-spkg-info $(1); \ - echo; \ - echo "Error: $(1) is a dummy package and "; \ - echo "cannot be installed using the Sage distribution." ) | sage-logger -p 'cat; exit 1' '$$(SAGE_LOGS)/$(1)-$(2).log'; \ fi $(1)-no-deps: $(1)-$(4)-no-deps From 1a97f3c90b323e3f80db11cd0c5044de6b506ee1 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 24 Jun 2024 15:52:43 -0700 Subject: [PATCH 134/231] build/bin/sage-spkg: Update use of 'sage -package properties' --- build/bin/sage-spkg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/bin/sage-spkg b/build/bin/sage-spkg index d4d5981b27f..4465fc905bf 100755 --- a/build/bin/sage-spkg +++ b/build/bin/sage-spkg @@ -313,7 +313,7 @@ export SAGE_SPKG_WHEELS="$SAGE_INST_LOCAL/var/lib/sage/wheels" # VERSION, if provided, must match the version in build/pkgs. PKG_VER="${PKG_NAME#${PKG_BASE}}" PKG_VER="${PKG_VER#-}" -eval $(sage-package properties $PKG_BASE) +eval $(sage-package properties --format=shell $PKG_BASE) eval PKG_SCRIPTS=\$path_$PKG_BASE \ PKG_TYPE=\$type_$PKG_BASE \ PKG_SRC_TYPE=\$source_$PKG_BASE \ From 8f73ee373b5bd7e7b577b65e9a546dbf539780e7 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 24 Jun 2024 16:00:25 -0700 Subject: [PATCH 135/231] build/bin/sage-spkg (write_to_tty): Remove unused function --- build/bin/sage-spkg | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/build/bin/sage-spkg b/build/bin/sage-spkg index 4465fc905bf..2f3ab3d88e7 100755 --- a/build/bin/sage-spkg +++ b/build/bin/sage-spkg @@ -149,16 +149,6 @@ exit_with_error_msg() exit 1 } -write_to_tty() -{ - # Try writing to terminal. Suppress the possible error message - if ! ( cat > /dev/tty ) 2> /dev/null ; then - # Fall back to writing to stdout - cat - return 1 - fi -} - # Handle -n, -t, -q options for recursive make # See Issue #12016. if echo "$MAKE $MAKEFLAGS -$MAKEFLAGS" |grep '[ ]-[A-Za-z]*[qnt]' >/dev/null; then From 1b8cc6fe0d2e35f5c5bc6be8269922c32450bb84 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 24 Jun 2024 16:46:39 -0700 Subject: [PATCH 136/231] build/bin/sage-spkg: Export PKG_BASE, PKG_NAME, PKG_VER for use in unwrapped scripts; do not set in Makefile.in --- build/bin/sage-spkg | 8 ++++---- build/make/Makefile.in | 6 ------ 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/build/bin/sage-spkg b/build/bin/sage-spkg index 2f3ab3d88e7..6af5214c27f 100755 --- a/build/bin/sage-spkg +++ b/build/bin/sage-spkg @@ -275,7 +275,7 @@ if echo "$PKG_SRC" | grep / >/dev/null; then exit 1 fi PKG_NAME="$PKG_SRC" -PKG_BASE=`echo "$PKG_NAME" | sed 's/-.*//'` # strip version number +export PKG_BASE=`echo "$PKG_NAME" | sed 's/-.*//'` # strip version number case $# in 1) @@ -302,7 +302,7 @@ export SAGE_SPKG_WHEELS="$SAGE_INST_LOCAL/var/lib/sage/wheels" # PKG_SRC should look like "package-VERSION" or just "package". # VERSION, if provided, must match the version in build/pkgs. PKG_VER="${PKG_NAME#${PKG_BASE}}" -PKG_VER="${PKG_VER#-}" +export PKG_VER="${PKG_VER#-}" eval $(sage-package properties --format=shell $PKG_BASE) eval PKG_SCRIPTS=\$path_$PKG_BASE \ PKG_TYPE=\$type_$PKG_BASE \ @@ -313,9 +313,9 @@ if [ -n "$PKG_VER" -a "$PKG_VER" != "$LOCAL_PKG_VER" ]; then exit 1 fi if [ -z "$PKG_VER" ]; then - PKG_NAME="${PKG_BASE}" + export PKG_NAME="${PKG_BASE}" else - PKG_NAME="${PKG_BASE}-${PKG_VER}" + export PKG_NAME="${PKG_BASE}-${PKG_VER}" fi # Set the $SAGE_DESTDIR variable to be passed to the spkg-install diff --git a/build/make/Makefile.in b/build/make/Makefile.in index e6982a473b3..a59c81db529 100644 --- a/build/make/Makefile.in +++ b/build/make/Makefile.in @@ -749,12 +749,6 @@ $(1)-$(4)-no-deps: . '$$(SAGE_ROOT)/src/bin/sage-env' && \ . '$$(SAGE_ROOT)/build/bin/sage-build-env-config' && \ . '$$(SAGE_ROOT)/build/bin/sage-build-env' && \ - PKG_BASE="$(1)" \ - PKG_VER="$(2)" \ - PKG_NAME="$(1)-$(2)" \ - SAGE_SPKG_WHEELS=$$($(4))/var/lib/sage/wheels \ - SAGE_SPKG_SCRIPTS=$$($(4))/var/lib/sage/scripts \ - SAGE_INST_LOCAL=$$($(4)) \ SAGE_CHECK=$$(SAGE_CHECK_$(1)) \ sage-logger -p 'SAGE_CHECK=$$(SAGE_CHECK_$(1)) PATH=$$(SAGE_SRC)/bin:$$($(4))/bin:$$$$PATH $$(SAGE_SPKG) $$(SAGE_SPKG_OPTIONS) \ $(if $(filter $(1),$(TOOLCHAIN_DEPS)),--keep-existing) \ From 9d56b35676c9fc6140361dfbb6621ab70a2f863f Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 24 Jun 2024 17:04:59 -0700 Subject: [PATCH 137/231] build/pkgs/python3/spkg-install.in: Remove unnecessary use of PKG_BASE --- build/pkgs/python3/spkg-install.in | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/build/pkgs/python3/spkg-install.in b/build/pkgs/python3/spkg-install.in index caf91d20c6d..2b2844ea02f 100644 --- a/build/pkgs/python3/spkg-install.in +++ b/build/pkgs/python3/spkg-install.in @@ -20,11 +20,7 @@ cd src sdh_make_install -i -j1 echo "Installing valgrind suppression file..." -if [ "$PKG_BASE" = "python2" ]; then - SUPP_FILENAME="python.supp" -else - SUPP_FILENAME="${PKG_BASE}.supp" -fi +SUPP_FILENAME="python3.supp" sdh_install -T Misc/valgrind-python.supp "$SAGE_LOCAL/lib/valgrind/$SUPP_FILENAME" if [ "$UNAME" = "Linux" ]; then @@ -42,14 +38,9 @@ else fi PYTHON_VERSION=$($PYTHON -c 'import sys; print("%d.%d" % sys.version_info[:2])') -if [ "$PKG_BASE" = "python2" ]; then - PYTHON_LDVERSION="$PYTHON_VERSION" - PYTHON_CONFIG_DIR="$SAGE_LOCAL/lib/python${PYTHON_VERSION}/config" -else - PYTHON_ABIFLAGS=$($PYTHON -c 'import sys; print(sys.abiflags)') - PYTHON_LDVERSION="$PYTHON_VERSION$PYTHON_ABIFLAGS" - PYTHON_CONFIG_DIR="$SAGE_LOCAL/lib/python${PYTHON_VERSION}/config-${PYTHON_LDVERSION}" -fi +PYTHON_ABIFLAGS=$($PYTHON -c 'import sys; print(sys.abiflags)') +PYTHON_LDVERSION="$PYTHON_VERSION$PYTHON_ABIFLAGS" +PYTHON_CONFIG_DIR="$SAGE_LOCAL/lib/python${PYTHON_VERSION}/config-${PYTHON_LDVERSION}" # On OS X with XCode 4, the presence of # $SAGE_LOCAL/lib/python3.x/config/libpython3.x.a causes problems with From 7de3be54ce4142a42d256b48ce933292145e8a10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antoine=20Leudi=C3=A8re?= Date: Tue, 25 Jun 2024 23:11:01 +0200 Subject: [PATCH 138/231] Delete _check_rank_two method (again!) --- .../drinfeld_modules/drinfeld_module.py | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/sage/rings/function_field/drinfeld_modules/drinfeld_module.py b/src/sage/rings/function_field/drinfeld_modules/drinfeld_module.py index 52ab9bf2626..08fb31ae941 100644 --- a/src/sage/rings/function_field/drinfeld_modules/drinfeld_module.py +++ b/src/sage/rings/function_field/drinfeld_modules/drinfeld_module.py @@ -759,18 +759,6 @@ def _Hom_(self, other, category): from sage.rings.function_field.drinfeld_modules.homset import DrinfeldModuleHomset return DrinfeldModuleHomset(self, other, category) - def _check_rank_two(self): - r""" - Raise ``NotImplementedError`` if the rank is not two. - - Do not use this method, it will be removed. - """ - from sage.misc.superseded import deprecation - deprecation(38199, "This semi-private method should not be used. " - "It will be removed.") - if self.rank() != 2: - raise NotImplementedError('rank must be 2') - def _latex_(self): r""" Return a LaTeX representation of the Drinfeld module. From acee36245d7f3b894d8fad777ed4836d97dc4e19 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 25 Jun 2024 17:17:41 -0700 Subject: [PATCH 139/231] for a in "CLASS='Divisor|ToricDivisor';SUFFIX=_generic" "CLASS='ChowCycle|CohomologyClass';SUFFIX=" ; do eval "$a"; git --no-pager grep -l -E 'is_('$CLASS')' src/sage | xargs sed -E -i.bak 's/import is_('$CLASS')/import \1'$SUFFIX'/;/^ +/s/is_('$CLASS')[(]([^()]*([(][^()]*[)])?[^()]*)[)]/isinstance(\2, \1'$SUFFIX')/g'; done --- src/sage/schemes/generic/divisor.py | 6 +++--- src/sage/schemes/generic/divisor_group.py | 2 +- src/sage/schemes/toric/chow_group.py | 14 +++++++------- src/sage/schemes/toric/divisor.py | 10 +++++----- src/sage/schemes/toric/morphism.py | 12 ++++++------ src/sage/schemes/toric/variety.py | 6 +++--- 6 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/sage/schemes/generic/divisor.py b/src/sage/schemes/generic/divisor.py index d46b8caff0e..34e840c0b94 100644 --- a/src/sage/schemes/generic/divisor.py +++ b/src/sage/schemes/generic/divisor.py @@ -107,12 +107,12 @@ def is_Divisor(x): EXAMPLES:: - sage: from sage.schemes.generic.divisor import is_Divisor + sage: from sage.schemes.generic.divisor import Divisor_generic sage: x,y = AffineSpace(2, GF(5), names='xy').gens() sage: C = Curve(y^2 - x^9 - x) - sage: is_Divisor(C.divisor([])) + sage: isinstance(C.divisor([]), Divisor_generic) True - sage: is_Divisor("Ceci n'est pas un diviseur") + sage: isinstance("Ceci n'est pas un diviseur", Divisor_generic) False """ return isinstance(x, Divisor_generic) diff --git a/src/sage/schemes/generic/divisor_group.py b/src/sage/schemes/generic/divisor_group.py index d6a19f49d60..bd2f57d4ab0 100644 --- a/src/sage/schemes/generic/divisor_group.py +++ b/src/sage/schemes/generic/divisor_group.py @@ -72,7 +72,7 @@ def is_DivisorGroup(x): EXAMPLES:: - sage: from sage.schemes.generic.divisor_group import is_DivisorGroup, DivisorGroup + sage: from sage.schemes.generic.divisor_group import Divisor_genericGroup, DivisorGroup sage: Div = DivisorGroup(Spec(ZZ), base_ring=QQ) sage: is_DivisorGroup(Div) doctest:warning... diff --git a/src/sage/schemes/toric/chow_group.py b/src/sage/schemes/toric/chow_group.py index d11d70e135b..cd35bc8afcd 100644 --- a/src/sage/schemes/toric/chow_group.py +++ b/src/sage/schemes/toric/chow_group.py @@ -132,7 +132,7 @@ import sage.geometry.abc from sage.schemes.toric.variety import ToricVariety_field -from sage.schemes.toric.divisor import is_ToricDivisor +from sage.schemes.toric.divisor import ToricDivisor_generic class ChowCycle(FGP_Element): @@ -408,7 +408,7 @@ def intersection_with_divisor(self, divisor): (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)] """ - assert is_ToricDivisor(divisor), f'{divisor} is not a toric divisor' + assert isinstance(divisor, ToricDivisor_generic), f'{divisor} is not a toric divisor' A = self.parent() # the Chow group X = A._variety # the toric variety @@ -610,7 +610,7 @@ def __init__(self, toric_variety, base_ring, check): Chow group of 2-d CPR-Fano toric variety covered by 3 affine patches sage: isinstance(A, ChowGroup_class) True - sage: is_ChowCycle(A.an_element()) + sage: isinstance(A.an_element(), ChowCycle) True TESTS:: @@ -701,7 +701,7 @@ def _element_constructor_(self, x, check=True): if isinstance(x, sage.geometry.abc.ConvexRationalPolyhedralCone): cone = fan.embed(x) return self.element_class(self, self._cone_to_V(cone), False) - if is_ToricDivisor(x): + if isinstance(x, ToricDivisor_generic): v = sum(x.coefficient(i) * self._cone_to_V(onecone) for i, onecone in enumerate(fan(1))) return self.element_class(self, v, False) @@ -1243,11 +1243,11 @@ def is_ChowCycle(x) -> bool: sage: P2 = toric_varieties.P2() sage: A = P2.Chow_group() sage: from sage.schemes.toric.chow_group import * - sage: is_ChowCycle(A) + sage: isinstance(A, ChowCycle) False - sage: is_ChowCycle(A.an_element()) + sage: isinstance(A.an_element(), ChowCycle) True - sage: is_ChowCycle('Victoria') + sage: isinstance('Victoria', ChowCycle) False """ return isinstance(x, ChowCycle) diff --git a/src/sage/schemes/toric/divisor.py b/src/sage/schemes/toric/divisor.py index ff0373b3bef..dfa38ad2261 100644 --- a/src/sage/schemes/toric/divisor.py +++ b/src/sage/schemes/toric/divisor.py @@ -205,13 +205,13 @@ def is_ToricDivisor(x): EXAMPLES:: - sage: from sage.schemes.toric.divisor import is_ToricDivisor - sage: is_ToricDivisor(1) + sage: from sage.schemes.toric.divisor import ToricDivisor_generic + sage: isinstance(1, ToricDivisor_generic) False sage: P2 = toric_varieties.P2() sage: D = P2.divisor(0); D V(x) - sage: is_ToricDivisor(D) + sage: isinstance(D, ToricDivisor_generic) True """ return isinstance(x, ToricDivisor_generic) @@ -1817,7 +1817,7 @@ def _element_constructor_(self, x, check=True, reduce=True): sage: TDiv(TDiv.gen(0), check=True) V(x) """ - if is_ToricDivisor(x): + if isinstance(x, ToricDivisor_generic): if x.parent() is self: return x else: @@ -2012,7 +2012,7 @@ def _element_constructor_(self, x): sage: Cl(D) Divisor class [0, 0, 1, 0] """ - if is_ToricDivisor(x): + if isinstance(x, ToricDivisor_generic): x = self._projection_matrix * vector(x) if isinstance(x, Vector): x = list(x) diff --git a/src/sage/schemes/toric/morphism.py b/src/sage/schemes/toric/morphism.py index e95e071d864..c7e601ad3c3 100644 --- a/src/sage/schemes/toric/morphism.py +++ b/src/sage/schemes/toric/morphism.py @@ -755,8 +755,8 @@ def pullback_divisor(self, divisor): sage: f.pullback_divisor(D) 4*V(z0) + 2*V(z1) """ - from sage.schemes.toric.divisor import is_ToricDivisor - if not (is_ToricDivisor(divisor) and divisor.is_QQ_Cartier()): + from sage.schemes.toric.divisor import ToricDivisor_generic + if not (isinstance(divisor, ToricDivisor_generic) and divisor.is_QQ_Cartier()): raise ValueError('the divisor must be torus-invariant and QQ-Cartier') m = divisor.m(self._defining_cone) values = [] @@ -1300,8 +1300,8 @@ def pullback_divisor(self, divisor): sage: square.pullback_divisor(D) 2*V(z) """ - from sage.schemes.toric.divisor import is_ToricDivisor - if not (is_ToricDivisor(divisor) and divisor.is_QQ_Cartier()): + from sage.schemes.toric.divisor import ToricDivisor_generic + if not (isinstance(divisor, ToricDivisor_generic) and divisor.is_QQ_Cartier()): raise ValueError('the divisor must be torus-invariant and QQ-Cartier') fm = self.fan_morphism() values = [] @@ -1978,8 +1978,8 @@ def pullback_divisor(self, divisor): sage: fc.embedding_morphism().pullback_divisor(D) -V(z0) - 3*V(z1) - 3*V(z2) """ - from sage.schemes.toric.divisor import is_ToricDivisor - if not (is_ToricDivisor(divisor) and divisor.is_QQ_Cartier()): + from sage.schemes.toric.divisor import ToricDivisor_generic + if not (isinstance(divisor, ToricDivisor_generic) and divisor.is_QQ_Cartier()): raise ValueError('the divisor must be torus-invariant and QQ-Cartier') m = divisor.m(self.defining_cone()) values = [] diff --git a/src/sage/schemes/toric/variety.py b/src/sage/schemes/toric/variety.py index c1ca8351263..4e6de6471ba 100644 --- a/src/sage/schemes/toric/variety.py +++ b/src/sage/schemes/toric/variety.py @@ -3303,12 +3303,12 @@ def is_CohomologyClass(x): sage: P2 = toric_varieties.P2() sage: HH = P2.cohomology_ring() - sage: from sage.schemes.toric.variety import is_CohomologyClass - sage: is_CohomologyClass( HH.one() ) # needs sage.libs.singular + sage: from sage.schemes.toric.variety import CohomologyClass + sage: isinstance( HH.one() , CohomologyClass) # needs sage.libs.singular True sage: is_CohomologyClass( HH(P2.fan(1)[0]) ) # needs sage.libs.singular True - sage: is_CohomologyClass('z') + sage: isinstance('z', CohomologyClass) False """ return isinstance(x, CohomologyClass) From 0bdde67475cd8e086cde5accf367d8bb30f257c1 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 25 Jun 2024 17:20:34 -0700 Subject: [PATCH 140/231] Reverts --- src/sage/schemes/generic/divisor.py | 6 +++--- src/sage/schemes/toric/chow_group.py | 6 +++--- src/sage/schemes/toric/divisor.py | 6 +++--- src/sage/schemes/toric/variety.py | 6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/sage/schemes/generic/divisor.py b/src/sage/schemes/generic/divisor.py index 34e840c0b94..d46b8caff0e 100644 --- a/src/sage/schemes/generic/divisor.py +++ b/src/sage/schemes/generic/divisor.py @@ -107,12 +107,12 @@ def is_Divisor(x): EXAMPLES:: - sage: from sage.schemes.generic.divisor import Divisor_generic + sage: from sage.schemes.generic.divisor import is_Divisor sage: x,y = AffineSpace(2, GF(5), names='xy').gens() sage: C = Curve(y^2 - x^9 - x) - sage: isinstance(C.divisor([]), Divisor_generic) + sage: is_Divisor(C.divisor([])) True - sage: isinstance("Ceci n'est pas un diviseur", Divisor_generic) + sage: is_Divisor("Ceci n'est pas un diviseur") False """ return isinstance(x, Divisor_generic) diff --git a/src/sage/schemes/toric/chow_group.py b/src/sage/schemes/toric/chow_group.py index cd35bc8afcd..f3225661c10 100644 --- a/src/sage/schemes/toric/chow_group.py +++ b/src/sage/schemes/toric/chow_group.py @@ -1243,11 +1243,11 @@ def is_ChowCycle(x) -> bool: sage: P2 = toric_varieties.P2() sage: A = P2.Chow_group() sage: from sage.schemes.toric.chow_group import * - sage: isinstance(A, ChowCycle) + sage: is_ChowCycle(A) False - sage: isinstance(A.an_element(), ChowCycle) + sage: is_ChowCycle(A.an_element()) True - sage: isinstance('Victoria', ChowCycle) + sage: is_ChowCycle('Victoria') False """ return isinstance(x, ChowCycle) diff --git a/src/sage/schemes/toric/divisor.py b/src/sage/schemes/toric/divisor.py index dfa38ad2261..c66bf21a3a0 100644 --- a/src/sage/schemes/toric/divisor.py +++ b/src/sage/schemes/toric/divisor.py @@ -205,13 +205,13 @@ def is_ToricDivisor(x): EXAMPLES:: - sage: from sage.schemes.toric.divisor import ToricDivisor_generic - sage: isinstance(1, ToricDivisor_generic) + sage: from sage.schemes.toric.divisor import is_ToricDivisor + sage: is_ToricDivisor(1) False sage: P2 = toric_varieties.P2() sage: D = P2.divisor(0); D V(x) - sage: isinstance(D, ToricDivisor_generic) + sage: is_ToricDivisor(D) True """ return isinstance(x, ToricDivisor_generic) diff --git a/src/sage/schemes/toric/variety.py b/src/sage/schemes/toric/variety.py index 4e6de6471ba..c1ca8351263 100644 --- a/src/sage/schemes/toric/variety.py +++ b/src/sage/schemes/toric/variety.py @@ -3303,12 +3303,12 @@ def is_CohomologyClass(x): sage: P2 = toric_varieties.P2() sage: HH = P2.cohomology_ring() - sage: from sage.schemes.toric.variety import CohomologyClass - sage: isinstance( HH.one() , CohomologyClass) # needs sage.libs.singular + sage: from sage.schemes.toric.variety import is_CohomologyClass + sage: is_CohomologyClass( HH.one() ) # needs sage.libs.singular True sage: is_CohomologyClass( HH(P2.fan(1)[0]) ) # needs sage.libs.singular True - sage: isinstance('z', CohomologyClass) + sage: is_CohomologyClass('z') False """ return isinstance(x, CohomologyClass) From a9b2ccf70a5e92e79119321595778ca022a31ee8 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 25 Jun 2024 17:34:46 -0700 Subject: [PATCH 141/231] Deprecations --- src/sage/schemes/generic/divisor.py | 8 ++++++++ src/sage/schemes/toric/chow_group.py | 8 ++++++++ src/sage/schemes/toric/divisor.py | 8 ++++++++ src/sage/schemes/toric/variety.py | 8 ++++++++ 4 files changed, 32 insertions(+) diff --git a/src/sage/schemes/generic/divisor.py b/src/sage/schemes/generic/divisor.py index d46b8caff0e..981290dfe76 100644 --- a/src/sage/schemes/generic/divisor.py +++ b/src/sage/schemes/generic/divisor.py @@ -111,10 +111,18 @@ def is_Divisor(x): sage: x,y = AffineSpace(2, GF(5), names='xy').gens() sage: C = Curve(y^2 - x^9 - x) sage: is_Divisor(C.divisor([])) + doctest:warning... + DeprecationWarning: The function is_Divisor is deprecated; + use 'isinstance(..., Divisor_generic)' instead. + See https://github.com/sagemath/sage/issues/38277 for details. True sage: is_Divisor("Ceci n'est pas un diviseur") False """ + from sage.misc.superseded import deprecation + deprecation(38277, + "The function is_Divisor is deprecated; " + "use 'isinstance(..., Divisor_generic)' instead.") return isinstance(x, Divisor_generic) diff --git a/src/sage/schemes/toric/chow_group.py b/src/sage/schemes/toric/chow_group.py index f3225661c10..de2441eef0f 100644 --- a/src/sage/schemes/toric/chow_group.py +++ b/src/sage/schemes/toric/chow_group.py @@ -1244,10 +1244,18 @@ def is_ChowCycle(x) -> bool: sage: A = P2.Chow_group() sage: from sage.schemes.toric.chow_group import * sage: is_ChowCycle(A) + doctest:warning... + DeprecationWarning: The function is_ChowCycle is deprecated; + use 'isinstance(..., ChowCycle)' instead. + See https://github.com/sagemath/sage/issues/38277 for details. False sage: is_ChowCycle(A.an_element()) True sage: is_ChowCycle('Victoria') False """ + from sage.misc.superseded import deprecation + deprecation(38277, + "The function is_ChowCycle is deprecated; " + "use 'isinstance(..., ChowCycle)' instead.") return isinstance(x, ChowCycle) diff --git a/src/sage/schemes/toric/divisor.py b/src/sage/schemes/toric/divisor.py index c66bf21a3a0..af5efa5fc2d 100644 --- a/src/sage/schemes/toric/divisor.py +++ b/src/sage/schemes/toric/divisor.py @@ -207,6 +207,10 @@ def is_ToricDivisor(x): sage: from sage.schemes.toric.divisor import is_ToricDivisor sage: is_ToricDivisor(1) + doctest:warning... + DeprecationWarning: The function is_ToricDivisor is deprecated; + use 'isinstance(..., ToricDivisor_generic)' instead. + See https://github.com/sagemath/sage/issues/38277 for details. False sage: P2 = toric_varieties.P2() sage: D = P2.divisor(0); D @@ -214,6 +218,10 @@ def is_ToricDivisor(x): sage: is_ToricDivisor(D) True """ + from sage.misc.superseded import deprecation + deprecation(38277, + "The function is_ToricDivisor is deprecated; " + "use 'isinstance(..., ToricDivisor_generic)' instead.") return isinstance(x, ToricDivisor_generic) diff --git a/src/sage/schemes/toric/variety.py b/src/sage/schemes/toric/variety.py index c1ca8351263..0c315be0fa9 100644 --- a/src/sage/schemes/toric/variety.py +++ b/src/sage/schemes/toric/variety.py @@ -3305,12 +3305,20 @@ def is_CohomologyClass(x): sage: HH = P2.cohomology_ring() sage: from sage.schemes.toric.variety import is_CohomologyClass sage: is_CohomologyClass( HH.one() ) # needs sage.libs.singular + doctest:warning... + DeprecationWarning: The function is_CohomologyClass is deprecated; + use 'isinstance(..., CohomologyClass)' instead. + See https://github.com/sagemath/sage/issues/38277 for details. True sage: is_CohomologyClass( HH(P2.fan(1)[0]) ) # needs sage.libs.singular True sage: is_CohomologyClass('z') False """ + from sage.misc.superseded import deprecation + deprecation(38277, + "The function is_CohomologyClass is deprecated; " + "use 'isinstance(..., CohomologyClass)' instead.") return isinstance(x, CohomologyClass) From a01b099da62af9c6c4cceaac96e7c65a7447865e Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 25 Jun 2024 18:10:06 -0700 Subject: [PATCH 142/231] src/sage/schemes/generic/divisor_group.py: Revert --- src/sage/schemes/generic/divisor_group.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/schemes/generic/divisor_group.py b/src/sage/schemes/generic/divisor_group.py index bd2f57d4ab0..d6a19f49d60 100644 --- a/src/sage/schemes/generic/divisor_group.py +++ b/src/sage/schemes/generic/divisor_group.py @@ -72,7 +72,7 @@ def is_DivisorGroup(x): EXAMPLES:: - sage: from sage.schemes.generic.divisor_group import Divisor_genericGroup, DivisorGroup + sage: from sage.schemes.generic.divisor_group import is_DivisorGroup, DivisorGroup sage: Div = DivisorGroup(Spec(ZZ), base_ring=QQ) sage: is_DivisorGroup(Div) doctest:warning... From 8d0ba749cf1adafdbd42dbb7115b21f60eeae56f Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 25 Jun 2024 20:21:32 -0700 Subject: [PATCH 143/231] git --no-pager grep -l -E 'is_Infinite' src/sage | xargs sed -E -i.bak 's/import is_Infinite/import InfinityElement/;/^ +/s/is_(Infinite)[(]([^()]*([(][^()]*[)])?[^()]*)[)]/isinstance(\2, InfinityElement)/g' --- src/sage/geometry/fan_morphism.py | 4 ++-- src/sage/modular/arithgroup/arithgroup_element.pyx | 4 ++-- src/sage/rings/multi_power_series_ring_element.py | 4 ++-- src/sage/rings/power_series_ring_element.pyx | 8 ++++---- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/sage/geometry/fan_morphism.py b/src/sage/geometry/fan_morphism.py index 7ef46b80d17..5a8aef777f8 100644 --- a/src/sage/geometry/fan_morphism.py +++ b/src/sage/geometry/fan_morphism.py @@ -89,7 +89,7 @@ from sage.modules.free_module_morphism import FreeModuleMorphism from sage.rings.infinity import Infinity from sage.rings.integer_ring import ZZ -from sage.rings.infinity import is_Infinite +from sage.rings.infinity import InfinityElement from functools import reduce @@ -1458,7 +1458,7 @@ def is_surjective(self): sage: phi.is_surjective() False """ - if is_Infinite(self.index()): + if isinstance(self.index(), InfinityElement): return False # Not surjective between vector spaces. for dcones in self.codomain_fan().cones(): for sigma_p in dcones: diff --git a/src/sage/modular/arithgroup/arithgroup_element.pyx b/src/sage/modular/arithgroup/arithgroup_element.pyx index 6bcd2c58550..db914af629b 100644 --- a/src/sage/modular/arithgroup/arithgroup_element.pyx +++ b/src/sage/modular/arithgroup/arithgroup_element.pyx @@ -375,8 +375,8 @@ cdef class ArithmeticSubgroupElement(MultiplicativeGroupElement): sage: G([1, 4, 0, 1]).acton(infinity) +Infinity """ - from sage.rings.infinity import is_Infinite, infinity - if is_Infinite(z): + from sage.rings.infinity import InfinityElement, infinity + if isinstance(z, InfinityElement): if self.c() != 0: return self.a() / self.c() else: diff --git a/src/sage/rings/multi_power_series_ring_element.py b/src/sage/rings/multi_power_series_ring_element.py index 32e16def317..446bf965130 100644 --- a/src/sage/rings/multi_power_series_ring_element.py +++ b/src/sage/rings/multi_power_series_ring_element.py @@ -1956,7 +1956,7 @@ def exp(self, prec=infinity): assert (val >= 1) prec = min(prec, self.prec()) - if is_Infinite(prec): + if isinstance(prec, InfinityElement): prec = R.default_prec() n_inv_factorial = R.base_ring().one() x_pow_n = Rbg.one() @@ -2053,7 +2053,7 @@ def log(self, prec=infinity): assert (val >= 1) prec = min(prec, self.prec()) - if is_Infinite(prec): + if isinstance(prec, InfinityElement): prec = R.default_prec() x_pow_n = Rbg.one() log_x = Rbg.zero().add_bigoh(prec) diff --git a/src/sage/rings/power_series_ring_element.pyx b/src/sage/rings/power_series_ring_element.pyx index 8e1b76a7cc9..7007664501b 100644 --- a/src/sage/rings/power_series_ring_element.pyx +++ b/src/sage/rings/power_series_ring_element.pyx @@ -1901,7 +1901,7 @@ cdef class PowerSeries(AlgebraElement): assert(val >= 1) prec = min(prec, self.prec()) - if is_Infinite(prec): + if isinstance(prec, InfinityElement): prec = R.default_prec() n_inv_factorial = R.base_ring().one() x_pow_n = R.one() @@ -1987,7 +1987,7 @@ cdef class PowerSeries(AlgebraElement): x = self prec = min(prec, self.prec()) - if is_Infinite(prec): + if isinstance(prec, InfinityElement): prec = R.default_prec() n_inv_factorial = R.base_ring().one() x_pow_n = x @@ -2140,7 +2140,7 @@ cdef class PowerSeries(AlgebraElement): x = self prec = min(prec, self.prec()) - if is_Infinite(prec): + if isinstance(prec, InfinityElement): prec = R.default_prec() n_inv_factorial = R.base_ring().one() x_pow_n = x @@ -2228,7 +2228,7 @@ cdef class PowerSeries(AlgebraElement): assert(val >= 1) prec = min(prec, self.prec()) - if is_Infinite(prec): + if isinstance(prec, InfinityElement): prec = R.default_prec() n_inv_factorial = R.base_ring().one() x_pow_n = R.one() From ee7f9d14ce23900324f957f4bbcd5d91a7b21cfb Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 25 Jun 2024 20:26:06 -0700 Subject: [PATCH 144/231] Deprecate is_Infinite --- src/sage/rings/infinity.py | 7 +++++++ src/sage/rings/power_series_ring_element.pyx | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/sage/rings/infinity.py b/src/sage/rings/infinity.py index 182b2dd8b8d..16826c872ce 100644 --- a/src/sage/rings/infinity.py +++ b/src/sage/rings/infinity.py @@ -976,6 +976,10 @@ def is_Infinite(x) -> bool: EXAMPLES:: sage: sage.rings.infinity.is_Infinite(oo) + doctest:warning... + DeprecationWarning: The function is_Infinite is deprecated; + use 'isinstance(..., InfinityElement)' instead. + See https://github.com/sagemath/sage/issues/38022 for details. True sage: sage.rings.infinity.is_Infinite(-oo) True @@ -988,6 +992,9 @@ def is_Infinite(x) -> bool: sage: sage.rings.infinity.is_Infinite(ZZ) False """ + from sage.misc.superseded import deprecation + deprecation(38022, "The function is_Infinite is deprecated; use 'isinstance(..., InfinityElement)' instead.") + return isinstance(x, InfinityElement) diff --git a/src/sage/rings/power_series_ring_element.pyx b/src/sage/rings/power_series_ring_element.pyx index 7007664501b..22a5cc46645 100644 --- a/src/sage/rings/power_series_ring_element.pyx +++ b/src/sage/rings/power_series_ring_element.pyx @@ -96,7 +96,7 @@ With power series the behavior is the same. # **************************************************************************** from cpython.object cimport Py_EQ, Py_NE -from sage.rings.infinity import infinity, is_Infinite +from sage.rings.infinity import infinity, InfinityElement from sage.rings.rational_field import QQ From 23f0d071c70c430c1cd5beced50b0ba1ec106930 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 25 Jun 2024 20:42:25 -0700 Subject: [PATCH 145/231] src/sage/rings/multi_power_series_ring_element.py: Fix up --- src/sage/rings/multi_power_series_ring_element.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/rings/multi_power_series_ring_element.py b/src/sage/rings/multi_power_series_ring_element.py index 446bf965130..70c882cc51c 100644 --- a/src/sage/rings/multi_power_series_ring_element.py +++ b/src/sage/rings/multi_power_series_ring_element.py @@ -157,7 +157,7 @@ from sage.structure.richcmp import richcmp from sage.rings.finite_rings.integer_mod_ring import Zmod -from sage.rings.infinity import infinity, is_Infinite +from sage.rings.infinity import infinity, InfinityElement from sage.rings.integer import Integer from sage.rings.polynomial.polynomial_ring import is_PolynomialRing from sage.rings.power_series_ring import is_PowerSeriesRing From 0412e2f76ff8f10bf86eb332d83df1f94ab29c2e Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 25 Jun 2024 21:40:45 -0700 Subject: [PATCH 146/231] src/sage/combinat/sf/sfa.py: Deprecate is_SymmetricFunction --- src/sage/combinat/sf/classical.py | 2 +- src/sage/combinat/sf/sfa.py | 13 ++++++++++++- src/sage/rings/lazy_series.py | 10 ++++------ 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/sage/combinat/sf/classical.py b/src/sage/combinat/sf/classical.py index 792272417a8..badea76a0c5 100644 --- a/src/sage/combinat/sf/classical.py +++ b/src/sage/combinat/sf/classical.py @@ -155,7 +155,7 @@ def _element_constructor_(self, x): ############## # Dual bases # ############## - elif sfa.is_SymmetricFunction(x) and hasattr(x, 'dual'): + elif isinstance(x, sfa.SymmetricFunctionAlgebra_generic.Element) and hasattr(x, 'dual'): # Check to see if it is the dual of some other basis # If it is, try to coerce its corresponding element # in the other basis diff --git a/src/sage/combinat/sf/sfa.py b/src/sage/combinat/sf/sfa.py index 033a753f076..aff1f1b5164 100644 --- a/src/sage/combinat/sf/sfa.py +++ b/src/sage/combinat/sf/sfa.py @@ -304,12 +304,20 @@ def is_SymmetricFunction(x): sage: from sage.combinat.sf.sfa import is_SymmetricFunction sage: s = SymmetricFunctions(QQ).s() sage: is_SymmetricFunction(2) + doctest:warning... + DeprecationWarning: The function is_SymmetricFunction is deprecated; + use 'isinstance(..., SymmetricFunctionAlgebra_generic.Element)' instead. + See https://github.com/sagemath/sage/issues/38279 for details. False sage: is_SymmetricFunction(s(2)) True sage: is_SymmetricFunction(s([2,1])) True """ + from sage.misc.superseded import deprecation + deprecation(38279, + "The function is_SymmetricFunction is deprecated; " + "use 'isinstance(..., SymmetricFunctionAlgebra_generic.Element)' instead.") return isinstance(x, SymmetricFunctionAlgebra_generic.Element) ##################################################################### @@ -3429,7 +3437,7 @@ def plethysm(self, x, include=None, exclude=None): tHA = HopfAlgebrasWithBasis(R).TensorProducts() tensorflag = Px in tHA - if not is_SymmetricFunction(x): + if not isinstance(x, SymmetricFunctionAlgebra_generic.Element): if R.has_coerce_map_from(Px) or x in R: x = R(x) Px = R @@ -4648,6 +4656,9 @@ def internal_coproduct(self): True sage: all( h([n]).internal_coproduct() == sum([tensor([h(lam), h(m(lam))]) for lam in Partitions(n)]) ....: for n in range(6) ) + doctest:warning... + DeprecationWarning: The function is_SymmetricFunction is deprecated; use 'isinstance(..., SymmetricFunctionAlgebra_generic.Element)' instead. + See https://github.com/sagemath/sage/issues/38279 for details. True sage: all( factorial(n) * h([n]).internal_coproduct() ....: == sum([lam.conjugacy_class_size() * tensor([h(p(lam)), h(p(lam))]) diff --git a/src/sage/rings/lazy_series.py b/src/sage/rings/lazy_series.py index 74744c311da..4aab7395464 100644 --- a/src/sage/rings/lazy_series.py +++ b/src/sage/rings/lazy_series.py @@ -6981,9 +6981,8 @@ def functorial_composition(self, *args): """ if len(args) != self.parent()._arity: raise ValueError("arity must be equal to the number of arguments provided") - from sage.combinat.sf.sfa import is_SymmetricFunction - if not all(isinstance(g, LazySymmetricFunction) - or is_SymmetricFunction(g) + from sage.combinat.sf.sfa import SymmetricFunctionAlgebra_generic + if not all(isinstance(g, (LazySymmetricFunction, SymmetricFunctionAlgebra_generic.Element)) or not g for g in args): raise ValueError("all arguments must be (possibly lazy) symmetric functions") @@ -7200,9 +7199,8 @@ def arithmetic_product(self, *args): """ if len(args) != self.parent()._arity: raise ValueError("arity must be equal to the number of arguments provided") - from sage.combinat.sf.sfa import is_SymmetricFunction - if not all(isinstance(g, LazySymmetricFunction) - or is_SymmetricFunction(g) + from sage.combinat.sf.sfa import SymmetricFunctionAlgebra_generic + if not all(isinstance(g, (LazySymmetricFunction, SymmetricFunctionAlgebra_generic.Element)) or not g for g in args): raise ValueError("all arguments must be (possibly lazy) symmetric functions") From 9e126031c7354d57ed2e2ed31e833fa57b4fe8c0 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 25 Jun 2024 22:52:01 -0700 Subject: [PATCH 147/231] src/sage/combinat/sf/sfa.py: Fix up --- src/sage/combinat/sf/sfa.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/sage/combinat/sf/sfa.py b/src/sage/combinat/sf/sfa.py index aff1f1b5164..36168bd7e1e 100644 --- a/src/sage/combinat/sf/sfa.py +++ b/src/sage/combinat/sf/sfa.py @@ -4656,9 +4656,6 @@ def internal_coproduct(self): True sage: all( h([n]).internal_coproduct() == sum([tensor([h(lam), h(m(lam))]) for lam in Partitions(n)]) ....: for n in range(6) ) - doctest:warning... - DeprecationWarning: The function is_SymmetricFunction is deprecated; use 'isinstance(..., SymmetricFunctionAlgebra_generic.Element)' instead. - See https://github.com/sagemath/sage/issues/38279 for details. True sage: all( factorial(n) * h([n]).internal_coproduct() ....: == sum([lam.conjugacy_class_size() * tensor([h(p(lam)), h(p(lam))]) From 362322719570abe9de4686f7b6b1b1cb66d61d8b Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 25 Jun 2024 23:12:17 -0700 Subject: [PATCH 148/231] src/sage/monoids/string_monoid_element.py: Deprecate is_StringMonoidElement etc. --- src/sage/monoids/string_monoid_element.py | 24 +++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/sage/monoids/string_monoid_element.py b/src/sage/monoids/string_monoid_element.py index 6a7719c9d7c..02070b6b4a8 100644 --- a/src/sage/monoids/string_monoid_element.py +++ b/src/sage/monoids/string_monoid_element.py @@ -32,12 +32,20 @@ def is_StringMonoidElement(x): r""" """ + from sage.misc.superseded import deprecation + deprecation(38280, + "The function is_StringMonoidElement is deprecated; " + "use 'isinstance(..., StringMonoidElement)' instead.") return isinstance(x, StringMonoidElement) def is_AlphabeticStringMonoidElement(x): r""" """ + from sage.misc.superseded import deprecation + deprecation(38280, + "The function is_AlphabeticStringMonoidElement is deprecated; " + "use 'isinstance(..., StringMonoidElement) and isinstance(x.parent(), AlphabeticStringMonoid)' instead.") from .string_monoid import AlphabeticStringMonoid return isinstance(x, StringMonoidElement) and \ isinstance(x.parent(), AlphabeticStringMonoid) @@ -46,6 +54,10 @@ def is_AlphabeticStringMonoidElement(x): def is_BinaryStringMonoidElement(x): r""" """ + from sage.misc.superseded import deprecation + deprecation(38280, + "The function is_BinaryStringMonoidElement is deprecated; " + "use 'isinstance(..., StringMonoidElement) and isinstance(x.parent(), BinaryStringMonoid)' instead.") from .string_monoid import BinaryStringMonoid return isinstance(x, StringMonoidElement) and \ isinstance(x.parent(), BinaryStringMonoid) @@ -54,6 +66,10 @@ def is_BinaryStringMonoidElement(x): def is_OctalStringMonoidElement(x): r""" """ + from sage.misc.superseded import deprecation + deprecation(38280, + "The function is_OctalStringMonoidElement is deprecated; " + "use 'isinstance(..., StringMonoidElement) and isinstance(x.parent(), OctalStringMonoid)' instead.") from .string_monoid import OctalStringMonoid return isinstance(x, StringMonoidElement) and \ isinstance(x.parent(), OctalStringMonoid) @@ -62,6 +78,10 @@ def is_OctalStringMonoidElement(x): def is_HexadecimalStringMonoidElement(x): r""" """ + from sage.misc.superseded import deprecation + deprecation(38280, + "The function is_HexadecimalStringMonoidElement is deprecated; " + "use 'isinstance(..., StringMonoidElement) and isinstance(x.parent(), HexadecimalStringMonoid)' instead.") from .string_monoid import HexadecimalStringMonoid return isinstance(x, StringMonoidElement) and \ isinstance(x.parent(), HexadecimalStringMonoid) @@ -70,6 +90,10 @@ def is_HexadecimalStringMonoidElement(x): def is_Radix64StringMonoidElement(x): r""" """ + from sage.misc.superseded import deprecation + deprecation(38280, + "The function is_Radix64StringMonoidElement is deprecated; " + "use 'isinstance(..., StringMonoidElement) and isinstance(x.parent(), Radix64StringMonoid)' instead.") from .string_monoid import Radix64StringMonoid return isinstance(x, StringMonoidElement) and \ isinstance(x.parent(), Radix64StringMonoid) From 03247ad0fcd33e407f4d5e355bb8f877db9f1ca0 Mon Sep 17 00:00:00 2001 From: John Cremona Date: Wed, 26 Jun 2024 16:16:39 +0100 Subject: [PATCH 149/231] correct eclib's m4 file code to check version --- build/pkgs/eclib/spkg-configure.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/pkgs/eclib/spkg-configure.m4 b/build/pkgs/eclib/spkg-configure.m4 index 133b44bfdc1..ba5c22fa090 100644 --- a/build/pkgs/eclib/spkg-configure.m4 +++ b/build/pkgs/eclib/spkg-configure.m4 @@ -2,7 +2,7 @@ SAGE_SPKG_CONFIGURE([eclib], [ SAGE_SPKG_DEPCHECK([ntl pari flint], [ dnl use existing eclib only if the version reported by pkg-config is recent enough m4_pushdef([SAGE_ECLIB_VER],["20231212"]) - PKG_CHECK_MODULES([ECLIB], [eclib = SAGE_ECLIB_VER], [ + PKG_CHECK_MODULES([ECLIB], [eclib >= SAGE_ECLIB_VER], [ AC_CACHE_CHECK([for mwrank version == SAGE_ECLIB_VER], [ac_cv_path_MWRANK], [ AC_PATH_PROGS_FEATURE_CHECK([MWRANK], [mwrank], [ mwrank_version=`$ac_path_MWRANK -V 2>&1` From 0ff30e3a097456e7a0b4ebb3bbbf673593b15058 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 26 Jun 2024 13:59:02 -0700 Subject: [PATCH 150/231] src/sage/rings/number_field/number_field_element.pyx (is_NumberFieldElement): Fix deprecation message --- src/sage/rings/number_field/number_field_element.pyx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/rings/number_field/number_field_element.pyx b/src/sage/rings/number_field/number_field_element.pyx index 8a3e006ace6..7e57bd7fc5f 100644 --- a/src/sage/rings/number_field/number_field_element.pyx +++ b/src/sage/rings/number_field/number_field_element.pyx @@ -104,7 +104,7 @@ def is_NumberFieldElement(x): sage: is_NumberFieldElement(2) doctest:warning... DeprecationWarning: is_NumberFieldElement is deprecated; - use isinstance(..., sage.structure.element.NumberFieldElement) instead + use isinstance(..., sage.rings.number_field.number_field_element_base.NumberFieldElement_base) instead See https://github.com/sagemath/sage/issues/34931 for details. False sage: x = polygen(ZZ, 'x') @@ -115,7 +115,7 @@ def is_NumberFieldElement(x): from sage.misc.superseded import deprecation deprecation(34931, 'is_NumberFieldElement is deprecated; ' - 'use isinstance(..., sage.structure.element.NumberFieldElement) instead') + 'use isinstance(..., sage.rings.number_field.number_field_element_base.NumberFieldElement_base) instead') return isinstance(x, NumberFieldElement) From 505eaed35e91324d48b8bde3b13868bbd336a16b Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 26 Jun 2024 15:38:09 -0700 Subject: [PATCH 151/231] Deprecate is_Ring --- src/sage/rings/ring.pyx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/sage/rings/ring.pyx b/src/sage/rings/ring.pyx index d546fca961b..aef35f3f1c8 100644 --- a/src/sage/rings/ring.pyx +++ b/src/sage/rings/ring.pyx @@ -1646,9 +1646,16 @@ def is_Ring(x): sage: from sage.rings.ring import is_Ring sage: is_Ring(ZZ) + doctest:warning... + DeprecationWarning: The function is_Ring is deprecated; use '... in Rings()' instead + See https://github.com/sagemath/sage/issues/38288 for details. True sage: MS = MatrixSpace(QQ, 2) # needs sage.modules sage: is_Ring(MS) # needs sage.modules True """ + from sage.misc.superseded import deprecation_cython + deprecation_cython(38288, + "The function is_Ring is deprecated; " + "use '... in Rings()' instead") return x in _Rings From d468207107aa9ad5c9a31a7e5492324d1562c7bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20K=C3=B6ppe?= Date: Wed, 26 Jun 2024 23:57:03 -0700 Subject: [PATCH 152/231] Apply suggestions from code review Co-authored-by: Sebastian Oehms <47305845+soehms@users.noreply.github.com> --- src/sage/libs/mpmath/ext_main.pyx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/sage/libs/mpmath/ext_main.pyx b/src/sage/libs/mpmath/ext_main.pyx index 99a0c782423..a3ec1ba5e8e 100644 --- a/src/sage/libs/mpmath/ext_main.pyx +++ b/src/sage/libs/mpmath/ext_main.pyx @@ -1815,7 +1815,7 @@ cdef class mpf_base(mpnumber): sage: X().to_fixed(30) 3489660928 """ - return libmp.to_fixed(self._mpf_, prec) + return libmp.to_fixed(self._mpf_, prec) def __getstate__(self): return libmp.to_pickable(self._mpf_) @@ -2137,7 +2137,6 @@ cdef class mpf(mpf_base): def __round__(self, *args): return round(float(self), *args) - def __richcmp__(self, other, int op): """ Compares numbers :: From 5ba18eac27019fa5dc4f9ae2672b0b384e745aab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20K=C3=B6ppe?= Date: Thu, 27 Jun 2024 10:00:19 -0700 Subject: [PATCH 153/231] Update src/sage/libs/mpmath/ext_main.pyx Co-authored-by: Sebastian Oehms <47305845+soehms@users.noreply.github.com> --- src/sage/libs/mpmath/ext_main.pyx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sage/libs/mpmath/ext_main.pyx b/src/sage/libs/mpmath/ext_main.pyx index a3ec1ba5e8e..d4ffc5fa5c0 100644 --- a/src/sage/libs/mpmath/ext_main.pyx +++ b/src/sage/libs/mpmath/ext_main.pyx @@ -2137,6 +2137,7 @@ cdef class mpf(mpf_base): def __round__(self, *args): return round(float(self), *args) + def __richcmp__(self, other, int op): """ Compares numbers :: From ee4f9511128c7468d3326432c7f8dbca0bf36934 Mon Sep 17 00:00:00 2001 From: Cyril Bouvier Date: Fri, 28 Jun 2024 14:10:37 +0200 Subject: [PATCH 154/231] graph: modular decomposition of a single vertex is a single tree node --- src/sage/graphs/graph.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/sage/graphs/graph.py b/src/sage/graphs/graph.py index 3eda130f4d8..312915cc764 100644 --- a/src/sage/graphs/graph.py +++ b/src/sage/graphs/graph.py @@ -8159,9 +8159,9 @@ def modular_decomposition(self, algorithm=None, style='tuple'): Singleton Vertex:: sage: Graph(1).modular_decomposition() - (PRIME, [0]) + 0 sage: Graph(1).modular_decomposition(style='tree') - PRIME[0[]] + 0[] Vertices may be arbitrary --- check that :issue:`24898` is fixed:: @@ -8209,8 +8209,7 @@ def modular_decomposition(self, algorithm=None, style='tuple'): if not self.order(): D = None elif self.order() == 1: - D = create_prime_node() - D.children.append(create_normal_node(self.vertices(sort=False)[0])) + D = create_normal_node(self.vertices(sort=False)[0]) else: D = habib_maurer_algorithm(self) From 7324f6328cac0064ca4c08f86b30f03d187abb7d Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Thu, 20 Jun 2024 19:14:01 +0100 Subject: [PATCH 155/231] provide compatibility with numpy 2.0 --- src/doc/en/faq/faq-usage.rst | 2 +- .../Statistics-and-Distributions.rst | 2 ++ .../thematic_tutorials/numerical_sage/numpy.rst | 2 ++ src/doc/it/faq/faq-usage.rst | 2 +- src/sage/arith/misc.py | 2 +- src/sage/calculus/interpolators.pyx | 3 +++ src/sage/calculus/riemann.pyx | 3 +++ src/sage/combinat/fully_packed_loop.py | 3 +++ src/sage/env.py | 2 +- src/sage/functions/special.py | 3 +++ .../graphs/generators/classical_geometries.py | 2 +- src/sage/graphs/generic_graph.py | 3 +++ src/sage/graphs/graph_generators_pyx.pyx | 2 +- src/sage/modules/free_module_element.pyx | 8 ++++++++ src/sage/numerical/optimize.py | 17 +++++++++++++++++ src/sage/plot/arrow.py | 3 +++ src/sage/plot/complex_plot.pyx | 6 ++---- src/sage/plot/graphics.py | 2 +- src/sage/plot/histogram.py | 2 ++ src/sage/plot/multigraphics.py | 6 ++++++ src/sage/plot/plot3d/implicit_surface.pyx | 2 ++ src/sage/plot/scatter_plot.py | 4 ++-- src/sage/plot/streamline_plot.py | 3 +++ .../probability/probability_distribution.pyx | 3 +++ src/sage/rings/complex_double.pyx | 10 +++++----- src/sage/rings/integer.pyx | 2 ++ .../rings/polynomial/polynomial_element.pyx | 2 +- src/sage/rings/real_mpfi.pyx | 2 ++ .../elliptic_curves/period_lattice_region.pyx | 10 ++++++++++ src/sage/stats/basic_stats.py | 4 ++++ src/sage/stats/time_series.pyx | 2 ++ src/sage/structure/coerce.pyx | 2 ++ src/sage/symbolic/expression.pyx | 2 +- src/sage/symbolic/function.pyx | 3 +++ src/sage/symbolic/ring.pyx | 2 ++ 35 files changed, 108 insertions(+), 20 deletions(-) diff --git a/src/doc/en/faq/faq-usage.rst b/src/doc/en/faq/faq-usage.rst index 53f225fd729..d03881c36a2 100644 --- a/src/doc/en/faq/faq-usage.rst +++ b/src/doc/en/faq/faq-usage.rst @@ -324,7 +324,7 @@ ints. For example:: sage: RealNumber = float; Integer = int sage: from scipy import stats sage: stats.ttest_ind([1,2,3,4,5], [2,3,4,5,.6]) - Ttest...Result(statistic=0.0767529..., pvalue=0.940704...) + Ttest...Result(statistic=...0.0767529..., pvalue=...0.940704...) sage: stats.uniform(0,15).ppf([0.5,0.7]) array([ 7.5, 10.5]) diff --git a/src/doc/en/prep/Quickstarts/Statistics-and-Distributions.rst b/src/doc/en/prep/Quickstarts/Statistics-and-Distributions.rst index b5eb3d842a2..958a378f945 100644 --- a/src/doc/en/prep/Quickstarts/Statistics-and-Distributions.rst +++ b/src/doc/en/prep/Quickstarts/Statistics-and-Distributions.rst @@ -24,6 +24,8 @@ NumPy provides, for example, functions to compute the arithmetic mean and the standard deviation:: sage: import numpy as np + sage: if int(np.version.short_version[0]) > 1: + ....: np.set_printoptions(legacy="1.25") sage: np.mean([1, 2, 3, 5]) 2.75 diff --git a/src/doc/en/thematic_tutorials/numerical_sage/numpy.rst b/src/doc/en/thematic_tutorials/numerical_sage/numpy.rst index dbc2de71d42..925e5312882 100644 --- a/src/doc/en/thematic_tutorials/numerical_sage/numpy.rst +++ b/src/doc/en/thematic_tutorials/numerical_sage/numpy.rst @@ -7,6 +7,8 @@ import it. :: sage: import numpy + sage: if int(numpy.version.short_version[0]) > 1: + ....: numpy.set_printoptions(legacy="1.25") # to ensure numpy 2.0 compatibility The basic object of computation in NumPy is an array. It is simple to create an array. diff --git a/src/doc/it/faq/faq-usage.rst b/src/doc/it/faq/faq-usage.rst index 37bef7b13c1..5d3183769f7 100644 --- a/src/doc/it/faq/faq-usage.rst +++ b/src/doc/it/faq/faq-usage.rst @@ -305,7 +305,7 @@ anziché Integer di Sage. Ad esempio:: sage: RealNumber = float; Integer = int sage: from scipy import stats sage: stats.ttest_ind([1,2,3,4,5], [2,3,4,5,.6]) - Ttest...Result(statistic=0.0767529..., pvalue=0.940704...) + Ttest...Result(statistic=...0.0767529..., pvalue=...0.940704...) sage: stats.uniform(0,15).ppf([0.5,0.7]) array([ 7.5, 10.5]) diff --git a/src/sage/arith/misc.py b/src/sage/arith/misc.py index 28f81d7b798..d184c52bf19 100644 --- a/src/sage/arith/misc.py +++ b/src/sage/arith/misc.py @@ -2277,7 +2277,7 @@ def power_mod(a, n, m): sage: from numpy import int32 # needs numpy sage: power_mod(int32(2), int32(390), int32(391)) # needs numpy - 285 + ...285... sage: from gmpy2 import mpz sage: power_mod(mpz(2), mpz(390), mpz(391)) mpz(285) diff --git a/src/sage/calculus/interpolators.pyx b/src/sage/calculus/interpolators.pyx index 221b52369e2..bb0be7bab0c 100644 --- a/src/sage/calculus/interpolators.pyx +++ b/src/sage/calculus/interpolators.pyx @@ -27,6 +27,9 @@ Development supported by NSF award No. 0702939. import numpy as np cimport numpy as np +if int(np.version.short_version[0]) > 1: + np.set_printoptions(legacy="1.25") + from math import pi cdef double TWOPI = 2*pi diff --git a/src/sage/calculus/riemann.pyx b/src/sage/calculus/riemann.pyx index 6ec80d89aa7..c09d93c4260 100644 --- a/src/sage/calculus/riemann.pyx +++ b/src/sage/calculus/riemann.pyx @@ -44,6 +44,9 @@ from sage.calculus.integration import numerical_integral import numpy as np cimport numpy as np +if int(np.version.short_version[0]) > 1: + np.set_printoptions(legacy="1.25") + from math import pi from math import sin from math import cos diff --git a/src/sage/combinat/fully_packed_loop.py b/src/sage/combinat/fully_packed_loop.py index b198fed0c0d..b3ebd206cd2 100644 --- a/src/sage/combinat/fully_packed_loop.py +++ b/src/sage/combinat/fully_packed_loop.py @@ -66,6 +66,9 @@ def _make_color_list(n, colors=None, color_map=None, randomize=False): r""" TESTS:: + sage: import numpy as np + sage: if int(np.version.short_version[0]) > 1: + ....: np.set_printoptions(legacy="1.25") sage: from sage.combinat.fully_packed_loop import _make_color_list sage: _make_color_list(5) sage: _make_color_list(5, ['blue', 'red']) diff --git a/src/sage/env.py b/src/sage/env.py index 722649ab3da..abb9b19f9e3 100644 --- a/src/sage/env.py +++ b/src/sage/env.py @@ -296,7 +296,7 @@ def sage_include_directories(use_sources=False): sage: import sage.env sage: sage.env.sage_include_directories() ['...', - '.../numpy/core/include', + '.../numpy/...core/include', '.../include/python...'] To check that C/C++ files are correctly found, we verify that we can diff --git a/src/sage/functions/special.py b/src/sage/functions/special.py index e100ba3ee23..2a03bb68f67 100644 --- a/src/sage/functions/special.py +++ b/src/sage/functions/special.py @@ -217,6 +217,9 @@ class SphericalHarmonic(BuiltinFunction): sage: spherical_harmonic(1, 1, pi/2, pi).n() # abs tol 1e-14 # needs sage.symbolic 0.345494149471335 sage: from scipy.special import sph_harm # NB: arguments x and y are swapped # needs scipy + sage: import numpy as np # needs scipy + sage: if int(np.version.short_version[0]) > 1: # needs scipy + ....: np.set_printoptions(legacy="1.25") # needs scipy sage: sph_harm(1, 1, pi.n(), (pi/2).n()) # abs tol 1e-14 # needs scipy sage.symbolic (0.3454941494713355-4.231083042742082e-17j) diff --git a/src/sage/graphs/generators/classical_geometries.py b/src/sage/graphs/generators/classical_geometries.py index da04362eef3..957f88d2061 100644 --- a/src/sage/graphs/generators/classical_geometries.py +++ b/src/sage/graphs/generators/classical_geometries.py @@ -1315,7 +1315,7 @@ def CossidentePenttilaGraph(q): from sage.libs.gap.libgap import libgap adj_list = libgap.function_factory("""function(q) - local z, e, so, G, nu, G1, G0, B, T, s, O1, O2, x; + local z, e, so, G, nu, G1, G0, B, T, s, O1, O2, x, sqo; LoadPackage("grape"); G0:=SO(3,q^2); so:=GeneratorsOfGroup(G0); diff --git a/src/sage/graphs/generic_graph.py b/src/sage/graphs/generic_graph.py index 063931ae274..0bafbd00564 100644 --- a/src/sage/graphs/generic_graph.py +++ b/src/sage/graphs/generic_graph.py @@ -18420,6 +18420,9 @@ def shortest_path_all_pairs(self, by_weight=False, algorithm=None, M = self.adjacency_matrix(vertices=int_to_vertex) # We call the Floyd-Warshall method from SciPy + import numpy # to ensure numpy 2.0 compatibility + if int(numpy.version.short_version[0]) > 1: + numpy.set_printoptions(legacy="1.25") from numpy import array as np_array from scipy.sparse.csgraph import floyd_warshall dd, pp = floyd_warshall(np_array(M), directed=self.is_directed(), diff --git a/src/sage/graphs/graph_generators_pyx.pyx b/src/sage/graphs/graph_generators_pyx.pyx index 033e8b22adc..04b20d3229b 100644 --- a/src/sage/graphs/graph_generators_pyx.pyx +++ b/src/sage/graphs/graph_generators_pyx.pyx @@ -57,7 +57,7 @@ def RandomGNP(n, p, bint directed=False, bint loops=False, seed=None): sage: from numpy import mean # needs numpy sage: abs(mean([RandomGNP(200, .2).density() for i in range(30)]) - .2) < .001 # needs numpy - True + ...True... sage: RandomGNP(150, .2, loops=True) Traceback (most recent call last): ... diff --git a/src/sage/modules/free_module_element.pyx b/src/sage/modules/free_module_element.pyx index d71d22ac1f7..b6f297a3510 100644 --- a/src/sage/modules/free_module_element.pyx +++ b/src/sage/modules/free_module_element.pyx @@ -555,7 +555,11 @@ def vector(arg0, arg1=None, arg2=None, sparse=None, immutable=False): R = None try: + import numpy from numpy import ndarray + if int(numpy.version.short_version[0]) > 1: + numpy.set_printoptions(legacy="1.25") + except ImportError: pass else: @@ -1188,7 +1192,11 @@ cdef class FreeModuleElement(Vector): # abstract base class over Rational Field to numpy array of type <... 'float'>: setting an array element with a sequence. """ + import numpy from numpy import array + if int(numpy.version.short_version[0]) > 1: + numpy.set_printoptions(legacy="1.25") + try: return array(self, dtype=dtype) except ValueError as e: diff --git a/src/sage/numerical/optimize.py b/src/sage/numerical/optimize.py index e3d94d1746e..7ae8ca4966f 100644 --- a/src/sage/numerical/optimize.py +++ b/src/sage/numerical/optimize.py @@ -155,6 +155,10 @@ def find_root(f, a, b, xtol=10e-13, rtol=2.0**-50, maxiter=100, full_output=Fals b = max(s_1, s_2) import scipy.optimize + import numpy + if int(numpy.version.short_version[0]) > 1: + numpy.set_printoptions(legacy="1.25") + g = lambda x: float(f(x)) brentqRes = scipy.optimize.brentq(g, a, b, full_output=full_output, xtol=xtol, rtol=rtol, maxiter=maxiter) @@ -288,6 +292,10 @@ def find_local_minimum(f, a, b, tol=1.48e-08, maxfun=500): a = float(a) b = float(b) import scipy.optimize + import numpy + if int(numpy.version.short_version[0]) > 1: + numpy.set_printoptions(legacy="1.25") + xmin, fval, iter, funcalls = scipy.optimize.fminbound(f, a, b, full_output=1, xtol=tol, maxfun=maxfun) return fval, xmin @@ -376,6 +384,8 @@ def minimize(func, x0, gradient=None, hessian=None, algorithm="default", sage: def rosen(x): # The Rosenbrock function ....: return sum(100.0r*(x[1r:]-x[:-1r]**2.0r)**2.0r + (1r-x[:-1r])**2.0r) sage: import numpy + sage: if int(numpy.version.short_version[0]) > 1: + ....: numpy.set_printoptions(legacy="1.25") sage: from numpy import zeros sage: def rosen_der(x): ....: xm = x[1r:-1r] @@ -393,6 +403,9 @@ def minimize(func, x0, gradient=None, hessian=None, algorithm="default", from sage.structure.element import Expression from sage.ext.fast_callable import fast_callable import numpy + if int(numpy.version.short_version[0]) > 1: + numpy.set_printoptions(legacy="1.25") + from scipy import optimize if isinstance(func, Expression): var_list = func.variables() @@ -530,6 +543,8 @@ def minimize_constrained(func,cons,x0,gradient=None,algorithm='default', **args) from sage.structure.element import Expression from sage.ext.fast_callable import fast_callable import numpy + if int(numpy.version.short_version[0]) > 1: + numpy.set_printoptions(legacy="1.25") from scipy import optimize function_type = type(lambda x,y: x+y) @@ -652,6 +667,8 @@ def find_fit(data, model, initial_guess=None, parameters=None, variables=None, s ``lmdif`` and ``lmder`` algorithms. """ import numpy + if int(numpy.version.short_version[0]) > 1: + numpy.set_printoptions(legacy="1.25") if not isinstance(data, numpy.ndarray): try: diff --git a/src/sage/plot/arrow.py b/src/sage/plot/arrow.py index ac1dc79d802..23e2517ca56 100644 --- a/src/sage/plot/arrow.py +++ b/src/sage/plot/arrow.py @@ -53,6 +53,9 @@ def get_minmax_data(self): EXAMPLES:: + sage: import numpy # to ensure numpy 2.0 compatibility + sage: if int(numpy.version.short_version[0]) > 1: + ....: numpy.set_printoptions(legacy="1.25") sage: from sage.plot.arrow import CurveArrow sage: b = CurveArrow(path=[[(0,0),(.5,.5),(1,0)],[(.5,1),(0,0)]], ....: options={}) diff --git a/src/sage/plot/complex_plot.pyx b/src/sage/plot/complex_plot.pyx index f1f2671a803..4d71414e1c2 100644 --- a/src/sage/plot/complex_plot.pyx +++ b/src/sage/plot/complex_plot.pyx @@ -1282,15 +1282,13 @@ def rgb_to_hls(rgb): raise ValueError("Last dimension of input array must be 3; " "shape {} was found.".format(rgb.shape)) in_shape = rgb.shape - rgb = np.array( - rgb, copy=False, dtype=np.dtype(float), ndmin=2 - ) + rgb = np.asarray(rgb, dtype=np.dtype(float)) rgb_max = rgb.max(-1) rgb_min = rgb.min(-1) l = (rgb_max + rgb_min)/2.0 # lightness hls = np.zeros_like(rgb) - delta = rgb.ptp(-1) + delta = np.ptp(rgb, -1) s = np.zeros_like(delta) ipos = delta > 0 diff --git a/src/sage/plot/graphics.py b/src/sage/plot/graphics.py index a84d162cb56..94f5db09d83 100644 --- a/src/sage/plot/graphics.py +++ b/src/sage/plot/graphics.py @@ -2754,7 +2754,7 @@ def matplotlib(self, filename=None, sage: xmin, xmax = sub.get_xlim() sage: ymin, ymax = sub.get_ylim() sage: xmin > xmax, ymin > ymax - (True, True) + (...True..., ...True...) """ if not isinstance(ticks, (list, tuple)): ticks = (ticks, None) diff --git a/src/sage/plot/histogram.py b/src/sage/plot/histogram.py index fa86a44bd0a..a585cacf9cd 100644 --- a/src/sage/plot/histogram.py +++ b/src/sage/plot/histogram.py @@ -92,6 +92,8 @@ def get_minmax_data(self): {'xmax': 10.0, 'xmin': 3.0, 'ymax': 0.476190476190..., 'ymin': 0} """ import numpy + if int(numpy.version.short_version[0]) > 1: + numpy.set_printoptions(legacy="1.25") # Extract these options (if they are not None) and pass them to # histogram() diff --git a/src/sage/plot/multigraphics.py b/src/sage/plot/multigraphics.py index f657e1d369e..c6c71a72d7e 100644 --- a/src/sage/plot/multigraphics.py +++ b/src/sage/plot/multigraphics.py @@ -785,6 +785,9 @@ def _add_subplot(self, figure, index, **options): True sage: G.position(1) (0.2, 0.3, 0.4, 0.1) + sage: import numpy # to ensure numpy 2.0 compatibility + sage: if int(numpy.version.short_version[0]) > 1: + ....: numpy.set_printoptions(legacy="1.25") sage: ax1.get_position().bounds # tol 1.0e-13 (0.2, 0.3, 0.4000000000000001, 0.10000000000000003) @@ -1296,6 +1299,9 @@ def position(self, index): sage: g1 = plot(sin(x), (x, -pi, pi)) sage: g2 = circle((0,1), 1.) sage: G = graphics_array([g1, g2]) + sage: import numpy # to ensure numpy 2.0 compatibility + sage: if int(numpy.version.short_version[0]) > 1: + ....: numpy.set_printoptions(legacy="1.25") sage: G.position(0) # tol 5.0e-3 (0.025045451349937315, 0.03415488992713045, diff --git a/src/sage/plot/plot3d/implicit_surface.pyx b/src/sage/plot/plot3d/implicit_surface.pyx index ce0da48a4e0..f4d5059b620 100644 --- a/src/sage/plot/plot3d/implicit_surface.pyx +++ b/src/sage/plot/plot3d/implicit_surface.pyx @@ -468,6 +468,7 @@ cdef class MarchingCubesTriangles(MarchingCubes): sage: cube_marcher.y_vertices.tolist() [[[<1.0, 0.5, 0.0>, None]], [[None, None]]] sage: cube_marcher.x_vertices.any() # This shouldn't affect the X vertices. + ... """ (self.y_vertices, self.y_vertices_swapped) = \ (self.y_vertices_swapped, self.y_vertices) @@ -574,6 +575,7 @@ cdef class MarchingCubesTriangles(MarchingCubes): sage: cube_marcher.x_vertices.tolist() [[None, None], [None, <1.5, 1.0, 1.0>]] sage: cube_marcher.y_vertices.any() or cube_marcher.z_vertices.any() # This shouldn't affect the Y or Z vertices. + ... """ cdef bint has_prev = (_prev is not None) cdef bint has_next = (_next is not None) diff --git a/src/sage/plot/scatter_plot.py b/src/sage/plot/scatter_plot.py index 4ad418f040b..781854d372c 100644 --- a/src/sage/plot/scatter_plot.py +++ b/src/sage/plot/scatter_plot.py @@ -63,9 +63,9 @@ def get_minmax_data(self): sage: s = scatter_plot([[0,1],[2,4],[3.2,6]]) sage: d = s.get_minmax_data() sage: d['xmin'] - 0.0 + ...0.0... sage: d['ymin'] - 1.0 + ...1.0... """ return {'xmin': self.xdata.min(), 'xmax': self.xdata.max(), diff --git a/src/sage/plot/streamline_plot.py b/src/sage/plot/streamline_plot.py index 663d3aee70b..d2cb11088c7 100644 --- a/src/sage/plot/streamline_plot.py +++ b/src/sage/plot/streamline_plot.py @@ -71,6 +71,9 @@ def get_minmax_data(self): EXAMPLES:: sage: x, y = var('x y') + sage: import numpy # to ensure numpy 2.0 compatibility + sage: if int(numpy.version.short_version[0]) > 1: + ....: numpy.set_printoptions(legacy="1.25") sage: d = streamline_plot((.01*x, x+y), (x,10,20), (y,10,20))[0].get_minmax_data() sage: d['xmin'] 10.0 diff --git a/src/sage/probability/probability_distribution.pyx b/src/sage/probability/probability_distribution.pyx index e2c71af9c25..59ba4a95ab6 100644 --- a/src/sage/probability/probability_distribution.pyx +++ b/src/sage/probability/probability_distribution.pyx @@ -140,6 +140,9 @@ cdef class ProbabilityDistribution: 1.8, 2.0] """ + import numpy as np + if int(np.version.short_version[0]) > 1: + np.set_printoptions(legacy="1.25") import pylab ell = [float(self.get_random_element()) for _ in range(num_samples)] S = pylab.hist(ell, bins, density=True) diff --git a/src/sage/rings/complex_double.pyx b/src/sage/rings/complex_double.pyx index c59a2b46d6f..b4dddebb4dc 100644 --- a/src/sage/rings/complex_double.pyx +++ b/src/sage/rings/complex_double.pyx @@ -2558,10 +2558,10 @@ cdef class ComplexToCDF(Morphism): sage: # needs numpy sage: import numpy - sage: f = CDF.coerce_map_from(numpy.complex_) - sage: f(numpy.complex_(I)) + sage: f = CDF.coerce_map_from(numpy.complex128) + sage: f(numpy.complex128(I)) 1.0*I - sage: f(numpy.complex_(I)).parent() + sage: f(numpy.complex128(I)).parent() Complex Double Field """ def __init__(self, R): @@ -2578,7 +2578,7 @@ cdef class ComplexToCDF(Morphism): EXAMPLES:: sage: import numpy # needs numpy - sage: CDF(numpy.complex_(I)) # indirect doctest # needs numpy + sage: CDF(numpy.complex128(I)) # indirect doctest # needs numpy 1.0*I """ cdef ComplexDoubleElement z = ComplexDoubleElement.__new__(ComplexDoubleElement) @@ -2592,7 +2592,7 @@ cdef class ComplexToCDF(Morphism): EXAMPLES:: sage: import numpy # needs numpy - sage: f = sage.rings.complex_double.ComplexToCDF(numpy.complex_) # needs numpy + sage: f = sage.rings.complex_double.ComplexToCDF(numpy.complex128) # needs numpy sage: f._repr_type() # needs numpy 'Native' """ diff --git a/src/sage/rings/integer.pyx b/src/sage/rings/integer.pyx index b4a1fa5039b..38c30f7627b 100644 --- a/src/sage/rings/integer.pyx +++ b/src/sage/rings/integer.pyx @@ -593,6 +593,8 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): Test comparisons with numpy types (see :issue:`13386` and :issue:`18076`):: sage: import numpy # needs numpy + sage: if int(numpy.version.short_version[0]) > 1: # needs numpy + ....: numpy.set_printoptions(legacy="1.25") # needs numpy sage: numpy.int8('12') == 12 # needs numpy True sage: 12 == numpy.int8('12') # needs numpy diff --git a/src/sage/rings/polynomial/polynomial_element.pyx b/src/sage/rings/polynomial/polynomial_element.pyx index dcf2af7cdf2..c87eccd44f1 100644 --- a/src/sage/rings/polynomial/polynomial_element.pyx +++ b/src/sage/rings/polynomial/polynomial_element.pyx @@ -8851,7 +8851,7 @@ cdef class Polynomial(CommutativePolynomial): 'you expect.') import numpy - from numpy.linalg.linalg import LinAlgError + from numpy.linalg import LinAlgError from sage.rings.complex_double import CDF numpy_dtype = ('complex' if input_complex else 'double') diff --git a/src/sage/rings/real_mpfi.pyx b/src/sage/rings/real_mpfi.pyx index 95b472e912c..76fbfedab95 100644 --- a/src/sage/rings/real_mpfi.pyx +++ b/src/sage/rings/real_mpfi.pyx @@ -231,6 +231,8 @@ specified if given a non-interval and an interval:: TESTS:: sage: import numpy # needs numpy + sage: if int(numpy.version.short_version[0]) > 1: # needs numpy + ....: numpy.set_printoptions(legacy="1.25") # needs numpy sage: RIF(2) == numpy.int8('2') # needs numpy True sage: numpy.int8('2') == RIF(2) # needs numpy diff --git a/src/sage/schemes/elliptic_curves/period_lattice_region.pyx b/src/sage/schemes/elliptic_curves/period_lattice_region.pyx index 8f240627e77..70ce616f92f 100644 --- a/src/sage/schemes/elliptic_curves/period_lattice_region.pyx +++ b/src/sage/schemes/elliptic_curves/period_lattice_region.pyx @@ -77,6 +77,8 @@ cdef class PeriodicRegion: EXAMPLES:: sage: import numpy as np + sage: if int(np.version.short_version[0]) > 1: + ....: np.set_printoptions(legacy="1.25") sage: from sage.schemes.elliptic_curves.period_lattice_region import PeriodicRegion sage: data = np.zeros((4, 4)) sage: PeriodicRegion(CDF(2), CDF(2*I), data).is_empty() @@ -295,6 +297,8 @@ cdef class PeriodicRegion: EXAMPLES:: sage: import numpy as np + sage: if int(np.version.short_version[0]) > 1: + ....: np.set_printoptions(legacy="1.25") sage: from sage.schemes.elliptic_curves.period_lattice_region import PeriodicRegion sage: data = np.zeros((10, 10)) sage: data[1:4,1:4] = True @@ -317,6 +321,8 @@ cdef class PeriodicRegion: EXAMPLES:: sage: import numpy as np + sage: if int(np.version.short_version[0]) > 1: + ....: np.set_printoptions(legacy="1.25") sage: from sage.schemes.elliptic_curves.period_lattice_region import PeriodicRegion sage: data = np.zeros((4, 4)) sage: data[1,1] = True @@ -370,6 +376,8 @@ cdef class PeriodicRegion: EXAMPLES:: sage: import numpy as np + sage: if int(np.version.short_version[0]) > 1: + ....: np.set_printoptions(legacy="1.25") sage: from sage.schemes.elliptic_curves.period_lattice_region import PeriodicRegion sage: data = np.zeros((20, 20)) @@ -520,6 +528,8 @@ cdef class PeriodicRegion: TESTS:: sage: import numpy as np + sage: if int(np.version.short_version[0]) > 1: + ....: np.set_printoptions(legacy="1.25") sage: from sage.schemes.elliptic_curves.period_lattice_region import PeriodicRegion sage: data = np.zeros((4, 4)) sage: data[1, 1] = True diff --git a/src/sage/stats/basic_stats.py b/src/sage/stats/basic_stats.py index b2e6b301bf7..6937f6cb410 100644 --- a/src/sage/stats/basic_stats.py +++ b/src/sage/stats/basic_stats.py @@ -227,6 +227,8 @@ def std(v, bias=False): sage: # needs numpy sage: import numpy + sage: if int(numpy.version.short_version[0]) > 1: + ....: numpy.set_printoptions(legacy="1.25") sage: x = numpy.array([1,2,3,4,5]) sage: std(x, bias=False) 1.5811388300841898 @@ -304,6 +306,8 @@ def variance(v, bias=False): sage: variance([RIF(1.0103, 1.0103), RIF(2)]) 0.4897530450000000? sage: import numpy # needs numpy + sage: if int(numpy.version.short_version[0]) > 1: # needs numpy + ....: numpy.set_printoptions(legacy="1.25") # needs numpy sage: x = numpy.array([1,2,3,4,5]) # needs numpy sage: variance(x, bias=False) # needs numpy 2.5 diff --git a/src/sage/stats/time_series.pyx b/src/sage/stats/time_series.pyx index 2e22ec45c69..23adae84fb4 100644 --- a/src/sage/stats/time_series.pyx +++ b/src/sage/stats/time_series.pyx @@ -1718,6 +1718,8 @@ cdef class TimeSeries: if len(v0) == 1: return v1[0]/v0[0] import numpy + if int(numpy.version.short_version[0]) > 1: + numpy.set_printoptions(legacy="1.25") coeffs = numpy.polyfit(v0,v1,1) return coeffs[0] diff --git a/src/sage/structure/coerce.pyx b/src/sage/structure/coerce.pyx index dfbd5ff82fa..955a256e9b4 100644 --- a/src/sage/structure/coerce.pyx +++ b/src/sage/structure/coerce.pyx @@ -520,6 +520,8 @@ cdef class CoercionModel: Check that :issue:`8426` is fixed (see also :issue:`18076`):: sage: import numpy # needs numpy + sage: if int(numpy.version.short_version[0]) > 1: # needs numpy + ....: numpy.set_printoptions(legacy="1.25") # needs numpy sage: # needs sage.rings.real_mpfr sage: x = polygen(RR) diff --git a/src/sage/symbolic/expression.pyx b/src/sage/symbolic/expression.pyx index a92fe241355..7671338feaa 100644 --- a/src/sage/symbolic/expression.pyx +++ b/src/sage/symbolic/expression.pyx @@ -1167,7 +1167,7 @@ cdef class Expression(Expression_abc): sage: unicode_art(SR(13 - I)) 13 - ⅈ sage: unicode_art(SR(1.3 - I)) - 1.3 - ⅈ + 1.3 - ...ⅈ sage: unicode_art(cos(I)) cosh(1) diff --git a/src/sage/symbolic/function.pyx b/src/sage/symbolic/function.pyx index 2cb2f09c715..cd89ad2a256 100644 --- a/src/sage/symbolic/function.pyx +++ b/src/sage/symbolic/function.pyx @@ -964,6 +964,9 @@ cdef class BuiltinFunction(Function): mpc(real='0.83373002513114902', imag='-0.98889770576286506') sage: import numpy # needs numpy + sage: if int(numpy.version.short_version[0]) > 1: # needs numpy + ....: numpy.set_printoptions(legacy="1.25") # needs numpy + sage: sin(numpy.int32(0)) # needs numpy 0.0 sage: type(_) # needs numpy diff --git a/src/sage/symbolic/ring.pyx b/src/sage/symbolic/ring.pyx index 501b0920898..5b007d9e5fd 100644 --- a/src/sage/symbolic/ring.pyx +++ b/src/sage/symbolic/ring.pyx @@ -1162,6 +1162,8 @@ cdef class NumpyToSRMorphism(Morphism): We check that :issue:`8949` and :issue:`9769` are fixed (see also :issue:`18076`):: sage: import numpy # needs numpy + sage: if int(numpy.version.short_version[0]) > 1: # needs numpy + ....: numpy.set_printoptions(legacy="1.25") # needs numpy sage: f(x) = x^2 sage: f(numpy.int8('2')) # needs numpy 4 From 9a067126b23066788d2cc8e3e43e69601688d32e Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Mon, 24 Jun 2024 13:02:30 +0100 Subject: [PATCH 156/231] rectify the test for numpy.typecodes --- src/sage/matrix/matrix1.pyx | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/sage/matrix/matrix1.pyx b/src/sage/matrix/matrix1.pyx index a810418389c..c38df5412f0 100644 --- a/src/sage/matrix/matrix1.pyx +++ b/src/sage/matrix/matrix1.pyx @@ -705,12 +705,15 @@ cdef class Matrix(Matrix0): Type ``numpy.typecodes`` for a list of the possible typecodes:: - sage: import numpy # needs numpy - sage: sorted(numpy.typecodes.items()) # needs numpy + sage: import numpy # needs numpy + sage: numpy.typecodes.items() # needs numpy # random [('All', '?bhilqpBHILQPefdgFDGSUVOMm'), ('AllFloat', 'efdgFDG'), - ('AllInteger', 'bBhHiIlLqQpP'), ('Character', 'c'), ('Complex', 'FDG'), - ('Datetime', 'Mm'), ('Float', 'efdg'), ('Integer', 'bhilqp'), - ('UnsignedInteger', 'BHILQP')] + ... + + For instance, you can see possibilities for real floating point numbers:: + + sage: numpy.typecodes['Float'] # needs numpy + 'efdg' Alternatively, numpy automatically calls this function (via the magic :meth:`__array__` method) to convert Sage matrices From 611bd424d5bb06fb65275bfde4008f220ae779d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antoine=20Leudi=C3=A8re?= Date: Fri, 28 Jun 2024 19:59:21 +0200 Subject: [PATCH 157/231] Fix `absolutely` flag --- .../drinfeld_modules/drinfeld_module.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/sage/rings/function_field/drinfeld_modules/drinfeld_module.py b/src/sage/rings/function_field/drinfeld_modules/drinfeld_module.py index 958347113c0..f2456102a2d 100644 --- a/src/sage/rings/function_field/drinfeld_modules/drinfeld_module.py +++ b/src/sage/rings/function_field/drinfeld_modules/drinfeld_module.py @@ -1313,9 +1313,9 @@ def is_isomorphic(self, other, absolutely=False): INPUT: - - ``absolutely`` -- a boolean (default: ``False``); if ``True``, + - ``absolutely`` -- a boolean (default: ``False``); if ``False``, check the existence of an isomorphism defined on the base - field; if ``False``, check over an algebraic closure. + field; if ``True``, check over an algebraic closure. EXAMPLES:: @@ -1349,6 +1349,18 @@ def is_isomorphic(self, other, absolutely=False): sage: phi.is_isomorphic(psi, absolutely=True) True + In particular, two Drinfeld modules may have the same + `j`-invariant, while not being isomorphic on the base field:: + + sage: phi = DrinfeldModule(A, [z, 0, 1]) + sage: psi = DrinfeldModule(A, [z, 0, z]) + sage: phi.j_invariant() == psi.j_invariant() + True + sage: phi.is_isomorphic(psi) + False + sage: phi.is_isomorphic(psi, absolutely=True) + True + On certain fields, testing isomorphisms over the base field may fail:: From a34f2e48d9653d9296751b6673517902c45a9f49 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 28 Jun 2024 18:32:48 -0700 Subject: [PATCH 158/231] build/pkgs/surf: Add to distros/ --- build/pkgs/surf/distros/debian.txt | 1 + build/pkgs/surf/distros/fedora.txt | 1 + 2 files changed, 2 insertions(+) create mode 100644 build/pkgs/surf/distros/debian.txt create mode 100644 build/pkgs/surf/distros/fedora.txt diff --git a/build/pkgs/surf/distros/debian.txt b/build/pkgs/surf/distros/debian.txt new file mode 100644 index 00000000000..e33671ee0e3 --- /dev/null +++ b/build/pkgs/surf/distros/debian.txt @@ -0,0 +1 @@ +surf-alggeo diff --git a/build/pkgs/surf/distros/fedora.txt b/build/pkgs/surf/distros/fedora.txt new file mode 100644 index 00000000000..4cbab33147a --- /dev/null +++ b/build/pkgs/surf/distros/fedora.txt @@ -0,0 +1 @@ +surf-geometry From 7783fa8fbd6a58b8896ccf90dabac173f9ee600c Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 21 Jun 2024 21:46:19 -0700 Subject: [PATCH 159/231] configure: Check that the build directory is writable and on a normal file system --- configure.ac | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/configure.ac b/configure.ac index 4848a8f4b21..c13b8e5630e 100644 --- a/configure.ac +++ b/configure.ac @@ -537,6 +537,19 @@ AC_CONFIG_COMMANDS(mkdirs, AC_MSG_NOTICE([[creating symbolic link lib64 -> lib]]) ln -s lib "$SAGE_LOCAL/lib64" fi + dnl Check that the file system is sufficiently functional + if test -z "$SAGE_BUILD_DIR"; then + SAGE_BUILD_DIR="$SAGE_LOCAL/var/tmp/sage/build" + fi + AC_MSG_NOTICE([creating directory $SAGE_BUILD_DIR]) + mkdir -p "$SAGE_BUILD_DIR" || AC_MSG_ERROR([could not create $SAGE_BUILD_DIR]) + rm -f "$SAGE_BUILD_DIR"/conftest + touch "$SAGE_BUILD_DIR"/conftest || AC_MSG_ERROR([could not create a file in $SAGE_BUILD_DIR]) + chmod -w "$SAGE_BUILD_DIR"/conftest || AC_MSG_ERROR([could not set file permissions in $SAGE_BUILD_DIR]) + test -w "$SAGE_BUILD_DIR"/conftest && AC_MSG_ERROR([file permissions did not persist in $SAGE_BUILD_DIR]) + chmod +w "$SAGE_BUILD_DIR"/conftest || AC_MSG_ERROR([could not set file permissions in $SAGE_BUILD_DIR]) + test -w "$SAGE_BUILD_DIR"/conftest || AC_MSG_ERROR([file permissions did not persist in $SAGE_BUILD_DIR]) + rm -f "$SAGE_BUILD_DIR"/conftest ], [ SAGE_LOGS="$SAGE_ROOT/logs/pkgs" From d6be2c1c3c994c475b789af0056fe65ec07908be Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 22 Jun 2024 10:33:14 -0700 Subject: [PATCH 160/231] More verbosity --- configure.ac | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index c13b8e5630e..b4a3d63d1d3 100644 --- a/configure.ac +++ b/configure.ac @@ -545,10 +545,10 @@ AC_CONFIG_COMMANDS(mkdirs, mkdir -p "$SAGE_BUILD_DIR" || AC_MSG_ERROR([could not create $SAGE_BUILD_DIR]) rm -f "$SAGE_BUILD_DIR"/conftest touch "$SAGE_BUILD_DIR"/conftest || AC_MSG_ERROR([could not create a file in $SAGE_BUILD_DIR]) - chmod -w "$SAGE_BUILD_DIR"/conftest || AC_MSG_ERROR([could not set file permissions in $SAGE_BUILD_DIR]) - test -w "$SAGE_BUILD_DIR"/conftest && AC_MSG_ERROR([file permissions did not persist in $SAGE_BUILD_DIR]) - chmod +w "$SAGE_BUILD_DIR"/conftest || AC_MSG_ERROR([could not set file permissions in $SAGE_BUILD_DIR]) - test -w "$SAGE_BUILD_DIR"/conftest || AC_MSG_ERROR([file permissions did not persist in $SAGE_BUILD_DIR]) + chmod -w "$SAGE_BUILD_DIR"/conftest || AC_MSG_ERROR([could not set file permissions -w in $SAGE_BUILD_DIR]) + test -w "$SAGE_BUILD_DIR"/conftest && AC_MSG_ERROR([file permissions -w did not persist in $SAGE_BUILD_DIR]) + chmod +w "$SAGE_BUILD_DIR"/conftest || AC_MSG_ERROR([could not set file permissions +w in $SAGE_BUILD_DIR]) + test -w "$SAGE_BUILD_DIR"/conftest || AC_MSG_ERROR([file permissions +w did not persist in $SAGE_BUILD_DIR]) rm -f "$SAGE_BUILD_DIR"/conftest ], [ From df678bc1ad59c2dd11f8f4b670c0c9d4c9faaed2 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 28 Jun 2024 20:48:25 -0700 Subject: [PATCH 161/231] configure.ac: Check the executable bit instead of the write bit --- configure.ac | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/configure.ac b/configure.ac index b4a3d63d1d3..df6a785251e 100644 --- a/configure.ac +++ b/configure.ac @@ -542,13 +542,13 @@ AC_CONFIG_COMMANDS(mkdirs, SAGE_BUILD_DIR="$SAGE_LOCAL/var/tmp/sage/build" fi AC_MSG_NOTICE([creating directory $SAGE_BUILD_DIR]) - mkdir -p "$SAGE_BUILD_DIR" || AC_MSG_ERROR([could not create $SAGE_BUILD_DIR]) + mkdir -p "$SAGE_BUILD_DIR" || AC_MSG_ERROR([error creating directory $SAGE_BUILD_DIR (SAGE_BUILD_DIR)]) rm -f "$SAGE_BUILD_DIR"/conftest - touch "$SAGE_BUILD_DIR"/conftest || AC_MSG_ERROR([could not create a file in $SAGE_BUILD_DIR]) - chmod -w "$SAGE_BUILD_DIR"/conftest || AC_MSG_ERROR([could not set file permissions -w in $SAGE_BUILD_DIR]) - test -w "$SAGE_BUILD_DIR"/conftest && AC_MSG_ERROR([file permissions -w did not persist in $SAGE_BUILD_DIR]) - chmod +w "$SAGE_BUILD_DIR"/conftest || AC_MSG_ERROR([could not set file permissions +w in $SAGE_BUILD_DIR]) - test -w "$SAGE_BUILD_DIR"/conftest || AC_MSG_ERROR([file permissions +w did not persist in $SAGE_BUILD_DIR]) + touch "$SAGE_BUILD_DIR"/conftest || AC_MSG_ERROR([error creating a file in $SAGE_BUILD_DIR]) + chmod +x "$SAGE_BUILD_DIR"/conftest || AC_MSG_ERROR([error setting file permissions +x in $SAGE_BUILD_DIR]) + test -x "$SAGE_BUILD_DIR"/conftest || AC_MSG_ERROR([file permissions +x did not persist in $SAGE_BUILD_DIR]) + chmod -x "$SAGE_BUILD_DIR"/conftest || AC_MSG_ERROR([error setting file permissions -x in $SAGE_BUILD_DIR]) + test -x "$SAGE_BUILD_DIR"/conftest && AC_MSG_ERROR([file permissions -x did not persist in $SAGE_BUILD_DIR]) rm -f "$SAGE_BUILD_DIR"/conftest ], [ From e5027304e99fd1f24c553560d7de4afbb767653c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sat, 29 Jun 2024 10:09:16 +0200 Subject: [PATCH 162/231] fix some typos ; mostly in graphs --- src/sage/categories/coxeter_groups.py | 7 +++---- src/sage/graphs/base/static_dense_graph.pyx | 2 +- src/sage/graphs/cographs.py | 2 +- src/sage/graphs/comparability.pyx | 2 +- src/sage/graphs/convexity_properties.pyx | 2 +- src/sage/graphs/distances_all_pairs.pyx | 6 +++--- src/sage/graphs/generators/basic.py | 2 +- src/sage/graphs/generators/distance_regular.pyx | 4 ++-- src/sage/graphs/generic_graph.py | 4 ++-- src/sage/graphs/graph.py | 4 ++-- src/sage/graphs/graph_coloring.pyx | 2 +- src/sage/graphs/orientations.py | 2 +- src/sage/graphs/pq_trees.py | 6 +++--- src/sage/graphs/strongly_regular_db.pyx | 2 +- src/sage/graphs/views.pyx | 2 +- src/sage/libs/coxeter3/coxeter.pyx | 2 +- 16 files changed, 25 insertions(+), 26 deletions(-) diff --git a/src/sage/categories/coxeter_groups.py b/src/sage/categories/coxeter_groups.py index 25261db6645..f8b5abc8ce9 100644 --- a/src/sage/categories/coxeter_groups.py +++ b/src/sage/categories/coxeter_groups.py @@ -827,7 +827,7 @@ def kazhdan_lusztig_cells(self, side='left'): sage: len(W.kazhdan_lusztig_cells()) 10 - Computing the two sided cells in `B_3`:: + Computing the two-sided cells in `B_3`:: sage: # optional - coxeter3, needs sage.combinat sage.groups sage.libs.gap sage.modules sage.rings.number_field sage: W = CoxeterGroup('B3', implementation='coxeter3') @@ -2064,9 +2064,8 @@ def absolute_chain(self): """ reflections = self.absolute_chain_reflections() P = self.parent() - chain = [P.prod(reversed(reflections[:i])) - for i in range(len(reflections)+1)] - return chain + return [P.prod(reversed(reflections[:i])) + for i in range(len(reflections) + 1)] def absolute_chain_reflections(self): r""" diff --git a/src/sage/graphs/base/static_dense_graph.pyx b/src/sage/graphs/base/static_dense_graph.pyx index b23eab66a3b..fcd71c0143f 100644 --- a/src/sage/graphs/base/static_dense_graph.pyx +++ b/src/sage/graphs/base/static_dense_graph.pyx @@ -711,7 +711,7 @@ def connected_full_subgraphs(G, edges_only=False, labels=False, elif bitset_len(boundaries.rows[i]): # We prepare the boundary for the selection of the next vertex. - # This is equivalant to consider an empty neighborhood. + # This is equivalent to consider an empty neighborhood. bitset_copy(boundaries.rows[i + 1], boundaries.rows[i]) bitset_clear(boundaries.rows[i]) # to prevent doing twice this operation E.append([]) diff --git a/src/sage/graphs/cographs.py b/src/sage/graphs/cographs.py index b921375f643..35a45b47ff3 100644 --- a/src/sage/graphs/cographs.py +++ b/src/sage/graphs/cographs.py @@ -7,7 +7,7 @@ more details on this graph class, and :oeis:`A000084` to know the number of cographs of order `n \geq 1`. -This module implements the folowing methods concerning cographs: +This module implements the following methods concerning cographs: .. csv-table:: :class: contentstable diff --git a/src/sage/graphs/comparability.pyx b/src/sage/graphs/comparability.pyx index b10ce489268..ebafaac95f3 100644 --- a/src/sage/graphs/comparability.pyx +++ b/src/sage/graphs/comparability.pyx @@ -90,7 +90,7 @@ built is the following (see [ST1994]_): - `G` is a comparability graph - `\forall uv\in G, vu\not\in C^G_{uv}` - - The edges of `G` can be partitionned into `B_1,...,B_k` where `B_i` is the + - The edges of `G` can be partitioned into `B_1,...,B_k` where `B_i` is the equivalence class of some oriented edge in `G-B_1-\dots-B_{i-1}` Hence, ensuring that a graph is a comparability graph can be done by checking diff --git a/src/sage/graphs/convexity_properties.pyx b/src/sage/graphs/convexity_properties.pyx index c8a321ece81..d36124fc31d 100644 --- a/src/sage/graphs/convexity_properties.pyx +++ b/src/sage/graphs/convexity_properties.pyx @@ -117,7 +117,7 @@ cdef class ConvexityProperties: elements `z` with `d_{G}(u,w) + d_{G}(w,v) = d_{G}(u,v)`. This is not in general equal to `h(\{u,v\})` ! - Nothing says these recommandations will actually lead to any actual + Nothing says these recommendations will actually lead to any actual improvements. There are just some ideas remembered while writing this code. Trying to optimize may well lead to lost in efficiency on many instances. diff --git a/src/sage/graphs/distances_all_pairs.pyx b/src/sage/graphs/distances_all_pairs.pyx index 85a1d1ee263..249b4c4e92d 100644 --- a/src/sage/graphs/distances_all_pairs.pyx +++ b/src/sage/graphs/distances_all_pairs.pyx @@ -1717,7 +1717,7 @@ def diameter(G, algorithm=None, source=None): unweighted undirected graph. It is based on the following observation: The diameter of the graph is equal to the maximum eccentricity of - a vertex. Let `v` be any vertex, and let `V` be partitionned into + a vertex. Let `v` be any vertex, and let `V` be partitioned into `A\cup B` where: .. MATH:: @@ -2519,8 +2519,8 @@ def antipodal_graph(G): This method first computes the eccentricity of all vertices and determines the diameter of the graph. Then, it for each vertex `u` with eccentricity the diameter, it computes BFS distances from `u` and add an edge in the - antipodal graph for each vertex `v` at diamter distance from `u` (i.e., for - each antipodal vertex). + antipodal graph for each vertex `v` at diameter distance from `u` + (i.e., for each antipodal vertex). The drawback of this method is that some BFS distances may be computed twice, one time to determine the eccentricities and another time is the diff --git a/src/sage/graphs/generators/basic.py b/src/sage/graphs/generators/basic.py index 9776b561748..257d0b2278f 100644 --- a/src/sage/graphs/generators/basic.py +++ b/src/sage/graphs/generators/basic.py @@ -414,7 +414,7 @@ def CorrelationGraph(seqs, alpha, include_anticorrelation): INPUT: - - ``seqs`` -- list of sequences, taht is a list of lists + - ``seqs`` -- list of sequences, that is a list of lists - ``alpha`` -- float; threshold on the correlation coefficient between two sequences for adding an edge diff --git a/src/sage/graphs/generators/distance_regular.pyx b/src/sage/graphs/generators/distance_regular.pyx index 23a52f57e5d..bb0797d8f42 100644 --- a/src/sage/graphs/generators/distance_regular.pyx +++ b/src/sage/graphs/generators/distance_regular.pyx @@ -740,7 +740,7 @@ def AlternatingFormsGraph(const int n, const int q): matrices over `GF(q)` with zero diagonal. Two vertices are adjacent if and only if the difference of the two matrices has rank 2. - This grap is distance-regular with classical parameters + This graph is distance-regular with classical parameters `(\lfloor \frac n 2 \rfloor, q^2, q^2 - 1, q^{2 \lceil \frac n 2 \rceil -1})`. INPUT: @@ -1129,7 +1129,7 @@ def DoubleGrassmannGraph(const int q, const int e): r""" Return the bipartite double of the distance-`e` graph of the Grassmann graph `J_q(n,e)`. - This graph can also be descirbed as follows: + This graph can also be described as follows: Let `V` be the vector space of dimension `n` over `GF(q)`. The vertex set is the set of `e+1` or `e` subspaces of `V`. Two vertices are adjacent if one subspace is contained in the other. diff --git a/src/sage/graphs/generic_graph.py b/src/sage/graphs/generic_graph.py index 063931ae274..f9a9375fdfb 100644 --- a/src/sage/graphs/generic_graph.py +++ b/src/sage/graphs/generic_graph.py @@ -624,7 +624,7 @@ def _use_labels_for_hash(self): Helper method for method ``__hash__``. This method checks whether parameter ``hash_labels`` has been specified - by the user. Otherwise, defaults to the value of parameter ``weigthed``. + by the user. Otherwise, defaults to the value of parameter ``weighted``. TESTS:: @@ -25854,7 +25854,7 @@ def graph_isom_equivalent_non_edge_labeled_graph(g, partition=None, standard_lab # The groups are ordered by increasing multiplicity edge_partition = [tmp[mu] for mu in sorted(tmp.keys())] - # Now the edges are partitionned according to the multiplicity they + # Now the edges are partitioned according to the multiplicity they # represent, and edge labels are forgotten. else: diff --git a/src/sage/graphs/graph.py b/src/sage/graphs/graph.py index 3eda130f4d8..6b350f54f4b 100644 --- a/src/sage/graphs/graph.py +++ b/src/sage/graphs/graph.py @@ -8707,13 +8707,13 @@ def two_factor_petersen(self, solver=None, verbose=0, *, integrality_tolerance=1 Petersen's 2-factor decomposition theorem asserts that any `2r`-regular graph `G` can be decomposed into 2-factors. Equivalently, it means that - the edges of any `2r`-regular graphs can be partitionned in `r` sets + the edges of any `2r`-regular graphs can be partitioned in `r` sets `C_1,\dots,C_r` such that for all `i`, the set `C_i` is a disjoint union of cycles (a 2-regular graph). As any graph of maximal degree `\Delta` can be completed into a regular graph of degree `2\lceil\frac\Delta 2\rceil`, this result also means - that the edges of any graph of degree `\Delta` can be partitionned in + that the edges of any graph of degree `\Delta` can be partitioned in `r=2\lceil\frac\Delta 2\rceil` sets `C_1,\dots,C_r` such that for all `i`, the set `C_i` is a graph of maximal degree `2` (a disjoint union of paths and cycles). diff --git a/src/sage/graphs/graph_coloring.pyx b/src/sage/graphs/graph_coloring.pyx index 3f8c892f30e..b650822bca7 100644 --- a/src/sage/graphs/graph_coloring.pyx +++ b/src/sage/graphs/graph_coloring.pyx @@ -1320,7 +1320,7 @@ def edge_coloring(g, value_only=False, vizing=False, hex_colors=False, solver=No - When set to ``False``, tries to find a `\Delta`-edge-coloring using Mixed Integer Linear Programming (MILP). If impossible, returns a - `(\Delta + 1)`-edge-coloring. Please note that determinating if the + `(\Delta + 1)`-edge-coloring. Please note that determining if the chromatic index of a graph equals `\Delta` is computationally difficult, and could take a long time. diff --git a/src/sage/graphs/orientations.py b/src/sage/graphs/orientations.py index 1ecb283ba2a..923ed9d2874 100644 --- a/src/sage/graphs/orientations.py +++ b/src/sage/graphs/orientations.py @@ -80,7 +80,7 @@ def acyclic_orientations(G): sage: len(list(it)) 54 - Test for arbitary vertex labels:: + Test for arbitrary vertex labels:: sage: g_str = Graph([('abc', 'def'), ('ghi', 'def'), ('xyz', 'abc'), ('xyz', 'uvw'), ('uvw', 'abc'), ('uvw', 'ghi')]) sage: it = g_str.acyclic_orientations() diff --git a/src/sage/graphs/pq_trees.py b/src/sage/graphs/pq_trees.py index 016336f7405..fe7b00f415f 100644 --- a/src/sage/graphs/pq_trees.py +++ b/src/sage/graphs/pq_trees.py @@ -245,7 +245,7 @@ def reorder_sets(sets): EXAMPLES: There is only one way (up to reversal) to represent contiguously - the sequence ofsets `\{i-1, i, i+1\}`:: + the sequence of sets `\{i-1, i, i+1\}`:: sage: from sage.graphs.pq_trees import reorder_sets sage: seq = [Set([i-1,i,i+1]) for i in range(1,15)] @@ -401,9 +401,9 @@ def ordering(self): return value - def __repr__(self): + def __repr__(self) -> str: r""" - Succintly represents ``self``. + Succinctly represents ``self``. EXAMPLES:: diff --git a/src/sage/graphs/strongly_regular_db.pyx b/src/sage/graphs/strongly_regular_db.pyx index ac26256a1d3..b11ad677a83 100644 --- a/src/sage/graphs/strongly_regular_db.pyx +++ b/src/sage/graphs/strongly_regular_db.pyx @@ -1058,7 +1058,7 @@ def is_polhill(int v, int k, int l, int mu): [(1, 2), (3, 2), (2, 1), (2, 3), (2, 2)]] D = [[G(e) for e in x] for x in D] - # The K_i are hyperplanes partitionning the nonzero elements of + # The K_i are hyperplanes partitioning the nonzero elements of # GF(2^s)^2. See section 6. s = 3 G1 = GF(2**s,'x') diff --git a/src/sage/graphs/views.pyx b/src/sage/graphs/views.pyx index 95da1be4b64..8dd73c928d4 100644 --- a/src/sage/graphs/views.pyx +++ b/src/sage/graphs/views.pyx @@ -204,7 +204,7 @@ cdef class EdgesView: sage: G.has_edge(1, 0) False - We can consider only the edges between two specifed sets of vertices:: + We can consider only the edges between two specified sets of vertices:: sage: G = Graph([(0, 1), (1, 2)]) sage: E = EdgesView(G, vertices=[0], vertices2=[1], labels=False) diff --git a/src/sage/libs/coxeter3/coxeter.pyx b/src/sage/libs/coxeter3/coxeter.pyx index 0ce4f0a9b10..655fc65545c 100644 --- a/src/sage/libs/coxeter3/coxeter.pyx +++ b/src/sage/libs/coxeter3/coxeter.pyx @@ -944,7 +944,7 @@ cdef class CoxGroupElement: def is_two_sided_descent(self, s): """ - Return whether ``s`` is a two sided descent of ``self``. + Return whether ``s`` is a two-sided descent of ``self``. EXAMPLES:: From ff4d7ebbc5367205bf257ee512914c70bf7b451d Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 29 Jun 2024 01:28:00 -0700 Subject: [PATCH 163/231] build/pkgs/libffi: Update to 3.4.6 --- build/pkgs/libffi/checksums.ini | 5 +++-- build/pkgs/libffi/package-version.txt | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/build/pkgs/libffi/checksums.ini b/build/pkgs/libffi/checksums.ini index 327da6eed8b..73ac72b3952 100644 --- a/build/pkgs/libffi/checksums.ini +++ b/build/pkgs/libffi/checksums.ini @@ -1,3 +1,4 @@ tarball=libffi-VERSION.tar.gz -sha1=280c265b789e041c02e5c97815793dfc283fb1e6 -sha256=d06ebb8e1d9a22d19e38d63fdb83954253f39bedc5d46232a05645685722ca37 +sha1=19251dfee520dff42acefe36bfe76d7168071e01 +sha256=b0dea9df23c863a7a50e825440f3ebffabd65df1497108e5d437747843895a4e +upstream_url=https://github.com/libffi/libffi/releases/download/vVERSION/libffi-VERSION.tar.gz diff --git a/build/pkgs/libffi/package-version.txt b/build/pkgs/libffi/package-version.txt index e4604e3afd0..1cf8253024c 100644 --- a/build/pkgs/libffi/package-version.txt +++ b/build/pkgs/libffi/package-version.txt @@ -1 +1 @@ -3.2.1 +3.4.6 From 58fc47956f530cd56fda985c5582550c0b0677e4 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 29 Jun 2024 01:29:06 -0700 Subject: [PATCH 164/231] build/pkgs/libffi/patches: Remove --- ...ffi-3.2.1-disable-multi-os-directory.patch | 89 ------------------- 1 file changed, 89 deletions(-) delete mode 100644 build/pkgs/libffi/patches/libffi-3.2.1-disable-multi-os-directory.patch diff --git a/build/pkgs/libffi/patches/libffi-3.2.1-disable-multi-os-directory.patch b/build/pkgs/libffi/patches/libffi-3.2.1-disable-multi-os-directory.patch deleted file mode 100644 index d3c250534fb..00000000000 --- a/build/pkgs/libffi/patches/libffi-3.2.1-disable-multi-os-directory.patch +++ /dev/null @@ -1,89 +0,0 @@ -Issue #27109: Patch based on the upstream fix at -https://github.com/libffi/libffi/commit/877ea9bf9ac2c98cb858c12f5a6aeeec13cf978f#diff-67e997bcfdac55191033d57a16d1408a - -Ensure that libraries are installed to $SAGE_LOCAL/lib and not -$SAGE_LOCAL/lib/$(gcc -print-multi-os-directory) which on some Linuxes -returns things like "../lib64" ---- libffi-3.2.1-orig/configure.ac 2014-11-12 05:56:51.000000000 -0600 -+++ libffi-3.2.1/configure.ac 2015-10-29 15:53:41.695055040 -0500 -@@ -590,6 +590,10 @@ - AC_DEFINE(USING_PURIFY, 1, [Define this if you are using Purify and want to suppress spurious messages.]) - fi) - -+AC_ARG_ENABLE(multi-os-directory, -+[ --disable-multi-os-directory -+ disable use of gcc --print-multi-os-directory to change the library installation directory]) -+ - # These variables are only ever used when we cross-build to X86_WIN32. - # And we only support this with GCC, so... - if test "x$GCC" = "xyes"; then -@@ -601,11 +605,13 @@ - toolexecdir="${libdir}"/gcc-lib/'$(target_alias)' - toolexeclibdir="${libdir}" - fi -- multi_os_directory=`$CC $CFLAGS -print-multi-os-directory` -- case $multi_os_directory in -- .) ;; # Avoid trailing /. -- ../*) toolexeclibdir=$toolexeclibdir/$multi_os_directory ;; -- esac -+ if test x"$enable_multi_os_directory" != x"no"; then -+ multi_os_directory=`$CC $CFLAGS -print-multi-os-directory` -+ case $multi_os_directory in -+ .) ;; # Avoid trailing /. -+ ../*) toolexeclibdir=$toolexeclibdir/$multi_os_directory ;; -+ esac -+ fi - AC_SUBST(toolexecdir) - else - toolexeclibdir="${libdir}" ---- libffi-3.2.1-orig/configure 2014-11-12 11:59:57.000000000 +0000 -+++ libffi-3.2.1/configure 2015-10-30 19:50:51.082221000 +0000 -@@ -886,6 +886,7 @@ - enable_structs - enable_raw_api - enable_purify_safety -+enable_multi_os_directory - ' - ac_precious_vars='build_alias - host_alias -@@ -1538,6 +1539,8 @@ - --disable-structs omit code for struct support - --disable-raw-api make the raw api unavailable - --enable-purify-safety purify-safe mode -+ --disable-multi-os-directory -+ disable use of gcc --print-multi-os-directory to change the library installation directory - - Optional Packages: - --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] -@@ -18714,6 +18717,12 @@ - fi - - -+# Check whether --enable-multi-os-directory was given. -+if test "${enable_multi_os_directory+set}" = set; then : -+ enableval=$enable_multi_os_directory; -+fi -+ -+ - # These variables are only ever used when we cross-build to X86_WIN32. - # And we only support this with GCC, so... - if test "x$GCC" = "xyes"; then -@@ -18725,11 +18734,13 @@ - toolexecdir="${libdir}"/gcc-lib/'$(target_alias)' - toolexeclibdir="${libdir}" - fi -- multi_os_directory=`$CC $CFLAGS -print-multi-os-directory` -- case $multi_os_directory in -- .) ;; # Avoid trailing /. -- ../*) toolexeclibdir=$toolexeclibdir/$multi_os_directory ;; -- esac -+ if test x"$enable_multi_os_directory" != x"no"; then -+ multi_os_directory=`$CC $CFLAGS -print-multi-os-directory` -+ case $multi_os_directory in -+ .) ;; # Avoid trailing /. -+ ../*) toolexeclibdir=$toolexeclibdir/$multi_os_directory ;; -+ esac -+ fi - - else - toolexeclibdir="${libdir}" From 57562d06740500a74e142bce46560e7cd4d525f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sun, 30 Jun 2024 11:50:17 +0200 Subject: [PATCH 165/231] fix typos and code details in Hecke triangle groups --- src/sage/misc/c3_controlled.pyx | 6 +- .../modform_hecketriangle/abstract_ring.py | 2 +- .../modform_hecketriangle/abstract_space.py | 59 +++++++++---------- .../modform_hecketriangle/constructor.py | 3 +- .../hecke_triangle_group_element.py | 15 ++--- .../hecke_triangle_groups.py | 6 +- .../series_constructor.py | 39 ++++++------ .../modular/modform_hecketriangle/subspace.py | 6 +- 8 files changed, 65 insertions(+), 71 deletions(-) diff --git a/src/sage/misc/c3_controlled.pyx b/src/sage/misc/c3_controlled.pyx index 5787505313c..518e321c197 100644 --- a/src/sage/misc/c3_controlled.pyx +++ b/src/sage/misc/c3_controlled.pyx @@ -155,7 +155,7 @@ class as its bases. However, this would have several drawbacks: point of truth for calculating the bases of each class. - It increases the complexity of the calculation of the MRO with - ``C3``. For example, for a linear hierachy of classes, the + ``C3``. For example, for a linear hierarchy of classes, the complexity goes from `O(n^2)` to `O(n^3)` which is not acceptable. - It increases the complexity of inspecting the classes. For example, @@ -913,7 +913,7 @@ cpdef tuple C3_sorted_merge(list lists, key=identity): tailsets[-1].add(key(heads[-1])) heads[-1] = O elif O != heads[-1]: - assert O_key not in tailsets[-1], "C3 should not have choosen this O" + assert O_key not in tailsets[-1], "C3 should not have chosen this O" # Use a heap or something for fast sorted insertion? # Since Python uses TimSort, that's probably not so bad. tails[-1].append(O) @@ -992,7 +992,7 @@ class HierarchyElement(object, metaclass=ClasscallMetaclass): EXAMPLES: See the introduction of this module :mod:`sage.misc.c3_controlled` - for many examples. Here we consider a large example, originaly + for many examples. Here we consider a large example, originally taken from the hierarchy of categories above :class:`HopfAlgebrasWithBasis`:: diff --git a/src/sage/modular/modform_hecketriangle/abstract_ring.py b/src/sage/modular/modform_hecketriangle/abstract_ring.py index f1f0efad596..b0bf6a850a3 100644 --- a/src/sage/modular/modform_hecketriangle/abstract_ring.py +++ b/src/sage/modular/modform_hecketriangle/abstract_ring.py @@ -1793,7 +1793,7 @@ def EisensteinSeries(self, k=None): - ``k`` -- A non-negative even integer, namely the weight. If ``k=None`` (default) then the weight of ``self`` - is choosen if ``self`` is homogeneous and the + is chosen if ``self`` is homogeneous and the weight is possible, otherwise ``k=0`` is set. OUTPUT: diff --git a/src/sage/modular/modform_hecketriangle/abstract_space.py b/src/sage/modular/modform_hecketriangle/abstract_space.py index 719d8847f31..c60e2b0c4f7 100644 --- a/src/sage/modular/modform_hecketriangle/abstract_space.py +++ b/src/sage/modular/modform_hecketriangle/abstract_space.py @@ -697,7 +697,7 @@ def weight_parameters(self): # l2 = num % ZZ(2) # l1 = ((num-l2)/ZZ(2)).numerator() # TODO: The correct generalization seems (l1,l2) = (0,num) - l2 = ZZ(0) + l2 = ZZ.zero() l1 = num else: l2 = num % n @@ -769,7 +769,7 @@ def aut_factor(self, gamma, t): return aut_f @cached_method - def F_simple(self, order_1=ZZ(0)): + def F_simple(self, order_1=ZZ.zero()): r""" Return a (the most) simple normalized element of ``self`` corresponding to the weight parameters ``l1=self._l1`` and @@ -836,7 +836,7 @@ def F_simple(self, order_1=ZZ(0)): return new_space(rat) - def Faber_pol(self, m, order_1=ZZ(0), fix_d=False, d_num_prec=None): + def Faber_pol(self, m, order_1=ZZ.zero(), fix_d=False, d_num_prec=None): r""" Return the ``m``'th Faber polynomial of ``self``. @@ -986,7 +986,7 @@ def Faber_pol(self, m, order_1=ZZ(0), fix_d=False, d_num_prec=None): return fab_pol.polynomial() # very similar to Faber_pol: faber_pol(q)=Faber_pol(d*q) - def faber_pol(self, m, order_1=ZZ(0), fix_d=False, d_num_prec=None): + def faber_pol(self, m, order_1=ZZ.zero(), fix_d=False, d_num_prec=None): r""" If ``n=infinity`` a non-trivial order of ``-1`` can be specified through the parameter ``order_1`` (default: 0). Otherwise it is ignored. @@ -1127,7 +1127,7 @@ def faber_pol(self, m, order_1=ZZ(0), fix_d=False, d_num_prec=None): return fab_pol.polynomial() - def F_basis_pol(self, m, order_1=ZZ(0)): + def F_basis_pol(self, m, order_1=ZZ.zero()): r""" Returns a polynomial corresponding to the basis element of the corresponding space of weakly holomorphic forms of @@ -1229,7 +1229,7 @@ def F_basis_pol(self, m, order_1=ZZ(0)): return rat - def F_basis(self, m, order_1=ZZ(0)): + def F_basis(self, m, order_1=ZZ.zero()): r""" Returns a weakly holomorphic element of ``self`` (extended if necessarily) determined by the property that @@ -1357,11 +1357,11 @@ def _canonical_min_exp(self, min_exp, order_1): order_1 = max(order_1, 0) if (self.hecke_n() != infinity): - order_1 = ZZ(0) + order_1 = ZZ.zero() return (min_exp, order_1) - def quasi_part_gens(self, r=None, min_exp=0, max_exp=infinity, order_1=ZZ(0)): + def quasi_part_gens(self, r=None, min_exp=0, max_exp=infinity, order_1=ZZ.zero()): r""" Return a basis in ``self`` of the subspace of (quasi) weakly holomorphic forms which satisfy the specified properties on @@ -1372,7 +1372,7 @@ def quasi_part_gens(self, r=None, min_exp=0, max_exp=infinity, order_1=ZZ(0)): - ``r`` -- An integer or ``None`` (default), indicating the desired power of ``E2`` If ``r=None`` then all possible powers (``r``) are - choosen. + chosen. - ``min_exp`` -- An integer giving a lower bound for the first non-trivial Fourier coefficient of the @@ -1499,14 +1499,14 @@ def quasi_part_gens(self, r=None, min_exp=0, max_exp=infinity, order_1=ZZ(0)): max_numerator_weight = self._weight - 4*n/(n-2)*min_exp + 4 # If r is not specified we gather all generators for all possible r's - if (r is None): + if r is None: gens = [] - for rnew in range(ZZ(0), QQ(max_numerator_weight/ZZ(2)).floor() + 1): + for rnew in range(QQ(max_numerator_weight/ZZ(2)).floor() + 1): gens += self.quasi_part_gens(r=rnew, min_exp=min_exp, max_exp=max_exp, order_1=order_1) return gens r = ZZ(r) - if (r < 0 or 2*r > max_numerator_weight): + if r < 0 or 2*r > max_numerator_weight: return [] E2 = self.E2() @@ -1526,7 +1526,7 @@ def quasi_part_gens(self, r=None, min_exp=0, max_exp=infinity, order_1=ZZ(0)): return gens - def quasi_part_dimension(self, r=None, min_exp=0, max_exp=infinity, order_1=ZZ(0)): + def quasi_part_dimension(self, r=None, min_exp=0, max_exp=infinity, order_1=ZZ.zero()): r""" Return the dimension of the subspace of ``self`` generated by ``self.quasi_part_gens(r, min_exp, max_exp, order_1)``. @@ -1590,10 +1590,10 @@ def quasi_part_dimension(self, r=None, min_exp=0, max_exp=infinity, order_1=ZZ(0 (min_exp, order_1) = self._canonical_min_exp(min_exp, order_1) # For modular forms spaces the quasi parts are all zero except for r=0 - if (self.is_modular()): - r = ZZ(0) - if (r != 0): - return ZZ(0) + if self.is_modular(): + r = ZZ.zero() + if r != 0: + return ZZ.zero() # The lower bounds on the powers of f_inf and E4 determine # how large powers of E2 we can fit in... @@ -1604,12 +1604,12 @@ def quasi_part_dimension(self, r=None, min_exp=0, max_exp=infinity, order_1=ZZ(0 max_numerator_weight = self._weight - 4*n/(n-2)*min_exp + 4 # If r is not specified we calculate the total dimension over all possible r's - if (r is None): - return sum([self.quasi_part_dimension(r=rnew, min_exp=min_exp, max_exp=max_exp, order_1=order_1) for rnew in range(ZZ(0), QQ(max_numerator_weight/ZZ(2)).floor() + 1)]) + if r is None: + return sum([self.quasi_part_dimension(r=rnew, min_exp=min_exp, max_exp=max_exp, order_1=order_1) for rnew in range(QQ(max_numerator_weight/ZZ(2)).floor() + 1)]) r = ZZ(r) if (r < 0 or 2*r > max_numerator_weight): - return ZZ(0) + return ZZ.zero() k = self._weight - QQ(2*r) ep = self._ep * (-1)**r @@ -1625,13 +1625,13 @@ def quasi_part_dimension(self, r=None, min_exp=0, max_exp=infinity, order_1=ZZ(0 if (max_exp == infinity): max_exp = order_inf elif (max_exp < min_exp): - return ZZ(0) + return ZZ.zero() else: max_exp = min(ZZ(max_exp), order_inf) - return max(ZZ(0), max_exp - min_exp + 1) + return max(ZZ.zero(), max_exp - min_exp + 1) - def construct_form(self, laurent_series, order_1=ZZ(0), check=True, rationalize=False): + def construct_form(self, laurent_series, order_1=ZZ.zero(), check=True, rationalize=False): r""" Tries to construct an element of self with the given Fourier expansion. The assumption is made that the specified Fourier @@ -1755,7 +1755,7 @@ def construct_form(self, laurent_series, order_1=ZZ(0), check=True, rationalize= return el @cached_method - def _quasi_form_matrix(self, min_exp=0, order_1=ZZ(0), incr_prec_by=0): + def _quasi_form_matrix(self, min_exp=0, order_1=ZZ.zero(), incr_prec_by=0): r""" Return a base change matrix which transforms coordinate vectors with respect to a certain basis into a vector corresponding to @@ -1866,7 +1866,7 @@ def _quasi_form_matrix(self, min_exp=0, order_1=ZZ(0), incr_prec_by=0): return A - def required_laurent_prec(self, min_exp=0, order_1=ZZ(0)): + def required_laurent_prec(self, min_exp=0, order_1=ZZ.zero()): r""" Return an upper bound for the required precision for Laurent series to uniquely determine a corresponding (quasi) form in ``self`` with the given @@ -1913,7 +1913,7 @@ def required_laurent_prec(self, min_exp=0, order_1=ZZ(0)): return self._quasi_form_matrix(min_exp=min_exp, order_1=order_1).dimensions()[0] + min_exp - def construct_quasi_form(self, laurent_series, order_1=ZZ(0), check=True, rationalize=False): + def construct_quasi_form(self, laurent_series, order_1=ZZ.zero(), check=True, rationalize=False): r""" Try to construct an element of self with the given Fourier expansion. The assumption is made that the specified Fourier @@ -2072,7 +2072,7 @@ def construct_quasi_form(self, laurent_series, order_1=ZZ(0), check=True, ration return el @cached_method - def q_basis(self, m=None, min_exp=0, order_1=ZZ(0)): + def q_basis(self, m=None, min_exp=0, order_1=ZZ.zero()): r""" Try to return a (basis) element of ``self`` with a Laurent series of the form ``q^m + O(q^N)``, where ``N=self.required_laurent_prec(min_exp)``. @@ -2380,10 +2380,9 @@ def _an_element_(self): sage: el O(q^5) """ - # this seems ok, so might as well leave it as is for everything - return self(ZZ(0)) - #return self.F_simple() + return self(ZZ.zero()) + # return self.F_simple() @cached_method def dimension(self): diff --git a/src/sage/modular/modform_hecketriangle/constructor.py b/src/sage/modular/modform_hecketriangle/constructor.py index 309a024c43a..0f40b4e4a35 100644 --- a/src/sage/modular/modform_hecketriangle/constructor.py +++ b/src/sage/modular/modform_hecketriangle/constructor.py @@ -67,12 +67,11 @@ def rational_type(f, n=ZZ(3), base_ring=ZZ): - ``analytic_type`` -- The :class:`AnalyticType` of `f`. - For the zero function the degree `(0, 1)` is choosen. + For the zero function the degree `(0, 1)` is chosen. This function is (heavily) used to determine the type of elements and to check if the element really is contained in its parent. - EXAMPLES:: sage: from sage.modular.modform_hecketriangle.constructor import rational_type diff --git a/src/sage/modular/modform_hecketriangle/hecke_triangle_group_element.py b/src/sage/modular/modform_hecketriangle/hecke_triangle_group_element.py index c2938e444a0..cc88da2542e 100644 --- a/src/sage/modular/modform_hecketriangle/hecke_triangle_group_element.py +++ b/src/sage/modular/modform_hecketriangle/hecke_triangle_group_element.py @@ -1074,7 +1074,7 @@ def primitive_part(self, method="cf"): is +- the identity (to correct the sign) and ``power = self.primitive_power()``. - The primitive part itself is choosen such that it cannot be + The primitive part itself is chosen 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. @@ -1167,7 +1167,7 @@ def reduce(self, primitive=True): If ``self`` is elliptic (or +- the identity) the result is never reduced (by definition). Instead a more canonical conjugation representative of ``self`` (resp. it's - primitive part) is choosen. + primitive part) is chosen. Warning: The case ``n=infinity`` is not verified at all and probably wrong! @@ -1379,7 +1379,8 @@ def primitive_power(self, method="cf"): return j elif two*j == G.n(): return j - # for the cases fom here on the sign has to be adjusted to the + # for the cases from here on the sign has to be adjusted + # to the # sign of self (in self._block_decomposition_data()) elif two*j == -G.n(): return -j @@ -1433,7 +1434,7 @@ def block_length(self, primitive=False): 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 + with minimal absolute value is chosen. For +- the identity element ``0`` is returned. EXAMPLES:: @@ -2956,7 +2957,7 @@ def fixed_points(self, embedded=False, order="default"): - ``embedded`` -- If ``True``, the fixed points are embedded into ``AlgebraicRealField`` resp. ``AlgebraicField``. Default: ``False``. - - ``order`` -- If ``order="none"`` the fixed points are choosen + - ``order`` -- If ``order="none"`` the fixed points are chosen and ordered according to a fixed formula. If ``order="sign"`` the fixed points are always ordered @@ -2979,9 +2980,9 @@ def fixed_points(self, embedded=False, order="default"): ``AlgebraicField`` is returned. Otherwise an element of a relative field extension over the base field of (the parent of) ``self`` is returned. - Warning: Relative field extensions don't support default embeddings. + Warning: Relative field extensions do not support default embeddings. So the correct embedding (which is the positive resp. imaginary positive - one) has to be choosen. + one) has to be chosen. EXAMPLES:: diff --git a/src/sage/modular/modform_hecketriangle/hecke_triangle_groups.py b/src/sage/modular/modform_hecketriangle/hecke_triangle_groups.py index 17ee69ec123..aea71efb49e 100644 --- a/src/sage/modular/modform_hecketriangle/hecke_triangle_groups.py +++ b/src/sage/modular/modform_hecketriangle/hecke_triangle_groups.py @@ -122,7 +122,7 @@ def _repr_(self): sage: HeckeTriangleGroup(10) Hecke triangle group for n = 10 """ - return "Hecke triangle group for n = {}".format(self._n) + return f"Hecke triangle group for n = {self._n}" def _latex_(self): r""" @@ -1261,7 +1261,7 @@ def list_discriminants(self, D, primitive=True, hyperbolic=True, incomplete=Fals - ``incomplete`` -- If ``True`` (default: ``False``) then all (also higher) discriminants which were gathered so far are listed - (however there might be missing discriminants inbetween). + (however there might be missing discriminants in between). OUTPUT: @@ -1412,7 +1412,7 @@ def rational_period_functions(self, k, D): if not ZZ(2).divides(k): raise TypeError except TypeError: - raise ValueError("k={} has to be an even integer!".format(k)) + raise ValueError(f"k={k} has to be an even integer!") z = PolynomialRing(self.base_ring(), 'z').gen() diff --git a/src/sage/modular/modform_hecketriangle/series_constructor.py b/src/sage/modular/modform_hecketriangle/series_constructor.py index b44f41a09a0..50a1adbc7f0 100644 --- a/src/sage/modular/modform_hecketriangle/series_constructor.py +++ b/src/sage/modular/modform_hecketriangle/series_constructor.py @@ -210,29 +210,24 @@ def J_inv_ZZ(self): sage: MFSeriesConstructor(group=infinity, prec=3).J_inv_ZZ() q^-1 + 3/8 + 69/1024*q + O(q^2) """ - - F1 = lambda a,b: self._series_ring( - [ ZZ(0) ] - + [ - rising_factorial(a,k) * rising_factorial(b,k) / (ZZ(k).factorial())**2 - * sum(ZZ(1)/(a+j) + ZZ(1)/(b+j) - ZZ(2)/ZZ(1+j) - for j in range(ZZ(0),ZZ(k)) - ) - for k in range(ZZ(1), ZZ(self._prec+1)) - ], - ZZ(self._prec+1) - ) - - F = lambda a,b,c: self._series_ring( - [ - rising_factorial(a,k) * rising_factorial(b,k) / rising_factorial(c,k) / ZZ(k).factorial() - for k in range(ZZ(0), ZZ(self._prec+1)) - ], - ZZ(self._prec+1) - ) + F1 = lambda a, b: self._series_ring( + [ZZ.zero()] + + [rising_factorial(a,k) * rising_factorial(b,k) / (ZZ(k).factorial())**2 + * sum(ZZ.one()/(a+j) + ZZ.one()/(b+j) - ZZ(2)/ZZ(1+j) + for j in range(k)) + for k in range(1, self._prec+1) + ], + ZZ(self._prec+1) + ) + + F = lambda a, b, c: self._series_ring( + [rising_factorial(a,k) * rising_factorial(b,k) / rising_factorial(c,k) / ZZ(k).factorial() + for k in range(self._prec+1)], + ZZ(self._prec+1) + ) a = self._group.alpha() b = self._group.beta() - Phi = F1(a,b) / F(a,b,ZZ(1)) + Phi = F1(a, b) / F(a, b, ZZ.one()) q = self._series_ring.gen() # the current implementation of power series reversion is slow @@ -240,7 +235,7 @@ def J_inv_ZZ(self): temp_f = (q*Phi.exp()).polynomial() new_f = temp_f.revert_series(temp_f.degree()+1) - J_inv_ZZ = ZZ(1) / (new_f + O(q**(temp_f.degree()+1))) + J_inv_ZZ = ZZ.one() / (new_f + O(q**(temp_f.degree()+1))) return J_inv_ZZ diff --git a/src/sage/modular/modform_hecketriangle/subspace.py b/src/sage/modular/modform_hecketriangle/subspace.py index aa16edabc04..692fcbfc9ec 100644 --- a/src/sage/modular/modform_hecketriangle/subspace.py +++ b/src/sage/modular/modform_hecketriangle/subspace.py @@ -59,7 +59,7 @@ def ModularFormsSubSpace(*args, **kwargs): r""" Create a modular forms subspace generated by the supplied arguments if possible. Instead of a list of generators also multiple input arguments can be used. - If ``reduce=True`` then the corresponding ambient space is choosen as small as possible. + If ``reduce=True`` then the corresponding ambient space is chosen as small as possible. If no subspace is available then the ambient space is returned. EXAMPLES:: @@ -147,7 +147,7 @@ def __init__(self, ambient_space, basis, check): elements of ``ambient_space``. - ``check`` -- If ``True`` (default) then a maximal linearly - independent subset of ``basis`` is choosen. Otherwise + independent subset of ``basis`` is chosen. Otherwise it is assumed that ``basis`` is linearly independent. OUTPUT: @@ -230,7 +230,7 @@ def _repr_(self): # If we list the basis the representation usually gets too long... # return "Subspace with basis {} of {}".format([v.as_ring_element() for v in self.basis()], self._ambient_space) - return "Subspace of dimension {} of {}".format(len(self._basis), self._ambient_space) + return f"Subspace of dimension {len(self._basis)} of {self._ambient_space}" def change_ring(self, new_base_ring): r""" From c71c9d47e942db73006354e8c1ec1d20af385fb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sun, 30 Jun 2024 20:41:21 +0200 Subject: [PATCH 166/231] adding a few more links to python standard errors in doc --- src/sage/schemes/elliptic_curves/ell_field.py | 2 +- .../elliptic_curves/ell_finite_field.py | 6 ++--- .../schemes/elliptic_curves/ell_generic.py | 4 +-- .../elliptic_curves/ell_number_field.py | 2 +- .../elliptic_curves/ell_rational_field.py | 10 +++++--- .../elliptic_curves/gal_reps_number_field.py | 2 +- src/sage/schemes/elliptic_curves/heegner.py | 3 ++- .../schemes/elliptic_curves/lseries_ell.py | 6 ++--- src/sage/structure/element.pyx | 25 ++++++++++--------- src/sage/structure/list_clone.pyx | 2 +- src/sage/structure/parent.pyx | 2 +- src/sage/symbolic/assumptions.py | 6 ++--- src/sage/symbolic/comparison_impl.pxi | 8 +++--- src/sage/symbolic/pynac_function_impl.pxi | 2 +- src/sage/symbolic/random_tests.py | 2 +- 15 files changed, 44 insertions(+), 38 deletions(-) diff --git a/src/sage/schemes/elliptic_curves/ell_field.py b/src/sage/schemes/elliptic_curves/ell_field.py index 237c838b3d4..cf5df9c9b7e 100644 --- a/src/sage/schemes/elliptic_curves/ell_field.py +++ b/src/sage/schemes/elliptic_curves/ell_field.py @@ -2129,7 +2129,7 @@ def hasse_invariant(self): characteristic, and is an element of the field which is zero if and only if the curve is supersingular. Over a field of characteristic zero, where the Hasse invariant is undefined, - a ``ValueError`` is raised. + a :class:`ValueError` is raised. EXAMPLES:: diff --git a/src/sage/schemes/elliptic_curves/ell_finite_field.py b/src/sage/schemes/elliptic_curves/ell_finite_field.py index a6e9cf2e845..e285f473cb7 100644 --- a/src/sage/schemes/elliptic_curves/ell_finite_field.py +++ b/src/sage/schemes/elliptic_curves/ell_finite_field.py @@ -444,7 +444,7 @@ def cardinality(self, algorithm=None, extension_degree=1): - ``'all'`` -- compute cardinality with both ``'pari'`` and ``'bsgs'``; return result if they agree or raise a - ``AssertionError`` if they do not + :class:`AssertionError` if they do not - ``extension_degree`` -- an integer `d` (default: 1): if the base field is `\GF{q}`, return the cardinality of ``self`` @@ -1612,7 +1612,7 @@ def endomorphism_discriminant_from_class_number(self, h): (integer) The discriminant of the endomorphism ring `\text{End}(E)`, if this has class number ``h``. If `\text{End}(E)` does not have class - number ``h``, a ``ValueError`` is raised. + number ``h``, a :class:`ValueError` is raised. ALGORITHM: @@ -1622,7 +1622,7 @@ def endomorphism_discriminant_from_class_number(self, h): must be a multiple of `h_0`, compute the possible conductors, using :meth:`height_above_floor` for each prime `\ell` dividing the quotient `h/h_0`. If exactly one conductor `f` - remains, return `f^2D_0`, otherwise raise a ``ValueError``; + remains, return `f^2D_0`, otherwise raise a :class:`ValueError`; this can onlyhappen when the input value of `h` was incorrect. .. NOTE:: diff --git a/src/sage/schemes/elliptic_curves/ell_generic.py b/src/sage/schemes/elliptic_curves/ell_generic.py index 16347cc6a6f..bd08abf3c2e 100644 --- a/src/sage/schemes/elliptic_curves/ell_generic.py +++ b/src/sage/schemes/elliptic_curves/ell_generic.py @@ -2701,8 +2701,8 @@ def isomorphism_to(self, other): .. NOTE:: - If the curves in question are not isomorphic, a ``ValueError`` - is raised. + If the curves in question are not isomorphic, + a :class:`ValueError` is raised. EXAMPLES:: diff --git a/src/sage/schemes/elliptic_curves/ell_number_field.py b/src/sage/schemes/elliptic_curves/ell_number_field.py index a139cab50ce..c99da8b72b2 100644 --- a/src/sage/schemes/elliptic_curves/ell_number_field.py +++ b/src/sage/schemes/elliptic_curves/ell_number_field.py @@ -1628,7 +1628,7 @@ def non_minimal_primes(self): sage: Emin.non_minimal_primes() [] - If the model is not globally integral, a ``ValueError`` is + If the model is not globally integral, a :class:`ValueError` is raised:: sage: E = EllipticCurve([0, 0, 0, 1/2, 1/3]) diff --git a/src/sage/schemes/elliptic_curves/ell_rational_field.py b/src/sage/schemes/elliptic_curves/ell_rational_field.py index 1dba8a94ba1..50e92adfd76 100644 --- a/src/sage/schemes/elliptic_curves/ell_rational_field.py +++ b/src/sage/schemes/elliptic_curves/ell_rational_field.py @@ -694,7 +694,9 @@ def database_attributes(self): def database_curve(self): r""" Return the curve in the elliptic curve database isomorphic to this - curve, if possible. Otherwise raise a ``LookupError`` exception. + curve, if possible. + + Otherwise this raises a :class:`LookupError` exception. Since :issue:`11474`, this returns exactly the same curve as :meth:`minimal_model`; the only difference is the additional @@ -1515,7 +1517,7 @@ def analytic_rank(self, algorithm="pari", leading_coefficient=False): TESTS: When the input is horrendous, some of the algorithms just bomb - out with a ``RuntimeError``:: + out with a :class:`RuntimeError`:: sage: EllipticCurve([1234567,89101112]).analytic_rank(algorithm='rubinstein') Traceback (most recent call last): @@ -4100,7 +4102,9 @@ def congruence_number(self, M=1): def cremona_label(self, space=False): r""" Return the Cremona label associated to (the minimal model) of this - curve, if it is known. If not, raise a ``LookupError`` exception. + curve, if it is known. + + If not, this raises a :class:`LookupError` exception. EXAMPLES:: diff --git a/src/sage/schemes/elliptic_curves/gal_reps_number_field.py b/src/sage/schemes/elliptic_curves/gal_reps_number_field.py index e049b72fa76..29b06c438ba 100644 --- a/src/sage/schemes/elliptic_curves/gal_reps_number_field.py +++ b/src/sage/schemes/elliptic_curves/gal_reps_number_field.py @@ -840,7 +840,7 @@ def _semistable_reducible_primes(E, verbose=False): A list of primes, which contains all primes `l` unramified in `K/\mathbb{QQ}`, such that `E` is semistable at all primes lying over `l`, and the Galois image at `l` is reducible. If `E` has CM - defined over its ground field, a ``ValueError`` is raised. + defined over its ground field, a :class:`ValueError` is raised. EXAMPLES:: diff --git a/src/sage/schemes/elliptic_curves/heegner.py b/src/sage/schemes/elliptic_curves/heegner.py index 1c4d0505af0..7b014c728ed 100644 --- a/src/sage/schemes/elliptic_curves/heegner.py +++ b/src/sage/schemes/elliptic_curves/heegner.py @@ -566,6 +566,7 @@ def galois_group(self, base=QQ): def is_subfield(self, M): """ Return ``True`` if this ring class field is a subfield of the ring class field `M`. + If `M` is not a ring class field, then a :class:`TypeError` is raised. EXAMPLES:: @@ -706,7 +707,7 @@ def __call__(self, x): - `x` -- automorphism or quadratic field element - OUTPUT: An automorphism (or ``TypeError``) + OUTPUT: An automorphism (or :class:`TypeError`) EXAMPLES:: diff --git a/src/sage/schemes/elliptic_curves/lseries_ell.py b/src/sage/schemes/elliptic_curves/lseries_ell.py index 73fb8a63659..64d267a1251 100644 --- a/src/sage/schemes/elliptic_curves/lseries_ell.py +++ b/src/sage/schemes/elliptic_curves/lseries_ell.py @@ -17,8 +17,8 @@ # Distributed under the terms of the GNU General Public License (GPL) # as published by the Free Software Foundation; either version 2 of # the License, or (at your option) any later version. -# http://www.gnu.org/licenses/ -#***************************************************************************** +# https://www.gnu.org/licenses/ +# **************************************************************************** from sage.structure.sage_object import SageObject from sage.rings.real_mpfr import RealField @@ -143,7 +143,7 @@ def dokchitser(self, prec=53, If the curve has too large a conductor, it is not possible to compute with the `L`-series using this command. Instead a - ``RuntimeError`` is raised:: + :class:`RuntimeError` is raised:: sage: e = EllipticCurve([1,1,0,-63900,-1964465932632]) sage: L = e.lseries().dokchitser(15, algorithm='gp') diff --git a/src/sage/structure/element.pyx b/src/sage/structure/element.pyx index a53c70a3f60..63f55b1f59e 100644 --- a/src/sage/structure/element.pyx +++ b/src/sage/structure/element.pyx @@ -1252,7 +1252,7 @@ cdef class Element(SageObject): This default Cython implementation of ``_add_`` calls the Python method ``self._add_`` if it exists. This method may be defined in the ``ElementMethods`` of the category of the parent. - If the method is not found, a ``TypeError`` is raised + If the method is not found, a :class:`TypeError` is raised indicating that the operation is not supported. See :ref:`element_arithmetic`. @@ -1364,7 +1364,7 @@ cdef class Element(SageObject): This default Cython implementation of ``_sub_`` calls the Python method ``self._sub_`` if it exists. This method may be defined in the ``ElementMethods`` of the category of the parent. - If the method is not found, a ``TypeError`` is raised + If the method is not found, a :class:`TypeError` is raised indicating that the operation is not supported. See :ref:`element_arithmetic`. @@ -1418,7 +1418,7 @@ cdef class Element(SageObject): This default Cython implementation of ``_neg_`` calls the Python method ``self._neg_`` if it exists. This method may be defined in the ``ElementMethods`` of the category of the parent. - If the method is not found, a ``TypeError`` is raised + If the method is not found, a :class:`TypeError` is raised indicating that the operation is not supported. See :ref:`element_arithmetic`. @@ -1532,7 +1532,7 @@ cdef class Element(SageObject): This default Cython implementation of ``_mul_`` calls the Python method ``self._mul_`` if it exists. This method may be defined in the ``ElementMethods`` of the category of the parent. - If the method is not found, a ``TypeError`` is raised + If the method is not found, a :class:`TypeError` is raised indicating that the operation is not supported. See :ref:`element_arithmetic`. @@ -1645,7 +1645,7 @@ cdef class Element(SageObject): This default Cython implementation of ``_matmul_`` calls the Python method ``self._matmul_`` if it exists. This method may be defined in the ``ElementMethods`` of the category of the - parent. If the method is not found, a ``TypeError`` is raised + parent. If the method is not found, a :class:`TypeError` is raised indicating that the operation is not supported. See :ref:`element_arithmetic`. @@ -1748,7 +1748,7 @@ cdef class Element(SageObject): This default Cython implementation of ``_div_`` calls the Python method ``self._div_`` if it exists. This method may be defined in the ``ElementMethods`` of the category of the parent. - If the method is not found, a ``TypeError`` is raised + If the method is not found, a :class:`TypeError` is raised indicating that the operation is not supported. See :ref:`element_arithmetic`. @@ -1848,7 +1848,7 @@ cdef class Element(SageObject): This default Cython implementation of ``_floordiv_`` calls the Python method ``self._floordiv_`` if it exists. This method may be defined in the ``ElementMethods`` of the category of the parent. - If the method is not found, a ``TypeError`` is raised + If the method is not found, a :class:`TypeError` is raised indicating that the operation is not supported. See :ref:`element_arithmetic`. @@ -1948,7 +1948,7 @@ cdef class Element(SageObject): This default Cython implementation of ``_mod_`` calls the Python method ``self._mod_`` if it exists. This method may be defined in the ``ElementMethods`` of the category of the parent. - If the method is not found, a ``TypeError`` is raised + If the method is not found, a :class:`TypeError` is raised indicating that the operation is not supported. See :ref:`element_arithmetic`. @@ -2075,7 +2075,7 @@ cdef class Element(SageObject): This default Cython implementation of ``_pow_`` calls the Python method ``self._pow_`` if it exists. This method may be defined in the ``ElementMethods`` of the category of the parent. - If the method is not found, a ``TypeError`` is raised + If the method is not found, a :class:`TypeError` is raised indicating that the operation is not supported. See :ref:`element_arithmetic`. @@ -2105,7 +2105,7 @@ cdef class Element(SageObject): This default Cython implementation of ``_pow_int`` calls the Python method ``self._pow_int`` if it exists. This method may be defined in the ``ElementMethods`` of the category of the parent. - If the method is not found, a ``TypeError`` is raised + If the method is not found, a :class:`TypeError` is raised indicating that the operation is not supported. See :ref:`element_arithmetic`. @@ -2847,8 +2847,9 @@ cdef class RingElement(ModuleElement): def multiplicative_order(self): r""" - Return the multiplicative order of ``self``, if ``self`` is a unit, - or raise ``ArithmeticError`` otherwise. + Return the multiplicative order of ``self``, if ``self`` is a unit. + + This raise an :class:`ArithmeticError` otherwise. """ if not self.is_unit(): raise ArithmeticError("self (=%s) must be a unit to have a multiplicative order.") diff --git a/src/sage/structure/list_clone.pyx b/src/sage/structure/list_clone.pyx index 5a217166bcd..7363dee36d9 100644 --- a/src/sage/structure/list_clone.pyx +++ b/src/sage/structure/list_clone.pyx @@ -295,7 +295,7 @@ cdef class ClonableElement(Element): """ Check that ``self`` is mutable. - Raise a ``ValueError`` if ``self`` is immutable. + This raises a :class:`ValueError` if ``self`` is immutable. TESTS:: diff --git a/src/sage/structure/parent.pyx b/src/sage/structure/parent.pyx index dd57aa02787..db6e01de40a 100644 --- a/src/sage/structure/parent.pyx +++ b/src/sage/structure/parent.pyx @@ -1418,7 +1418,7 @@ cdef class Parent(sage.structure.category_object.CategoryObject): To: Finite Field of size 5 There might not be a natural morphism, in which case a - ``TypeError`` is raised:: + :class:`TypeError` is raised:: sage: QQ.hom(ZZ) Traceback (most recent call last): diff --git a/src/sage/symbolic/assumptions.py b/src/sage/symbolic/assumptions.py index 9ef8dd39212..755f5b89a4f 100644 --- a/src/sage/symbolic/assumptions.py +++ b/src/sage/symbolic/assumptions.py @@ -461,11 +461,11 @@ def assume(*args): If everything goes as planned, there is no output. If you assume something that is not one of the two forms above, then - an ``AttributeError`` is raised as we try to call its ``assume`` + an :class:`AttributeError` is raised as we try to call its ``assume`` method. If you make inconsistent assumptions (for example, that ``x`` is - both even and odd), then a ``ValueError`` is raised. + both even and odd), then a :class:`ValueError` is raised. .. WARNING:: @@ -630,7 +630,7 @@ def assume(*args): True sage: forget() - Ensure that an ``AttributeError`` is raised if we are given junk:: + Ensure that an :class:`AttributeError` is raised if we are given junk:: sage: assume(3) Traceback (most recent call last): diff --git a/src/sage/symbolic/comparison_impl.pxi b/src/sage/symbolic/comparison_impl.pxi index a1ef76bd778..00cbe88964f 100644 --- a/src/sage/symbolic/comparison_impl.pxi +++ b/src/sage/symbolic/comparison_impl.pxi @@ -189,7 +189,7 @@ class _math_key(): OUTPUT: - Boolean. A ``ValueError`` is raised if we do not know how to + Boolean. A :class:`ValueError` is raised if we do not know how to perform the comparison. EXAMPLES:: @@ -232,7 +232,7 @@ cpdef math_sorted(expressions): The list sorted by ascending (real) value. If an entry does not define a real value (or plus/minus infinity), or if the comparison - is not known, a ``ValueError`` is raised. + is not known, a :class:`ValueError` is raised. EXAMPLES:: @@ -341,7 +341,7 @@ class _mixed_key(): OUTPUT: - Boolean. A ``ValueError`` is raised if we do not know how to + Boolean. A :class:`ValueError` is raised if we do not know how to perform the comparison. EXAMPLES:: @@ -424,7 +424,7 @@ cpdef mixed_sorted(expressions): and the expressions with variables according to print order. If an entry does not define a real value (or plus/minus infinity), or if the comparison - is not known, a ``ValueError`` is raised. + is not known, a :class:`ValueError` is raised. EXAMPLES:: diff --git a/src/sage/symbolic/pynac_function_impl.pxi b/src/sage/symbolic/pynac_function_impl.pxi index 6be7e7d4a16..1cc496ca213 100644 --- a/src/sage/symbolic/pynac_function_impl.pxi +++ b/src/sage/symbolic/pynac_function_impl.pxi @@ -66,7 +66,7 @@ cpdef unsigned find_registered_function(name, int nargs) except -1: r""" Look up a function registered with Pynac (GiNaC). - Raise a ``ValueError`` if the function is not registered. + This raises a :class:`ValueError` if the function is not registered. OUTPUT: diff --git a/src/sage/symbolic/random_tests.py b/src/sage/symbolic/random_tests.py index 6410f797521..fd49cc4cdd9 100644 --- a/src/sage/symbolic/random_tests.py +++ b/src/sage/symbolic/random_tests.py @@ -356,7 +356,7 @@ def assert_strict_weak_order(a, b, c, cmp_func): OUTPUT: - Does not return anything. Raises a ``ValueError`` if ``cmp_func`` + Nothing. This raises a :class:`ValueError` if ``cmp_func`` is not a strict weak order on the three given elements. REFERENCES: From bf8a356a8b7f71484f7ff0e4756eca1af281d2be Mon Sep 17 00:00:00 2001 From: "Kiran S. Kedlaya" Date: Mon, 1 Jul 2024 06:58:13 -0700 Subject: [PATCH 167/231] Implement hypergeometric traces, Euler factors at t=1 --- src/sage/modular/hypergeometric_motive.py | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/sage/modular/hypergeometric_motive.py b/src/sage/modular/hypergeometric_motive.py index 8e726fc877e..a912befc639 100644 --- a/src/sage/modular/hypergeometric_motive.py +++ b/src/sage/modular/hypergeometric_motive.py @@ -1495,10 +1495,12 @@ def H_value(self, p, f, t, ring=None): Using instead :class:`UniversalCyclotomicfield`, this is much slower than the `p`-adic version :meth:`padic_H_value`. + + Unlike in :meth:`padic_H_value`, tame and wild primes are not supported. EXAMPLES: - With values in the UniversalCyclotomicField (slow):: + With values in the ``UniversalCyclotomicField`` (slow):: sage: from sage.modular.hypergeometric_motive import HypergeometricData as Hyp sage: H = Hyp(alpha_beta=([1/2]*4, [0]*4)) @@ -1513,7 +1515,7 @@ def H_value(self, p, f, t, ring=None): sage: [H.H_value(13,i,-1) for i in range(1,3)] # not tested [-84, -1420] - With values in ComplexField:: + With values in ``ComplexField``:: sage: [H.H_value(5,i,-1, ComplexField(60)) for i in range(1,3)] [-4, 276] @@ -1750,7 +1752,7 @@ def euler_factor(self, t, p, deg=None, cache_p=False): INPUT: - - ``t`` -- rational number, not 0 or 1 + - ``t`` -- rational number, not 0 - ``p`` -- prime number of good reduction @@ -1837,6 +1839,15 @@ def euler_factor(self, t, p, deg=None, cache_p=False): sage: H.euler_factor(1/7^4, 7) 7*T^3 + 7*T^2 + T + 1 + This is an example with `t = 1`:: + + sage: H = Hyp(cyclotomic=[[4,2], [3,1]]) + sage: H.euler_factor(1, 7) + -T^2 + 1 + sage: H = Hyp(cyclotomic=[[5], [1,1,1,1]]) + sage: H.euler_factor(1, 7) + 343*T^2 - 6*T + 1 + TESTS:: sage: H1 = Hyp(alpha_beta=([1,1,1], [1/2,1/2,1/2])) @@ -1926,7 +1937,7 @@ def euler_factor(self, t, p, deg=None, cache_p=False): - [Watkins]_ """ t = QQ(t) - if t in [0, 1]: + if t == 0: raise ValueError('invalid t') if not is_prime(p): raise ValueError('p not prime') @@ -2003,7 +2014,7 @@ def euler_factor(self, t, p, deg=None, cache_p=False): ans = characteristic_polynomial_from_traces(traces, d, p, w, sign, deg=deg) # In the multiplicative case, we sometimes need to add extra factors. - if typ == "mult": + if typ == "mult" and t != 1: if self.degree() % 2 == 0: ans *= tmp if w % 2 == 0 and (t-1).valuation(p) % 2 == 0: From d6cd684ac3e1c06167e9b29f7d7f8da9f64c1ede Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Mon, 1 Jul 2024 16:35:57 +0200 Subject: [PATCH 168/231] use def and not lambda --- .../series_constructor.py | 45 +++++++++---------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/src/sage/modular/modform_hecketriangle/series_constructor.py b/src/sage/modular/modform_hecketriangle/series_constructor.py index 50a1adbc7f0..462cc273459 100644 --- a/src/sage/modular/modform_hecketriangle/series_constructor.py +++ b/src/sage/modular/modform_hecketriangle/series_constructor.py @@ -115,10 +115,9 @@ def __init__(self, group, prec): sage: MFSeriesConstructor(group=infinity) Power series constructor for Hecke modular forms for n=+Infinity with (basic series) precision 10 """ - self._group = group self._prec = prec - self._series_ring = PowerSeriesRing(QQ,'q',default_prec=self._prec) + self._series_ring = PowerSeriesRing(QQ, 'q', default_prec=self._prec) def _repr_(self): r""" @@ -147,7 +146,6 @@ def group(self): sage: MFSeriesConstructor(group=4).group() Hecke triangle group for n = 4 """ - return self._group def hecke_n(self): @@ -160,7 +158,6 @@ def hecke_n(self): sage: MFSeriesConstructor(group=4).hecke_n() 4 """ - return self._group.n() def prec(self): @@ -175,7 +172,6 @@ def prec(self): sage: MFSeriesConstructor(group=5, prec=20).prec() 20 """ - return self._prec @cached_method @@ -193,9 +189,9 @@ def J_inv_ZZ(self): .. TODO:: - The functions that are used in this implementation are - products of hypergeometric series with other, elementary, - functions. Implement them and clean up this representation. + The functions that are used in this implementation are + products of hypergeometric series with other, elementary, + functions. Implement them and clean up this representation. EXAMPLES:: @@ -210,21 +206,24 @@ def J_inv_ZZ(self): sage: MFSeriesConstructor(group=infinity, prec=3).J_inv_ZZ() q^-1 + 3/8 + 69/1024*q + O(q^2) """ - F1 = lambda a, b: self._series_ring( - [ZZ.zero()] - + [rising_factorial(a,k) * rising_factorial(b,k) / (ZZ(k).factorial())**2 - * sum(ZZ.one()/(a+j) + ZZ.one()/(b+j) - ZZ(2)/ZZ(1+j) - for j in range(k)) - for k in range(1, self._prec+1) - ], - ZZ(self._prec+1) - ) - - F = lambda a, b, c: self._series_ring( - [rising_factorial(a,k) * rising_factorial(b,k) / rising_factorial(c,k) / ZZ(k).factorial() - for k in range(self._prec+1)], - ZZ(self._prec+1) - ) + def F1(a, b): + return self._series_ring( + [ZZ.zero()] + + [rising_factorial(a, k) * rising_factorial(b, k) / (ZZ(k).factorial())**2 + * sum(ZZ.one()/(a+j) + ZZ.one()/(b+j) - ZZ(2)/ZZ(1+j) + for j in range(k)) + for k in range(1, self._prec + 1) + ], + ZZ(self._prec + 1) + ) + + def F(a, b, c): + return self._series_ring( + [rising_factorial(a, k) * rising_factorial(b, k) / rising_factorial(c, k) / ZZ(k).factorial() + for k in range(self._prec + 1)], + ZZ(self._prec + 1) + ) + a = self._group.alpha() b = self._group.beta() Phi = F1(a, b) / F(a, b, ZZ.one()) From cc8671ead4ad6ae6ca832e969910079053618b00 Mon Sep 17 00:00:00 2001 From: "Kiran S. Kedlaya" Date: Mon, 1 Jul 2024 08:29:40 -0700 Subject: [PATCH 169/231] Fix whitespace issue --- src/sage/modular/hypergeometric_motive.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/modular/hypergeometric_motive.py b/src/sage/modular/hypergeometric_motive.py index a912befc639..92bfbd448ad 100644 --- a/src/sage/modular/hypergeometric_motive.py +++ b/src/sage/modular/hypergeometric_motive.py @@ -1495,7 +1495,7 @@ def H_value(self, p, f, t, ring=None): Using instead :class:`UniversalCyclotomicfield`, this is much slower than the `p`-adic version :meth:`padic_H_value`. - + Unlike in :meth:`padic_H_value`, tame and wild primes are not supported. EXAMPLES: From 72150bb1717dd16cb7006853a04828401a628069 Mon Sep 17 00:00:00 2001 From: "Kiran S. Kedlaya" Date: Mon, 1 Jul 2024 10:41:59 -0700 Subject: [PATCH 170/231] Add GAP_Enter and GAP_Leave calls to integer coercion --- src/sage/libs/gap/element.pyx | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/src/sage/libs/gap/element.pyx b/src/sage/libs/gap/element.pyx index 0038892d6d4..8bf63697d4d 100644 --- a/src/sage/libs/gap/element.pyx +++ b/src/sage/libs/gap/element.pyx @@ -1518,20 +1518,24 @@ cdef class GapElement_Integer(GapElement): cdef mpz_t output if ring is None: ring = ZZ - if self.is_C_int(): - return ring(GAP_ValueInt(self.value)) - else: - # gap integers are stored as a mp_limb_t - size = GAP_SizeInt(self.value) # count limbs and extract sign - if size > 0: - c_sign = 1 - c_size = size - else: # Must have size < 0, or else self.value == 0 and self.is_C_int() == True - c_sign = -1 - c_size = -size - x = GAP_AddrInt(self.value) # pointer to limbs - mpz_roinit_n(output, x, c_size) - return ring(c_sign*mpz_get_pylong(output)) + try: + GAP_Enter() + if self.is_C_int(): + return ring(GAP_ValueInt(self.value)) + else: + # gap integers are stored as a mp_limb_t + size = GAP_SizeInt(self.value) # count limbs and extract sign + if size > 0: + c_sign = 1 + c_size = size + else: # Must have size < 0, or else self.value == 0 and self.is_C_int() == True + c_sign = -1 + c_size = -size + x = GAP_AddrInt(self.value) # pointer to limbs + mpz_roinit_n(output, x, c_size) + return ring(c_sign*mpz_get_pylong(output)) + finally: + GAP_Leave() _integer_ = sage From 149aeecf48edd6e3038c7fe99dc05e82402cb8db Mon Sep 17 00:00:00 2001 From: Max Date: Tue, 2 Jul 2024 00:04:30 +0200 Subject: [PATCH 171/231] Fix issue #37519 --- src/sage/interfaces/qepcad.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/interfaces/qepcad.py b/src/sage/interfaces/qepcad.py index 1d1c81dac68..f6c90053bdb 100644 --- a/src/sage/interfaces/qepcad.py +++ b/src/sage/interfaces/qepcad.py @@ -839,7 +839,7 @@ def __init__(self, formula, self._cell_cache = {} if verbose: - logfile = sys.stdout + logfile = sys.stdout.buffer varlist = None if vars is not None: From 420692be5cac004f748b97cb92677703ae208ae0 Mon Sep 17 00:00:00 2001 From: Cyril Bouvier Date: Tue, 2 Jul 2024 09:50:26 +0200 Subject: [PATCH 172/231] graphs: use next(vertex_iterator()) to get the first (and only) vertex --- src/sage/graphs/graph.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/graphs/graph.py b/src/sage/graphs/graph.py index 312915cc764..f0e7f19f449 100644 --- a/src/sage/graphs/graph.py +++ b/src/sage/graphs/graph.py @@ -8209,7 +8209,7 @@ def modular_decomposition(self, algorithm=None, style='tuple'): if not self.order(): D = None elif self.order() == 1: - D = create_normal_node(self.vertices(sort=False)[0]) + D = create_normal_node(next(self.vertex_iterator())) else: D = habib_maurer_algorithm(self) From bf638d3e486220781b83630ac13335fd4ed99311 Mon Sep 17 00:00:00 2001 From: Max Date: Tue, 2 Jul 2024 10:01:53 +0200 Subject: [PATCH 173/231] Replacing sys.stdout with sys.stdout.buffer --- src/sage/interfaces/qepcad.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/interfaces/qepcad.py b/src/sage/interfaces/qepcad.py index f6c90053bdb..68d8724e79b 100644 --- a/src/sage/interfaces/qepcad.py +++ b/src/sage/interfaces/qepcad.py @@ -809,7 +809,7 @@ def __init__(self, formula, A logfile can be specified with ``logfile``. If ``verbose=True`` is given, then the logfile is automatically - set to ``sys.stdout``, so all QEPCAD interaction is echoed to + set to ``sys.stdout.buffer``, so all QEPCAD interaction is echoed to the terminal. You can set the amount of memory that QEPCAD allocates with From ad6959c3a17ded435e1f6020aa2cb38237053315 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Labb=C3=A9?= Date: Wed, 3 Jul 2024 14:29:32 +0200 Subject: [PATCH 174/231] more verbose error message --- src/sage/sat/solvers/dimacs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/sat/solvers/dimacs.py b/src/sage/sat/solvers/dimacs.py index aafccfab48b..c2497e0c37b 100644 --- a/src/sage/sat/solvers/dimacs.py +++ b/src/sage/sat/solvers/dimacs.py @@ -520,7 +520,7 @@ def __call__(self, assumptions=None): assert L[-1] == "0", "last digit of solution line must be zero (not {})".format(L[-1]) return (None,) + tuple(int(e) > 0 for e in L[:-1]) else: - raise ValueError("When parsing the output, no line starts with letter v or s") + raise ValueError("When parsing the output(={}), no line starts with letter v or s".format(self._output)) class RSat(DIMACS): """ From 95a1e8579ec07e55dfd290ca168731a9a858a9d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Labb=C3=A9?= Date: Wed, 3 Jul 2024 15:05:20 +0200 Subject: [PATCH 175/231] DIMACS: delete file created during initialization --- src/sage/sat/solvers/dimacs.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/sage/sat/solvers/dimacs.py b/src/sage/sat/solvers/dimacs.py index c2497e0c37b..1288a69456d 100644 --- a/src/sage/sat/solvers/dimacs.py +++ b/src/sage/sat/solvers/dimacs.py @@ -82,8 +82,10 @@ def __init__(self, command=None, filename=None, verbosity=0, **kwds): sage: DIMACS() DIMACS Solver: '' """ + self._headname_file_created_during_init = False if filename is None: filename = tmp_filename() + self._headname_file_created_during_init = True self._headname = filename self._verbosity = verbosity @@ -114,11 +116,31 @@ def __del__(self): sage: from sage.sat.solvers.dimacs import DIMACS sage: d = DIMACS(command="iliketurtles {input}") sage: del d + + We check that files created during initialization are properly + deleted (:issue:`38328`):: + + sage: from sage.sat.solvers.dimacs import DIMACS + sage: d = DIMACS(command="iliketurtles {input}") + sage: filename = d._headname + sage: os.path.exists(filename) + True + sage: del d + sage: os.path.exists(filename) + False + + :: + + sage: fn = tmp_filename() + sage: d = DIMACS(filename=fn) + sage: del d """ if not self._tail.closed: self._tail.close() if os.path.exists(self._tail.name): os.unlink(self._tail.name) + if self._headname_file_created_during_init and os.path.exists(self._headname): + os.unlink(self._headname) def var(self, decision=None): """ From 9bc9a7f9399e3eb1815dd007f5f631b69a9f9958 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Thu, 4 Jul 2024 12:35:05 +0900 Subject: [PATCH 176/231] Removing the automatic size labeler. --- .ci/set_labels_by_changes.sh | 71 -------------------------------- .github/workflows/pr-labeler.yml | 51 ----------------------- 2 files changed, 122 deletions(-) delete mode 100644 .ci/set_labels_by_changes.sh delete mode 100644 .github/workflows/pr-labeler.yml diff --git a/.ci/set_labels_by_changes.sh b/.ci/set_labels_by_changes.sh deleted file mode 100644 index d71444014dc..00000000000 --- a/.ci/set_labels_by_changes.sh +++ /dev/null @@ -1,71 +0,0 @@ -#!/usr/bin/env bash - -# cd to the PR directory -cd $PR_MOUNT_DIR -PR_BASE_SHA=$(git merge-base $BASE_SHA $PR_HEAD_SHA) - -echo "set_labels_by_changes.sh called with environment:" -echo "BASE SHA: $PR_BASE_SHA" -echo "HEAD SHA: $PR_HEAD_SHA" -echo "SMALL THRESHOLD $SMALL_THRESHOLD" -echo "MODERATE THERESHOLD: $MODERATE_THRESHOLD" -echo "LARGE THRESHOLD: $LARGE_THRESHOLD" - -# get all the changes made and changed files -CHANGES=$(git diff --ignore-all-space $PR_BASE_SHA $PR_HEAD_SHA) - -# ignore blank lines -CHANGES=$(echo "$CHANGES" | grep -vE '^[\+\-]\s*$') - -# ignore non necessary lines from git diff -CHANGES=$(echo "$CHANGES" | grep -E '^[+\-]' | grep -vE '^\+\+\+|^\-\-\-') - -# count total no of lines -CHANGES=$(echo "$CHANGES" | wc -l) - -echo "CHANGES MADE: $CHANGES" - -AUTH_HEADER="Authorization: Bearer $GITHUB_TOKEN" - -MINIMAL="v: minimal" -SMALL="v: small" -MODERATE="v: moderate" -LARGE="v: large" - -DELETE_LABELS=("$MINIMAL" "$SMALL" "$MODERATE" "$LARGE") - -if [ "$CHANGES" -gt "$LARGE_THRESHOLD" ]; then - SIZE_LABEL="$LARGE" -elif [ "$CHANGES" -gt "$MODERATE_THRESHOLD" ]; then - SIZE_LABEL="$MODERATE" -elif [ "$CHANGES" -gt "$SMALL_THRESHOLD" ]; then - SIZE_LABEL="$SMALL" -else - SIZE_LABEL="$MINIMAL" -fi - -DELETE_LABELS=("${DELETE_LABELS[@]//${SIZE_LABEL}/}") - -# API for adding labels on the Pull Request -API_URL="https://api.github.com/repos/$REPOSITORY/issues/$PR_NUMBER/labels" - -echo "Adding label: ${SIZE_LABEL[@]}" -for LABEL in "${SIZE_LABEL[@]}"; do - curl -X POST \ - -H "$AUTH_HEADER" \ - -H "Accept: application/vnd.github+json" \ - -H "X-GitHub-Api-Version: 2022-11-28" \ - -d "{\"labels\":[\"$LABEL\"]}" \ - "$API_URL" >/dev/null -done - -echo "Deleting Labels:" - -for DELETE_LABEL in "${DELETE_LABELS[@]}"; do - ENCODED_LABEL=$(echo "$DELETE_LABEL" | sed 's/ /%20/g') - curl -X DELETE \ - -H "Accept: application/vnd.github+json" \ - -H "$AUTH_HEADER" \ - -H "X-GitHub-Api-Version: 2022-11-28" \ - "$API_URL/$ENCODED_LABEL" >/dev/null -done diff --git a/.github/workflows/pr-labeler.yml b/.github/workflows/pr-labeler.yml deleted file mode 100644 index 63f70bb6531..00000000000 --- a/.github/workflows/pr-labeler.yml +++ /dev/null @@ -1,51 +0,0 @@ -# This action automatically labels Pull-Requests -# based on files edited and no of lines changed. -name: Size Labeler / Checker -on: - pull_request_target: - types: - - opened - - reopened - - synchronize - - ready_for_review - - review_requested - - edited -jobs: - label-changes: - if: vars.SMALL_THRESHOLD && vars.MODERATE_THRESHOLD && vars.LARGE_THRESHOLD && github.event.pull_request.draft == false - runs-on: ubuntu-latest - permissions: - pull-requests: write - steps: - # checkout the .ci directory of the develop branch of the main repository sagemath/sage - - name: Checkout the main repo - uses: actions/checkout@v4 - with: - sparse-checkout: | - .ci - # Check out the pull request repository and mount it at path / - - name: Checkout the pull request repo - uses: actions/checkout@v4 - with: - ref: ${{ github.event.pull_request.head.sha }} - fetch-depth: 0 - repository: ${{ github.event.pull_request.head.repo.full_name }} - path: ${{ github.event.pull_request.head.repo.name }} - - - name: Add labels based on size - run: | - git fetch origin $BASE_REF - chmod a+x .ci/set_labels_by_changes.sh - .ci/set_labels_by_changes.sh - env: - BASE_REF: ${{ github.base_ref }} - PR_MOUNT_DIR: ${{ github.event.pull_request.head.repo.name }} - BASE_SHA: ${{ github.event.pull_request.base.sha }} - PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }} - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - REPOSITORY: ${{ github.repository }} - PR_REPO: ${{ github.event.pull_request.head.repo.name }} - PR_NUMBER: ${{ github.event.pull_request.number}} - SMALL_THRESHOLD: ${{ vars.SMALL_THRESHOLD }} - MODERATE_THRESHOLD: ${{ vars.MODERATE_THRESHOLD }} - LARGE_THRESHOLD: ${{ vars.LARGE_THRESHOLD }} From eb236abb5e4936644fff78e93b553479b4a86b98 Mon Sep 17 00:00:00 2001 From: "Kiran S. Kedlaya" Date: Sat, 6 Jul 2024 09:25:21 -0700 Subject: [PATCH 177/231] Incidental docstring formatting fixes (add class links) --- src/sage/modular/hypergeometric_motive.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/modular/hypergeometric_motive.py b/src/sage/modular/hypergeometric_motive.py index 92bfbd448ad..d21d34da445 100644 --- a/src/sage/modular/hypergeometric_motive.py +++ b/src/sage/modular/hypergeometric_motive.py @@ -1500,7 +1500,7 @@ def H_value(self, p, f, t, ring=None): EXAMPLES: - With values in the ``UniversalCyclotomicField`` (slow):: + With values in the :class:`UniversalCyclotomicField` (slow):: sage: from sage.modular.hypergeometric_motive import HypergeometricData as Hyp sage: H = Hyp(alpha_beta=([1/2]*4, [0]*4)) @@ -1515,7 +1515,7 @@ def H_value(self, p, f, t, ring=None): sage: [H.H_value(13,i,-1) for i in range(1,3)] # not tested [-84, -1420] - With values in ``ComplexField``:: + With values in :class:`ComplexField`:: sage: [H.H_value(5,i,-1, ComplexField(60)) for i in range(1,3)] [-4, 276] From 2297236d5d80f9b0434b7841ede34dec33cd65a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Tue, 9 Jul 2024 17:30:07 +0200 Subject: [PATCH 178/231] fix mistake in category of fraction fields --- src/sage/rings/fraction_field.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/sage/rings/fraction_field.py b/src/sage/rings/fraction_field.py index 756cbbc9efc..148aa1f6ee4 100644 --- a/src/sage/rings/fraction_field.py +++ b/src/sage/rings/fraction_field.py @@ -187,14 +187,20 @@ def __init__(self, R, sage: Frac(QQ['x,y']).variable_names() ('x', 'y') sage: category(Frac(QQ['x'])) - Category of quotient fields + Category of infinite quotient fields + + TESTS:: + + sage: F = FractionField(QQ['x']) + sage: F.cardinality() + +Infinity """ self._R = R self._element_class = element_class cat = category - if self in Rings().Infinite(): + if R in Rings().Infinite(): cat = cat.Infinite() - elif self in Rings().Finite(): + elif R in Rings().Finite(): cat = cat.Finite() Parent.__init__(self, base=R, names=R._names, category=cat) From 815026b6fee2b2651606f0c23cdaf3c12483f789 Mon Sep 17 00:00:00 2001 From: Antonio Rojas Date: Wed, 10 Jul 2024 09:08:39 +0200 Subject: [PATCH 179/231] Support ECM 7.0.6 --- src/sage/interfaces/ecm.py | 1 - src/sage/libs/libecm.pyx | 10 ++++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/sage/interfaces/ecm.py b/src/sage/interfaces/ecm.py index 99287dec718..98011970404 100644 --- a/src/sage/interfaces/ecm.py +++ b/src/sage/interfaces/ecm.py @@ -508,7 +508,6 @@ def _find_factor(self, n, factor_digits, B1, **kwds): """ n = self._validate(n) kwds.setdefault('c', 1000000000) - kwds.setdefault('I', 1) if factor_digits is not None: B1 = self.recommended_B1(factor_digits) kwds['one'] = True diff --git a/src/sage/libs/libecm.pyx b/src/sage/libs/libecm.pyx index 886a9b816e4..83fb7adaf8d 100644 --- a/src/sage/libs/libecm.pyx +++ b/src/sage/libs/libecm.pyx @@ -149,11 +149,13 @@ def ecmfactor(number, double B1, verbose=False, sigma=0): Some special cases:: sage: ecmfactor(1, 100) - (True, 1, ...) + Traceback (most recent call last): + ... + ValueError: Input number (1) must be greater than 1 sage: ecmfactor(0, 100) Traceback (most recent call last): ... - ValueError: Input number (0) must be positive + ValueError: Input number (0) must be greater than 1 """ cdef mpz_t n, f cdef int res @@ -164,8 +166,8 @@ def ecmfactor(number, double B1, verbose=False, sigma=0): sage_int_number = Integer(number) sage_int_sigma = Integer(sigma) - if number <= 0: - raise ValueError("Input number (%s) must be positive"%number) + if number <= 1: + raise ValueError("Input number (%s) must be greater than 1"%number) if verbose: print("Performing one curve with B1=%1.0f" % B1) From 4eb1f6b1a17673c844d85a49b491dab895ac4b27 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 10 Jul 2024 16:30:36 +0900 Subject: [PATCH 180/231] build/pkgs/ecm: Update to 7.0.6 --- build/pkgs/ecm/checksums.ini | 6 +++--- build/pkgs/ecm/package-version.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/pkgs/ecm/checksums.ini b/build/pkgs/ecm/checksums.ini index f2221539308..3f78010aaf2 100644 --- a/build/pkgs/ecm/checksums.ini +++ b/build/pkgs/ecm/checksums.ini @@ -1,4 +1,4 @@ tarball=ecm-VERSION.tar.gz -sha1=f35d225d1d44f9b8ad420bf9b50a92582f681337 -sha256=c721dd22e557c4a5dac9ac7e156a400cd2298812dd1f9b56e89966de01471ba8 -upstream_url=https://gitlab.inria.fr/zimmerma/ecm/uploads/89f6f0d65d3e980cef33dc922004e4b2/ecm-VERSION.tar.gz +sha1=257e1c327cd6de1097b7036c7ec358fe3dbfa4ad +sha256=7d20ece61ab6a20ad85f2c18064cabd77dc46a96ff894b5220dbb16e4666e8a5 +upstream_url=https://gitlab.inria.fr/zimmerma/ecm/uploads/ad3e5019fef98819ceae58b78f4cce93/ecm-VERSION.tar.gz diff --git a/build/pkgs/ecm/package-version.txt b/build/pkgs/ecm/package-version.txt index 2be8aeb6b14..024b4b9b53a 100644 --- a/build/pkgs/ecm/package-version.txt +++ b/build/pkgs/ecm/package-version.txt @@ -1 +1 @@ -7.0.5 +7.0.6 From 30bb62362fecb0308a159d5dd4aa8aaf6e4e4870 Mon Sep 17 00:00:00 2001 From: Shriya M <25shriya@gmail.com> Date: Tue, 9 Jul 2024 19:34:36 +0530 Subject: [PATCH 181/231] Updated __repr__() to _repr_() in Ideal.py --- src/sage/rings/ideal.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sage/rings/ideal.py b/src/sage/rings/ideal.py index ccb9128a540..bf1496fb88c 100644 --- a/src/sage/rings/ideal.py +++ b/src/sage/rings/ideal.py @@ -320,7 +320,7 @@ def _repr_short(self): return '\n(\n %s\n)\n' % (',\n\n '.join(L)) return '(%s)' % (', '.join(L)) - def __repr__(self): + def _repr_(self): """ Return a string representation of ``self``. @@ -1270,7 +1270,7 @@ class Ideal_principal(Ideal_generic): #def __init__(self, ring, gen): # Ideal_generic.__init__(self, ring, [gen]) - def __repr__(self): + def _repr_(self): """ Return a string representation of ``self``. @@ -1700,7 +1700,7 @@ class Ideal_fractional(Ideal_generic): See :func:`Ideal()`. """ - def __repr__(self): + def _repr_(self): """ Return a string representation of ``self``. From a57e2259e298a7a25bb9e4f2cabe40f10be8f545 Mon Sep 17 00:00:00 2001 From: Shriya M <25shriya@gmail.com> Date: Tue, 9 Jul 2024 19:35:22 +0530 Subject: [PATCH 182/231] Updated __repr__() to _repr_() in number_field_ideal.py --- src/sage/rings/number_field/number_field_ideal.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sage/rings/number_field/number_field_ideal.py b/src/sage/rings/number_field/number_field_ideal.py index b9d7e0ad781..a0de16c4079 100644 --- a/src/sage/rings/number_field/number_field_ideal.py +++ b/src/sage/rings/number_field/number_field_ideal.py @@ -427,7 +427,7 @@ def __elements_from_hnf(self, hnf): K = self.number_field() return [K(x, check=False) for x in K.pari_zk() * hnf] - def __repr__(self): + def _repr_(self): """ Return the string representation of this number field ideal. @@ -1862,7 +1862,7 @@ def __init__(self, field, gens, coerce=True): else: raise ValueError("gens must have a nonzero element (zero ideal is not a fractional ideal)") - def __repr__(self): + def _repr_(self): """ Return the string representation of this number field fractional ideal. @@ -3396,7 +3396,7 @@ def __call__(self, x): w = v * self.__M_OK_change return self.__Q( list(w) ) - def __repr__(self): + def _repr_(self): r""" Return a string representation of this QuotientMap. @@ -3464,7 +3464,7 @@ def __call__(self, x): z = (w * self.__M_OK_map).list() return self.__OK(sum(z[i] * self.__Kgen ** i for i in range(len(z)))) - def __repr__(self): + def _repr_(self): r""" Return a string representation of this QuotientMap. From e526f04e5cd4e6305a7ee9a6eeaabeec857de695 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 24 Jun 2024 18:08:14 -0700 Subject: [PATCH 183/231] .github/workflows/dist.yml: Build manylinux aarch64 wheels via QEMU --- .github/workflows/dist.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/dist.yml b/.github/workflows/dist.yml index 3d4028dfe78..ef27da4c052 100644 --- a/.github/workflows/dist.yml +++ b/.github/workflows/dist.yml @@ -166,6 +166,8 @@ jobs: arch: x86_64 - os: ubuntu-latest arch: i686 + - os: ubuntu-latest + arch: aarch64 - os: macos-13 arch: x86_64 - os: macos-14 @@ -190,6 +192,12 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Set up QEMU + if: runner.os == 'Linux' && matrix.arch != 'x86_64' && matrix.arch != 'i686' + uses: docker/setup-qemu-action@v3 + with: + platforms: all + - uses: actions/download-artifact@v4 with: name: dist From 3dd5ae9c43951ba8d99b6d733ba8b833177ee01c Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 24 Jun 2024 18:26:56 -0700 Subject: [PATCH 184/231] .github/workflows/dist.yml: Build musllinux wheels --- .github/workflows/dist.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/dist.yml b/.github/workflows/dist.yml index ef27da4c052..beef6b2ea52 100644 --- a/.github/workflows/dist.yml +++ b/.github/workflows/dist.yml @@ -179,8 +179,7 @@ jobs: # Non-Python packages to install as spkgs TARGETS_PRE: gmp mpfr mpc bliss coxeter3 mcqd meataxe sirocco boost_cropped tdlib # Disable building PyPy wheels on all platforms - # Disable musllinux until #33083 provides alpine package information - CIBW_SKIP: "pp* *-musllinux*" + CIBW_SKIP: "pp*" # CIBW_ARCHS: ${{ matrix.arch }} # https://cibuildwheel.readthedocs.io/en/stable/options/#requires-python @@ -233,7 +232,7 @@ jobs: run: | "${{ steps.python.outputs.python-path }}" -m pip install pipx export PATH=build/bin:$PATH - export CIBW_BEFORE_ALL="( $(sage-print-system-package-command debian --yes --no-install-recommends install $(sage-get-system-packages debian $SPKGS)) || $(sage-print-system-package-command fedora --yes --no-install-recommends install $(sage-get-system-packages fedora $SPKGS | sed s/pkg-config/pkgconfig/)) || ( $(sage-print-system-package-command homebrew --yes --no-install-recommends install $(sage-get-system-packages homebrew $SPKGS)) || echo error ignored) ) && if cp /host/sage-\$AUDITWHEEL_PLAT/config.status . 2>/dev/null; then chmod +x config.status; fi && if [ -x ./config.status ]; then ./config.status; else ./configure --enable-build-as-root ${{ startsWith(matrix.os, 'ubuntu') && '--prefix=/host/sage-\$AUDITWHEEL_PLAT' || '' }} && cp config.status prefix/; fi && MAKE=\"make -j6\" make V=0 $TARGETS_PRE && (echo \"sage_conf @ file://\$(pwd)/pkgs/sage-conf\" && echo \"sage_setup @ file://\$(pwd)/pkgs/sage-setup\") > constraints.txt" + export CIBW_BEFORE_ALL="( $(sage-print-system-package-command debian --yes --no-install-recommends install $(sage-get-system-packages debian $SPKGS)) || $(sage-print-system-package-command fedora --yes --no-install-recommends install $(sage-get-system-packages fedora $SPKGS | sed s/pkg-config/pkgconfig/)) || ( $(sage-print-system-package-command homebrew --yes --no-install-recommends install $(sage-get-system-packages homebrew $SPKGS)) || $(sage-print-system-package-command alpine --yes --no-install-recommends install $(sage-get-system-packages alpine $SPKGS)) || echo error ignored) ) && if cp /host/sage-\$AUDITWHEEL_PLAT/config.status . 2>/dev/null; then chmod +x config.status; fi && if [ -x ./config.status ]; then ./config.status; else ./configure --enable-build-as-root ${{ startsWith(matrix.os, 'ubuntu') && '--prefix=/host/sage-\$AUDITWHEEL_PLAT' || '' }} && cp config.status prefix/; fi && MAKE=\"make -j6\" make V=0 $TARGETS_PRE && (echo \"sage_conf @ file://\$(pwd)/pkgs/sage-conf\" && echo \"sage_setup @ file://\$(pwd)/pkgs/sage-setup\") > constraints.txt" mkdir -p unpacked for pkg in sagemath*objects sagemath*categories sagemath*bliss sagemath*coxeter3 sagemath*mcqd sagemath*tdlib; do case "$pkg:${{ matrix.arch }}" in From 995f4f9bb75bedcce4e547110962b622c3340452 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 24 Jun 2024 20:48:09 -0700 Subject: [PATCH 185/231] .github/workflows/dist.yml: Set SAGE_NUM_THREADS --- .github/workflows/dist.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dist.yml b/.github/workflows/dist.yml index beef6b2ea52..2c46aa2a9b8 100644 --- a/.github/workflows/dist.yml +++ b/.github/workflows/dist.yml @@ -185,7 +185,7 @@ jobs: # https://cibuildwheel.readthedocs.io/en/stable/options/#requires-python CIBW_PROJECT_REQUIRES_PYTHON: ">=3.9, <3.13" # Environment during wheel build - CIBW_ENVIRONMENT: "PATH=$(pwd)/prefix/bin:$PATH CPATH=$(pwd)/prefix/include:$CPATH LIBRARY_PATH=$(pwd)/prefix/lib:$LIBRARY_PATH LD_LIBRARY_PATH=$(pwd)/prefix/lib:$LD_LIBRARY_PATH PKG_CONFIG_PATH=$(pwd)/prefix/share/pkgconfig:$PKG_CONFIG_PATH ACLOCAL_PATH=/usr/share/aclocal PIP_CONSTRAINT=$(pwd)/constraints.txt" + CIBW_ENVIRONMENT: "PATH=$(pwd)/prefix/bin:$PATH CPATH=$(pwd)/prefix/include:$CPATH LIBRARY_PATH=$(pwd)/prefix/lib:$LIBRARY_PATH LD_LIBRARY_PATH=$(pwd)/prefix/lib:$LD_LIBRARY_PATH PKG_CONFIG_PATH=$(pwd)/prefix/share/pkgconfig:$PKG_CONFIG_PATH ACLOCAL_PATH=/usr/share/aclocal PIP_CONSTRAINT=$(pwd)/constraints.txt SAGE_NUM_THREADS=6" # Use 'build', not 'pip wheel' CIBW_BUILD_FRONTEND: build steps: From 67d7ce370d42f39afb4b13d5998c1296b78a9a51 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 24 Jun 2024 23:07:36 -0700 Subject: [PATCH 186/231] .github/workflows/dist.yml: Split aarch64 job into manylinux, musllinux --- .github/workflows/dist.yml | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/.github/workflows/dist.yml b/.github/workflows/dist.yml index 2c46aa2a9b8..b45144cd28d 100644 --- a/.github/workflows/dist.yml +++ b/.github/workflows/dist.yml @@ -155,7 +155,7 @@ jobs: if: env.CAN_DEPLOY == 'true' build_wheels: - name: Build wheels on ${{ matrix.os }}, arch ${{ matrix.arch }} + name: Build wheels on ${{ matrix.os }}, arch ${{ matrix.arch }} ${{ matrix.build }} runs-on: ${{ matrix.os }} needs: sdists_for_pypi strategy: @@ -168,6 +168,10 @@ jobs: arch: i686 - os: ubuntu-latest arch: aarch64 + build: manylinux + - os: ubuntu-latest + arch: aarch64 + build: musllinux - os: macos-13 arch: x86_64 - os: macos-14 @@ -178,6 +182,7 @@ jobs: SPKGS: _bootstrap _prereq # Non-Python packages to install as spkgs TARGETS_PRE: gmp mpfr mpc bliss coxeter3 mcqd meataxe sirocco boost_cropped tdlib + CIBW_BUILD: "*${{ matrix.build }}*" # Disable building PyPy wheels on all platforms CIBW_SKIP: "pp*" # @@ -244,7 +249,7 @@ jobs: - uses: actions/upload-artifact@v4 with: - name: ${{ matrix.os }}-${{ matrix.arch }}-wheels + name: ${{ matrix.os }}-${{ matrix.build }}-${{ matrix.arch }}-wheels path: ./wheelhouse/*.whl upload_wheels: @@ -257,7 +262,7 @@ jobs: - uses: actions/download-artifact@v4 with: - pattern: "*-*-wheels" + pattern: "*-*-*-wheels" path: wheelhouse merge-multiple: true From bffc1d3f282fd46cbd22097a453fe2298aae9c53 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 25 Jun 2024 09:44:27 -0700 Subject: [PATCH 187/231] .github/workflows/dist.yml: Use PIP_FIND_LINKS --- .github/workflows/dist.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dist.yml b/.github/workflows/dist.yml index b45144cd28d..a23c709de0c 100644 --- a/.github/workflows/dist.yml +++ b/.github/workflows/dist.yml @@ -190,7 +190,7 @@ jobs: # https://cibuildwheel.readthedocs.io/en/stable/options/#requires-python CIBW_PROJECT_REQUIRES_PYTHON: ">=3.9, <3.13" # Environment during wheel build - CIBW_ENVIRONMENT: "PATH=$(pwd)/prefix/bin:$PATH CPATH=$(pwd)/prefix/include:$CPATH LIBRARY_PATH=$(pwd)/prefix/lib:$LIBRARY_PATH LD_LIBRARY_PATH=$(pwd)/prefix/lib:$LD_LIBRARY_PATH PKG_CONFIG_PATH=$(pwd)/prefix/share/pkgconfig:$PKG_CONFIG_PATH ACLOCAL_PATH=/usr/share/aclocal PIP_CONSTRAINT=$(pwd)/constraints.txt SAGE_NUM_THREADS=6" + CIBW_ENVIRONMENT: "PATH=$(pwd)/prefix/bin:$PATH CPATH=$(pwd)/prefix/include:$CPATH LIBRARY_PATH=$(pwd)/prefix/lib:$LIBRARY_PATH LD_LIBRARY_PATH=$(pwd)/prefix/lib:$LD_LIBRARY_PATH PKG_CONFIG_PATH=$(pwd)/prefix/share/pkgconfig:$PKG_CONFIG_PATH ACLOCAL_PATH=/usr/share/aclocal PIP_CONSTRAINT=$(pwd)/constraints.txt PIP_FIND_LINKS=file://$(pwd)/wheelhouse SAGE_NUM_THREADS=6" # Use 'build', not 'pip wheel' CIBW_BUILD_FRONTEND: build steps: From 74e2966506c2f4ec72fb0cdd8725b4c3b459a2ff Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 25 Jun 2024 09:51:16 -0700 Subject: [PATCH 188/231] .github/workflows/dist.yml: More matrix jobs --- .github/workflows/dist.yml | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/.github/workflows/dist.yml b/.github/workflows/dist.yml index a23c709de0c..cecbb02188e 100644 --- a/.github/workflows/dist.yml +++ b/.github/workflows/dist.yml @@ -161,17 +161,10 @@ jobs: strategy: fail-fast: false matrix: + os: [ubuntu-latest] + arch: [x86_64, i686, aarch64] + build: [manylinux, musllinux] include: - - os: ubuntu-latest - arch: x86_64 - - os: ubuntu-latest - arch: i686 - - os: ubuntu-latest - arch: aarch64 - build: manylinux - - os: ubuntu-latest - arch: aarch64 - build: musllinux - os: macos-13 arch: x86_64 - os: macos-14 From 9f73f5db55f22b54809e53be3132b639875be635 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 25 Jun 2024 11:50:51 -0700 Subject: [PATCH 189/231] .github/workflows/dist.yml: Separate step for each distribution --- .github/workflows/dist.yml | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/.github/workflows/dist.yml b/.github/workflows/dist.yml index cecbb02188e..b5d93ca40c7 100644 --- a/.github/workflows/dist.yml +++ b/.github/workflows/dist.yml @@ -155,7 +155,7 @@ jobs: if: env.CAN_DEPLOY == 'true' build_wheels: - name: Build wheels on ${{ matrix.os }}, arch ${{ matrix.arch }} ${{ matrix.build }} + name: wheels ${{ matrix.arch }} ${{ matrix.build }} on ${{ matrix.os }} runs-on: ${{ matrix.os }} needs: sdists_for_pypi strategy: @@ -214,7 +214,7 @@ jobs: eval $(sage-print-system-package-command auto --sudo --yes --no-install-recommends --spkg install _bootstrap) ./bootstrap - - name: Build platform wheels + - name: Unpack and prepare # We build the wheels from the sdists so that MANIFEST filtering becomes effective. # But we must run cibuildwheel with the unpacked source directory, not a tarball, # so that SAGE_ROOT is copied into the build containers. @@ -228,18 +228,34 @@ jobs: # # omit sagemath-{meataxe,sirocco} for now -- needs sagemath-modules run: | - "${{ steps.python.outputs.python-path }}" -m pip install pipx + "${{ steps.python.outputs.python-path }}" -m pip install cibuildwheel==2.18.0 export PATH=build/bin:$PATH - export CIBW_BEFORE_ALL="( $(sage-print-system-package-command debian --yes --no-install-recommends install $(sage-get-system-packages debian $SPKGS)) || $(sage-print-system-package-command fedora --yes --no-install-recommends install $(sage-get-system-packages fedora $SPKGS | sed s/pkg-config/pkgconfig/)) || ( $(sage-print-system-package-command homebrew --yes --no-install-recommends install $(sage-get-system-packages homebrew $SPKGS)) || $(sage-print-system-package-command alpine --yes --no-install-recommends install $(sage-get-system-packages alpine $SPKGS)) || echo error ignored) ) && if cp /host/sage-\$AUDITWHEEL_PLAT/config.status . 2>/dev/null; then chmod +x config.status; fi && if [ -x ./config.status ]; then ./config.status; else ./configure --enable-build-as-root ${{ startsWith(matrix.os, 'ubuntu') && '--prefix=/host/sage-\$AUDITWHEEL_PLAT' || '' }} && cp config.status prefix/; fi && MAKE=\"make -j6\" make V=0 $TARGETS_PRE && (echo \"sage_conf @ file://\$(pwd)/pkgs/sage-conf\" && echo \"sage_setup @ file://\$(pwd)/pkgs/sage-setup\") > constraints.txt" + echo CIBW_BEFORE_ALL="( $(sage-print-system-package-command debian --yes --no-install-recommends install $(sage-get-system-packages debian $SPKGS)) || $(sage-print-system-package-command fedora --yes --no-install-recommends install $(sage-get-system-packages fedora $SPKGS | sed s/pkg-config/pkgconfig/)) || ( $(sage-print-system-package-command homebrew --yes --no-install-recommends install $(sage-get-system-packages homebrew $SPKGS)) || $(sage-print-system-package-command alpine --yes --no-install-recommends install $(sage-get-system-packages alpine $SPKGS)) || echo error ignored) ) && if cp /host/sage-\$AUDITWHEEL_PLAT/config.status . 2>/dev/null; then chmod +x config.status; fi && if [ -x ./config.status ]; then ./config.status; else ./configure --enable-build-as-root ${{ startsWith(matrix.os, 'ubuntu') && '--prefix=/host/sage-\$AUDITWHEEL_PLAT' || '' }} && cp config.status prefix/; fi && MAKE=\"make -j6\" make V=0 $TARGETS_PRE && (echo \"sage_conf @ file://\$(pwd)/pkgs/sage-conf\" && echo \"sage_setup @ file://\$(pwd)/pkgs/sage-setup\") > constraints.txt" >> "$GITHUB_ENV" mkdir -p unpacked - for pkg in sagemath*objects sagemath*categories sagemath*bliss sagemath*coxeter3 sagemath*mcqd sagemath*tdlib; do - case "$pkg:${{ matrix.arch }}" in - sagemath*tdlib:i686) continue;; # broken - boost-related - esac - (cd unpacked && tar xfz - ) < dist/$pkg*.tar.gz - "${{ steps.python.outputs.python-path }}" -m pipx run cibuildwheel==2.18.0 unpacked/$pkg* + for sdist in dist/$pkg*.tar.gz; do + (cd unpacked && tar xfz - ) < $sdist done + - name: sagemath-objects + run: | + "${{ steps.python.outputs.python-path }}" -m cibuildwheel unpacked/sagemath*objects* + + - name: sagemath-categories + run: | + "${{ steps.python.outputs.python-path }}" -m cibuildwheel unpacked/sagemath*categories* + + - name: sagemath-bliss + run: | + "${{ steps.python.outputs.python-path }}" -m cibuildwheel unpacked/sagemath*bliss* + + - name: sagemath-coxeter3 + run: | + "${{ steps.python.outputs.python-path }}" -m cibuildwheel unpacked/sagemath*coxeter3* + + - name: sagemath-mcqd + run: | + "${{ steps.python.outputs.python-path }}" -m cibuildwheel unpacked/sagemath*mcqd* + - uses: actions/upload-artifact@v4 with: name: ${{ matrix.os }}-${{ matrix.build }}-${{ matrix.arch }}-wheels From 4e538125893af3e587cfd4fa7d2bfba3fd01b0a3 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 25 Jun 2024 15:29:26 -0700 Subject: [PATCH 190/231] .github/workflows/dist.yml: Cosmetic change --- .github/workflows/dist.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/dist.yml b/.github/workflows/dist.yml index b5d93ca40c7..8cc8249e3c6 100644 --- a/.github/workflows/dist.yml +++ b/.github/workflows/dist.yml @@ -155,7 +155,7 @@ jobs: if: env.CAN_DEPLOY == 'true' build_wheels: - name: wheels ${{ matrix.arch }} ${{ matrix.build }} on ${{ matrix.os }} + name: wheels ${{ matrix.build }}*_${{ matrix.arch }} runs-on: ${{ matrix.os }} needs: sdists_for_pypi strategy: @@ -167,8 +167,10 @@ jobs: include: - os: macos-13 arch: x86_64 + build: macosx - os: macos-14 arch: arm64 + build: macosx env: CAN_DEPLOY: ${{ secrets.SAGEMATH_PYPI_API_TOKEN != '' }} # SPKGs to install as system packages From 39654ccddd04a827b05b9784259bb0cffa31a747 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Thu, 11 Jul 2024 20:29:36 +0200 Subject: [PATCH 191/231] little shoeshining for ncsym-dual --- src/sage/combinat/ncsym/dual.py | 73 ++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 34 deletions(-) diff --git a/src/sage/combinat/ncsym/dual.py b/src/sage/combinat/ncsym/dual.py index 38ae7135882..b9a230de61d 100644 --- a/src/sage/combinat/ncsym/dual.py +++ b/src/sage/combinat/ncsym/dual.py @@ -13,22 +13,20 @@ # https://www.gnu.org/licenses/ # **************************************************************************** -from sage.misc.lazy_attribute import lazy_attribute -from sage.misc.misc_c import prod -from sage.structure.parent import Parent -from sage.structure.unique_representation import UniqueRepresentation +from sage.arith.misc import factorial +from sage.categories.fields import Fields from sage.categories.graded_hopf_algebras import GradedHopfAlgebras from sage.categories.rings import Rings -from sage.categories.fields import Fields - -from sage.combinat.ncsym.bases import NCSymDualBases, NCSymBasis_abstract +from sage.combinat.free_module import CombinatorialFreeModule +from sage.combinat.ncsym.bases import NCSymBasis_abstract, NCSymDualBases from sage.combinat.partition import Partition from sage.combinat.set_partition import SetPartitions -from sage.combinat.free_module import CombinatorialFreeModule from sage.combinat.sf.sf import SymmetricFunctions from sage.combinat.subset import Subsets -from sage.arith.misc import factorial -from sage.sets.set import Set +from sage.misc.lazy_attribute import lazy_attribute +from sage.misc.misc_c import prod +from sage.structure.parent import Parent +from sage.structure.unique_representation import UniqueRepresentation class SymmetricFunctionsNonCommutingVariablesDual(UniqueRepresentation, Parent): @@ -86,7 +84,7 @@ def a_realization(self): """ return self.w() - _shorthands = tuple(['w']) + _shorthands = ('w',) def dual(self): r""" @@ -228,24 +226,25 @@ def product_on_basis(self, A, B): sage: w.product_on_basis(A, SetPartition([])) w{{1}, {2, 3}} """ - if len(A) == 0: + if not A: return self.monomial(B) - if len(B) == 0: + if not B: return self.monomial(A) P = SetPartitions() n = A.size() - k = B.size() + m = n + B.size() def unions(s): a = sorted(s) - b = sorted(Set(range(1, n+k+1)).difference(s)) + b = [j for j in range(1, m + 1) if j not in s] # -1 for indexing - ret = [[a[i-1] for i in sorted(part)] for part in A] - ret += [[b[i-1] for i in sorted(part)] for part in B] + ret = [[a[i - 1] for i in sorted(part)] for part in A] + ret.extend([b[i - 1] for i in sorted(part)] for part in B) return P(ret) + return self.sum_of_terms([(unions(s), 1) - for s in Subsets(n+k, n)]) + for s in Subsets(m, n)]) def coproduct_on_basis(self, A): r""" @@ -277,9 +276,9 @@ def coproduct_on_basis(self, A): """ n = A.size() return self.tensor_square().sum_of_terms([ - (( A.restriction(range(1, i+1)).standardization(), - A.restriction(range(i+1, n+1)).standardization() ), 1) - for i in range(n+1)], distinct=True) + ((A.restriction(range(1, i + 1)).standardization(), + A.restriction(range(i + 1, n + 1)).standardization()), 1) + for i in range(n + 1)], distinct=True) def antipode_on_basis(self, A): r""" @@ -307,8 +306,8 @@ def antipode_on_basis(self, A): if A.size() == 1: return -self(A) cpr = self.coproduct_on_basis(A) - return -sum( c*self.monomial(B1)*self.antipode_on_basis(B2) - for ((B1,B2),c) in cpr if B2 != A ) + return -sum(c * self.monomial(B1) * self.antipode_on_basis(B2) + for (B1, B2), c in cpr if B2 != A) def duality_pairing(self, x, y): r""" @@ -351,7 +350,7 @@ def duality_pairing(self, x, y): """ x = self(x) y = self.dual_basis()(y) - return sum(coeff * y[I] for (I, coeff) in x) + return sum(coeff * y[I] for I, coeff in x) def sum_of_partitions(self, la): r""" @@ -422,7 +421,7 @@ def _set_par_to_par(self, A): cur = 1 prev_len = 0 for p in A: - if prev_len > len(p) or list(p) != list(range(cur, cur+len(p))): + if prev_len > len(p) or list(p) != list(range(cur, cur + len(p))): return None prev_len = len(p) cur += len(p) @@ -470,16 +469,21 @@ def expand(self, n, letter='x'): sage: w[[1,3],[2]].expand(3, letter='y') y02*y11*y20 """ - from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing from sage.combinat.permutation import Permutations + from sage.rings.polynomial.polynomial_ring_constructor import ( + PolynomialRing, + ) m = self.parent() - names = ['{}{}{}'.format(letter, i, j) for i in range(n) for j in range(n)] - R = PolynomialRing(m.base_ring(), n*n, names) - x = [[R.gens()[i*n+j] for j in range(n)] for i in range(n)] - I = R.ideal([x[i][j]*x[i][k] for j in range(n) for k in range(n) for i in range(n)]) + names = [f'{letter}{i}{j}' for i in range(n) for j in range(n)] + R = PolynomialRing(m.base_ring(), n * n, names) + x = [[R.gens()[i * n + j] + for j in range(n)] for i in range(n)] + I = R.ideal([x[i][j] * x[i][k] + for j in range(n) for k in range(n) for i in range(n)]) Q = R.quotient(I, names) - x = [[Q.gens()[i*n+j] for j in range(n)] for i in range(n)] + x = [[Q.gens()[i * n + j] + for j in range(n)] for i in range(n)] P = SetPartitions() def on_basis(A): @@ -491,7 +495,8 @@ def on_basis(A): for p in Permutations(k): if P(p.to_cycles()) == A: # -1 for indexing - ret += R.sum(prod(x[I[i]][I[p[i]-1]] for i in range(k)) + ret += R.sum(prod(x[I[i]][I[p[i] - 1]] + for i in range(k)) for I in Subsets(range(n), k)) return ret @@ -592,5 +597,5 @@ def to_symmetric_function(self): raise ValueError("not a symmetric function") h = SymmetricFunctions(self.parent().base_ring()).homogeneous() d = {A.shape(): c for A, c in self} - return h.sum_of_terms([( AA, cc / prod([factorial(i) for i in AA.to_exp()]) ) - for AA, cc in d.items()], distinct=True) + return h.sum_of_terms([(AA, cc / prod(factorial(i) for i in AA.to_exp())) + for AA, cc in d.items()], distinct=True) From d958315879c5fbbcc17f1c6db77973dceefecfb3 Mon Sep 17 00:00:00 2001 From: Frederic Chapoton Date: Sat, 19 Oct 2013 16:58:30 +0000 Subject: [PATCH 192/231] trac #14862 composition input must be nonnegative integers --- src/sage/combinat/composition.py | 34 ++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/src/sage/combinat/composition.py b/src/sage/combinat/composition.py index 9cdb1ebd769..4656aea339f 100644 --- a/src/sage/combinat/composition.py +++ b/src/sage/combinat/composition.py @@ -155,6 +155,20 @@ def __classcall_private__(cls, co=None, descents=None, code=None, from_subset=No [1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0] sage: Composition(code=_) [4, 1, 2, 3, 5] + + TESTS: + + Let us check that :trac:`14862` is solved:: + + sage: C = Compositions() + sage: C([3,-1,1]) + Traceback (most recent call last): + ... + ValueError: elements must be nonnegative integers + sage: C("strawberry") + Traceback (most recent call last): + ... + TypeError: unable to convert x (=s) to an integer """ if descents is not None: if isinstance(descents, tuple): @@ -168,7 +182,22 @@ def __classcall_private__(cls, co=None, descents=None, code=None, from_subset=No elif isinstance(co, Composition): return co else: - return Compositions()(list(co)) + return Compositions()(co) + + def __init__(self, parent, lst): + """ + Initialize ``self``. + + EXAMPLES:: + + sage: C = Composition([3,1,2]) + sage: TestSuite(C).run() + """ + lst = [Integer(u) for u in lst] + if not all(u >= 0 for u in lst): + raise ValueError("elements must be nonnegative integers") + CombinatorialObject.__init__(self, lst) + Element.__init__(self, parent) def _ascii_art_(self): """ @@ -1860,7 +1889,8 @@ def from_subset(self, S, n) -> Composition: return self.element_class(self, [n]) if n <= d[-1]: - raise ValueError("S (=%s) is not a subset of {1, ..., %s}" % (d, n - 1)) + raise ValueError("S (=%s) is not a subset of {1, ..., %s}" + % (d, n-1)) else: d.append(n) From ec76270befc86cfaecce064cad609abded0e9036 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sat, 23 May 2015 11:48:17 +0200 Subject: [PATCH 193/231] trac #14862 new solution --- src/sage/combinat/composition.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/sage/combinat/composition.py b/src/sage/combinat/composition.py index 4656aea339f..5169f6771ef 100644 --- a/src/sage/combinat/composition.py +++ b/src/sage/combinat/composition.py @@ -164,15 +164,16 @@ def __classcall_private__(cls, co=None, descents=None, code=None, from_subset=No sage: C([3,-1,1]) Traceback (most recent call last): ... - ValueError: elements must be nonnegative integers + ValueError: not a composition sage: C("strawberry") Traceback (most recent call last): ... - TypeError: unable to convert x (=s) to an integer + ValueError: not a composition """ if descents is not None: if isinstance(descents, tuple): - return Compositions().from_descents(descents[0], nps=descents[1]) + return Compositions().from_descents(descents[0], + nps=descents[1]) else: return Compositions().from_descents(descents) elif code is not None: @@ -181,8 +182,8 @@ def __classcall_private__(cls, co=None, descents=None, code=None, from_subset=No return Compositions().from_subset(*from_subset) elif isinstance(co, Composition): return co - else: - return Compositions()(co) + + return Compositions()(co) def __init__(self, parent, lst): """ @@ -1784,8 +1785,10 @@ def _element_constructor_(self, lst) -> Composition: sage: P(Partition([5,2,1])) [5, 2, 1] """ - if isinstance(lst, (Composition, Partition)): - lst = list(lst) + # input can be an iterator, and one has to use it twice + lst = list(lst) + if any(not isinstance(x, (int, Integer)) or x < 0 for x in lst): + raise ValueError('not a composition') elt = self.element_class(self, lst) if elt not in self: raise ValueError("%s not in %s" % (elt, self)) From c15aed8ee379db9c098e2e4a32d1c373801009e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Fri, 12 Jul 2024 20:23:10 +0200 Subject: [PATCH 194/231] fix --- src/sage/combinat/composition.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/sage/combinat/composition.py b/src/sage/combinat/composition.py index 5169f6771ef..fd3a7f55b8b 100644 --- a/src/sage/combinat/composition.py +++ b/src/sage/combinat/composition.py @@ -158,7 +158,7 @@ def __classcall_private__(cls, co=None, descents=None, code=None, from_subset=No TESTS: - Let us check that :trac:`14862` is solved:: + Let us check that :issue:`14862` is solved:: sage: C = Compositions() sage: C([3,-1,1]) @@ -197,8 +197,7 @@ def __init__(self, parent, lst): lst = [Integer(u) for u in lst] if not all(u >= 0 for u in lst): raise ValueError("elements must be nonnegative integers") - CombinatorialObject.__init__(self, lst) - Element.__init__(self, parent) + CombinatorialElement.__init__(self, parent, lst) def _ascii_art_(self): """ @@ -1893,7 +1892,7 @@ def from_subset(self, S, n) -> Composition: if n <= d[-1]: raise ValueError("S (=%s) is not a subset of {1, ..., %s}" - % (d, n-1)) + % (d, n - 1)) else: d.append(n) From f62aa6c42fedaa541d7b0080df1e3c3e69ddb6ae Mon Sep 17 00:00:00 2001 From: user202729 <25191436+user202729@users.noreply.github.com> Date: Sat, 13 Jul 2024 11:20:42 +0700 Subject: [PATCH 195/231] Fix a minor typo --- src/sage/schemes/elliptic_curves/period_lattice.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/schemes/elliptic_curves/period_lattice.py b/src/sage/schemes/elliptic_curves/period_lattice.py index aa4662a85ac..ab34e1a4d35 100644 --- a/src/sage/schemes/elliptic_curves/period_lattice.py +++ b/src/sage/schemes/elliptic_curves/period_lattice.py @@ -2041,7 +2041,7 @@ def extended_agm_iteration(a, b, c): OUTPUT: - (3-tuple) `(a_0,b_0,c_0)`, the limit of the iteration `(a,b,c) \mapsto ((a+b)/2,\sqrt{ab},(c+\sqrt(c^2+b^2-a^2))/2)`. + (3-tuple) `(a_0,b_0,c_0)`, the limit of the iteration `(a,b,c) \mapsto ((a+b)/2,\sqrt{ab},(c+\sqrt{c^2+b^2-a^2})/2)`. EXAMPLES:: From 368a642e8d8c369c3bcc179a2d79f24680e398c2 Mon Sep 17 00:00:00 2001 From: dcoudert Date: Sat, 13 Jul 2024 12:41:53 +0200 Subject: [PATCH 196/231] add generator of random proper interval graphs --- src/sage/graphs/generators/random.py | 186 +++++++++++++++++++++++++++ 1 file changed, 186 insertions(+) diff --git a/src/sage/graphs/generators/random.py b/src/sage/graphs/generators/random.py index 767dc2a1496..007647c239f 100644 --- a/src/sage/graphs/generators/random.py +++ b/src/sage/graphs/generators/random.py @@ -870,6 +870,192 @@ def RandomIntervalGraph(n, seed=None): return IntervalGraph(intervals, True) +def RandomProperIntervalGraph(n, seed=None): + r""" + Return a random proper interval graph. + + An interval graph is built from a list `(a_i,b_i)_{1\leq i \leq n}` of + intervals : to each interval of the list is associated one vertex, two + vertices being adjacent if the two corresponding (closed) intervals + intersect. An interval graph is proper if no interval of the list properly + contains another interval. + + Observe that proper interval graphs coincide with unit interval graphs. + See the :wikipedia:`Interval_graph` for more details. + + This method implements the random proper interval graph generator proposed + in [SYKU2010]_ which outputs graphs with uniform probability. The time + complexity of this generator is in `O(n^3)`. + + .. NOTE:: + + The vertices are named 0, 1, 2, and so on. The intervals + used to create the graph are saved with the graph and can + be recovered using ``get_vertex()`` or ``get_vertices()``. + + INPUT: + + - ``n`` -- positive integer; the number of versitces of the graph + + - ``seed`` -- a ``random.Random`` seed or a Python ``int`` for the random + number generator (default: ``None``) + + EXAMPLES:: + + sage: from sage.graphs.generators.random import RandomProperIntervalGraph + sage: G = RandomProperIntervalGraph(10) + sage: G.is_interval() + True + + TESTS:: + + sage: from sage.graphs.generators.random import RandomProperIntervalGraph + sage: RandomProperIntervalGraph(0) + Graph on 0 vertices + sage: RandomProperIntervalGraph(1) + Graph on 1 vertex + sage: RandomProperIntervalGraph(-1) + Traceback (most recent call last): + ... + ValueError: parameter n must be >= 0 + """ + if seed is not None: + set_random_seed(seed) + if n < 0: + raise ValueError('parameter n must be >= 0') + if not n: + return Graph() + + from sage.graphs.generators.intersection import IntervalGraph + + if n == 1: + return IntervalGraph([[0, 1]]) + + from sage.combinat.combinat import catalan_number + from sage.functions.other import binomial + + # let np = n' = n - 1 + np = n - 1 + + # Choose case 1 with probability C(n') / (C(n') + binomial(n', n' // 2)) + cnp = catalan_number(np) + if random() < cnp / (cnp + binomial(np, np // 2)): + # Case 1: Generate a balanced nonnegative string (that can be + # reversible) of length 2n' as follows. We generate the sequence of '[' + # and ']' from left to right. Assume we have already chosen k symbols + # x_1x_2...x_k, with k < 2n'. The next symbol x_{k+1} is '[' with + # probability (h_x(k) + 2) (r - h_x(k) + 1) / (2 (r + 1) (h_x(k) + 1)) + # where r = 2n' - k - 1 and + # h_x(k) = 0 if k == 0, h_x(k - 1) + 1 if x_i == 0 else h_x(k - 1) - 1. + # + # Since the i-th interval starts at the i-th symbol [ and ends at the + # i-th symbol ], we directly build the intervals + intervals = [[0, 2*n] for _ in range(n)] + L = 1 # next starting interval + R = 0 # next ending interval + hx = [0] + r = 2 * np - 1 + for k in range(2 * np): + # Choose symbol x_{k+1} + if random() < ((hx[k] + 2) * (r - hx[k] + 1)) / (2 * (r + 1) * (hx[k] + 1)): + # We have choosen symbol [, so we start an interval + hx.append(hx[k] + 1) + intervals[L][0] = k + 1 + L += 1 + else: + # We have choosen symbol ], so we end an interval + hx.append(hx[k] - 1) + intervals[R][1] = k + 1 + R += 1 + r -= 1 + # Add the last symbol, ], to get a sequence of length 2*n + intervals[R][1] = k + 2 + + # Finally return the interval graph + return IntervalGraph(intervals) + + # Otherwise, generate a balanced nonnegative reversible string of length + # 2n'. This case happens with small probability and is way more complex. + # The string is of the form x_1x_2...x_ny_n..y_2y_1, where y_i is ] if x_i + # is [, and [ otherwise. + + from sage.misc.cachefunc import cached_function + + @cached_function + def compute_C(n, h): + """ + Return C(n, h) as defined below. + + Recall that the Catalan number is C(n) = binomial(2n, n) / (n + 1) + and let C(n, h) = 0 if h > n. The following equations hold for each + integers i and k with 0 <= i <= k. + + 1. C(2k, 2i + 1) = 0, C(2k + 1, 2i) = 0, + 2. C(2k, 0) = C(k), C(k, k) = 1, and + 3. C(k, i) = C(k - 1, i - 1) + C(k - 1, i + 1). + """ + if h > n: + return 0 + if n % 2 != h % 2: + # C(2k, 2i + 1) = 0 and C(2k + 1, 2i) = 0 + # i.e., if n and h have different parity + return 0 + if n == h: + return 1 + if not h and not n % 2: + # C(2k, 0) = C(k) + return catalan_number(n // 2) + # Otherwise, C(k, i) = C(k - 1, i - 1) + C(k - 1, i + 1) + return compute_C(n - 1, h - 1) + compute_C(n - 1, h + 1) + + # We first fill an array hx of length n, backward, and then use it to choose + # the symbols x_1x_2...x_n. Symbols y_n...y_2y_1 are + hx = [0] * n + hx[1] = 1 + # Set hx[np] = h with probability C(np, h) / binomial(np, np // 2) + number = randint(0, binomial(np, np // 2)) + total = 0 + for h in range(np + 1): + total += compute_C(np, h) + if number < total: + break + hx[np] = h + + x = [']'] + y = ['['] + for i in range(np - 1, 0, -1): + # Choose symbol x_i + if random() < (hx[i + 1] + 2) * (i - hx[i + 1] + 1) / (2 * (i + 1) * (hx[i + 1] + 1)): + hx[i] = hx[i + 1] + 1 + x.append(']') + y.append('[') + else: + hx[i] = hx[i + 1] - 1 + x.append('[') + y.append(']') + x.append('[') + x.reverse() + y.append(']') + x.extend(y) + + # We now turn the sequence of symbols to proper intervals. + # The i-th intervals starts from the index of the i-th symbol [ in + # symbols and ends at the position of the i-th symbol ]. + intervals = [[0, 2 * n] for _ in range(n)] + L = 0 # next starting interval + R = 0 # next ending interval + for pos, symbol in enumerate(x): + if symbol == '[': + intervals[L][0] = pos + L += 1 + else: + intervals[R][1] = pos + R += 1 + + # We finally return the resulting interval graph + return IntervalGraph(intervals) + + # Random Chordal Graphs def growing_subtrees(T, k): From 14077204367d95c9a8a5fdc7f0ff5cda6d225a27 Mon Sep 17 00:00:00 2001 From: dcoudert Date: Sat, 13 Jul 2024 12:48:02 +0200 Subject: [PATCH 197/231] add reference and expose in graphs --- src/doc/en/reference/references/index.rst | 5 +++++ src/sage/graphs/graph_generators.py | 1 + 2 files changed, 6 insertions(+) diff --git a/src/doc/en/reference/references/index.rst b/src/doc/en/reference/references/index.rst index b7725c7848b..9758434a84b 100644 --- a/src/doc/en/reference/references/index.rst +++ b/src/doc/en/reference/references/index.rst @@ -6296,6 +6296,11 @@ REFERENCES: Discrete Mathematics, Volume 63, Issues 2-3, 1987, Pages 279-295. +.. [SYKU2010] Toshiki Saitoh, Katsuhisa Yamanaka, Masashi Kiyomi, Ryuhei Uehara: + Random Generation and Enumeration of Proper Interval Graphs. + IEICE Trans. Inf. Syst. 93-D(7): 1816-1823 (2010) + :doi:`10.1587/transinf.E93.D.1816` + .. [SYYTIYTT2002] \T. Shimoyama, H. Yanami, K. Yokoyama, M. Takenaka, K. Itoh, \J. Yajima, N. Torii, and H. Tanaka, *The block cipher SC2000*; in FSE, (2001), pp. 312-327. diff --git a/src/sage/graphs/graph_generators.py b/src/sage/graphs/graph_generators.py index 2d6841eb719..bbe1c2cb632 100644 --- a/src/sage/graphs/graph_generators.py +++ b/src/sage/graphs/graph_generators.py @@ -2768,6 +2768,7 @@ def quadrangulations(self, order, minimum_degree=None, minimum_connectivity=None RandomIntervalGraph = staticmethod(random.RandomIntervalGraph) RandomLobster = staticmethod(random.RandomLobster) RandomNewmanWattsStrogatz = staticmethod(random.RandomNewmanWattsStrogatz) + RandomProperIntervalGraph = staticmethod(random.RandomProperIntervalGraph) RandomRegular = staticmethod(random.RandomRegular) RandomShell = staticmethod(random.RandomShell) RandomKTree = staticmethod(random.RandomKTree) From 731875a61009b59da817e1ca4897929a3c6baed4 Mon Sep 17 00:00:00 2001 From: dcoudert Date: Sat, 13 Jul 2024 12:53:23 +0200 Subject: [PATCH 198/231] add see also blocks --- src/sage/graphs/generators/random.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/sage/graphs/generators/random.py b/src/sage/graphs/generators/random.py index 007647c239f..72a36dad588 100644 --- a/src/sage/graphs/generators/random.py +++ b/src/sage/graphs/generators/random.py @@ -825,7 +825,7 @@ def RandomHolmeKim(n, m, p, seed=None): def RandomIntervalGraph(n, seed=None): r""" - Returns a random interval graph. + Return a random interval graph. An interval graph is built from a list `(a_i,b_i)_{1\leq i \leq n}` of intervals : to each interval of the list is associated one @@ -845,6 +845,11 @@ def RandomIntervalGraph(n, seed=None): used to create the graph are saved with the graph and can be recovered using ``get_vertex()`` or ``get_vertices()``. + .. SEEALSO:: + + - :meth:`sage.graphs.generators.intersection.IntervalGraph` + - :meth:`sage.graphs.generators.random.RandomProperIntervalGraph` + INPUT: - ``n`` -- integer; the number of vertices in the random graph @@ -863,7 +868,6 @@ def RandomIntervalGraph(n, seed=None): """ if seed is not None: set_random_seed(seed) - from sage.misc.prandom import random from sage.graphs.generators.intersection import IntervalGraph intervals = [tuple(sorted((random(), random()))) for i in range(n)] @@ -893,6 +897,11 @@ def RandomProperIntervalGraph(n, seed=None): used to create the graph are saved with the graph and can be recovered using ``get_vertex()`` or ``get_vertices()``. + .. SEEALSO:: + + - :meth:`sage.graphs.generators.intersection.IntervalGraph` + - :meth:`sage.graphs.generators.random.RandomIntervalGraph` + INPUT: - ``n`` -- positive integer; the number of versitces of the graph From d587f1bbb2c93e9fa21766ea0dab820d1a14b8cf Mon Sep 17 00:00:00 2001 From: dcoudert Date: Sat, 13 Jul 2024 12:57:10 +0200 Subject: [PATCH 199/231] append to doc in graph_generators.py --- src/sage/graphs/graph_generators.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sage/graphs/graph_generators.py b/src/sage/graphs/graph_generators.py index bbe1c2cb632..6814194ea37 100644 --- a/src/sage/graphs/graph_generators.py +++ b/src/sage/graphs/graph_generators.py @@ -367,6 +367,7 @@ def wrap_name(x): "RandomPartialKTree", "RandomLobster", "RandomNewmanWattsStrogatz", + "RandomProperIntervalGraph", "RandomRegular", "RandomShell", "RandomToleranceGraph", From 5c797edcb1a0bb20934f74e404b3390fad012fdc Mon Sep 17 00:00:00 2001 From: dcoudert Date: Sat, 13 Jul 2024 13:58:35 +0200 Subject: [PATCH 200/231] fix lint errors --- src/sage/graphs/generators/random.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/graphs/generators/random.py b/src/sage/graphs/generators/random.py index 72a36dad588..df93026f9a3 100644 --- a/src/sage/graphs/generators/random.py +++ b/src/sage/graphs/generators/random.py @@ -1018,7 +1018,7 @@ def compute_C(n, h): return compute_C(n - 1, h - 1) + compute_C(n - 1, h + 1) # We first fill an array hx of length n, backward, and then use it to choose - # the symbols x_1x_2...x_n. Symbols y_n...y_2y_1 are + # the symbols x_1x_2...x_n (and so symbols y_n...y_2y_1). hx = [0] * n hx[1] = 1 # Set hx[np] = h with probability C(np, h) / binomial(np, np // 2) @@ -1060,7 +1060,7 @@ def compute_C(n, h): else: intervals[R][1] = pos R += 1 - + # We finally return the resulting interval graph return IntervalGraph(intervals) From 61bd3a74389016dcc8ed8ecc313da9536a1915b3 Mon Sep 17 00:00:00 2001 From: dcoudert Date: Sat, 13 Jul 2024 15:17:31 +0200 Subject: [PATCH 201/231] fix typo --- src/sage/graphs/generators/random.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/sage/graphs/generators/random.py b/src/sage/graphs/generators/random.py index df93026f9a3..645a89ce8a5 100644 --- a/src/sage/graphs/generators/random.py +++ b/src/sage/graphs/generators/random.py @@ -883,7 +883,6 @@ def RandomProperIntervalGraph(n, seed=None): vertices being adjacent if the two corresponding (closed) intervals intersect. An interval graph is proper if no interval of the list properly contains another interval. - Observe that proper interval graphs coincide with unit interval graphs. See the :wikipedia:`Interval_graph` for more details. @@ -904,7 +903,7 @@ def RandomProperIntervalGraph(n, seed=None): INPUT: - - ``n`` -- positive integer; the number of versitces of the graph + - ``n`` -- positive integer; the number of vertices of the graph - ``seed`` -- a ``random.Random`` seed or a Python ``int`` for the random number generator (default: ``None``) From b10746d9cee019f514cff217481bb0a4400637fb Mon Sep 17 00:00:00 2001 From: AZ-0 <35401882+AZ-0@users.noreply.github.com> Date: Sat, 13 Jul 2024 23:07:00 +0200 Subject: [PATCH 202/231] add optional order= argument to .log() method for NTL finite-field elements Mimick Lorenz Panny's code from sagemath/sage#37329 --- .../rings/finite_rings/element_ntl_gf2e.pyx | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/sage/rings/finite_rings/element_ntl_gf2e.pyx b/src/sage/rings/finite_rings/element_ntl_gf2e.pyx index 32ffd192353..ef177234b18 100644 --- a/src/sage/rings/finite_rings/element_ntl_gf2e.pyx +++ b/src/sage/rings/finite_rings/element_ntl_gf2e.pyx @@ -1234,7 +1234,7 @@ cdef class FiniteField_ntl_gf2eElement(FinitePolyExtElement): """ return unpickleFiniteField_ntl_gf2eElement, (self._parent, str(self)) - def log(self, base): + def log(self, base, order=None, *, check=False): """ Compute an integer `x` such that `b^x = a`, where `a` is ``self`` and `b` is ``base``. @@ -1242,6 +1242,9 @@ cdef class FiniteField_ntl_gf2eElement(FinitePolyExtElement): INPUT: - ``base`` -- finite field element + - ``order`` -- integer (optional), the order of the base + - ``check`` -- boolean (default: ``False``): If set, + test whether the given ``order`` is correct. OUTPUT: @@ -1284,11 +1287,21 @@ cdef class FiniteField_ntl_gf2eElement(FinitePolyExtElement): - David Joyner and William Stein (2005-11) - Lorenz Panny (2021-11): use PARI's :pari:`fflog` instead of :func:`sage.groups.generic.discrete_log` """ + cdef Integer base_order + base = self.parent()(base) # The result is undefined if the input to fflog() is invalid. # Since the unit group is cyclic, it suffices to check orders. - cdef Integer base_order = base.multiplicative_order() + if order is None: + base_order = base.multiplicative_order() + else: + if check: + from sage.groups.generic import has_order + if not has_order(base, order, '*'): + raise ValueError('base does not have the provided order') + base_order = order + cdef Integer self_order = self.multiplicative_order() if not self_order.divides(base_order): raise ValueError(f'no logarithm of {self} exists to base {base}') From 06e5e86c1959fc43905d824edc9ea4f797fa5974 Mon Sep 17 00:00:00 2001 From: AZ-0 <35401882+AZ-0@users.noreply.github.com> Date: Sat, 13 Jul 2024 23:39:19 +0200 Subject: [PATCH 203/231] add optional order= argument to .log() method for Givaro finite-field elements --- .../rings/finite_rings/element_givaro.pyx | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/sage/rings/finite_rings/element_givaro.pyx b/src/sage/rings/finite_rings/element_givaro.pyx index 401f398ddee..c3df38a0fc6 100644 --- a/src/sage/rings/finite_rings/element_givaro.pyx +++ b/src/sage/rings/finite_rings/element_givaro.pyx @@ -1411,11 +1411,18 @@ cdef class FiniteField_givaroElement(FinitePolyExtElement): """ return Integer(self._cache.log_to_int(self.element)) - def log(FiniteField_givaroElement self, base): + def log(FiniteField_givaroElement self, base, order=None, *, check=False): """ Return the log to the base `b` of ``self``, i.e., an integer `n` such that `b^n =` ``self``. + INPUT: + + - ``base`` -- non-zero field element + - ``order`` -- integer (optional), multiple of order of ``base`` + - ``check`` -- boolean (default: ``False``): If set, + test whether the given ``order`` is correct. + .. WARNING:: TODO -- This is currently implemented by solving the discrete @@ -1429,9 +1436,22 @@ cdef class FiniteField_givaroElement(FinitePolyExtElement): sage: a = b^7 sage: a.log(b) 7 + + TESTS: + + An example for ``check=True``:: + + sage: F. = GF(3^5, impl='givaro') + sage: t.log(t, 3^4, check=True) + Traceback (most recent call last): + ... + ValueError: 81 is not a multiple of the order of the base """ b = self.parent()(base) - return sage.groups.generic.discrete_log(self, b) + if (order is not None) and check and not (b**order).is_one(): + raise ValueError(f"{order} is not a multiple of the order of the base") + + return sage.groups.generic.discrete_log(self, b, ord=order) def _int_repr(FiniteField_givaroElement self): r""" From e55bfbc47fa33d4c9776bd188a6cdff6c776b2e8 Mon Sep 17 00:00:00 2001 From: AZ-0 <35401882+AZ-0@users.noreply.github.com> Date: Sat, 13 Jul 2024 23:45:47 +0200 Subject: [PATCH 204/231] add optional order= argument to .log() method for modn finite-field elements The argument is unused. It's only there for coherence with the rest of the implementations. --- src/sage/rings/finite_rings/integer_mod.pyx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/sage/rings/finite_rings/integer_mod.pyx b/src/sage/rings/finite_rings/integer_mod.pyx index b2238689afb..d3cf6ad027b 100644 --- a/src/sage/rings/finite_rings/integer_mod.pyx +++ b/src/sage/rings/finite_rings/integer_mod.pyx @@ -638,7 +638,7 @@ cdef class IntegerMod_abstract(FiniteRingElement): else: return sib(self.parent())(v) - def log(self, b=None): + def log(self, b=None, order=None): r""" Compute the discrete logarithm of this element to base `b`, that is, @@ -653,6 +653,10 @@ cdef class IntegerMod_abstract(FiniteRingElement): - ``b`` -- a unit modulo `n`. If ``b`` is not given, ``R.multiplicative_generator()`` is used, where ``R`` is the parent of ``self``. + + - ``order`` -- integer (unused), the order of ``b``. + This argument is unused, only there for coherence of + api with finite field elements. OUTPUT: From fe1923d3280456cc6df1868f410c63a614b477a5 Mon Sep 17 00:00:00 2001 From: AZ-0 <35401882+AZ-0@users.noreply.github.com> Date: Sun, 14 Jul 2024 00:00:35 +0200 Subject: [PATCH 205/231] add optional check= argument to .log() method for modn finite-field elements --- src/sage/rings/finite_rings/integer_mod.pyx | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/sage/rings/finite_rings/integer_mod.pyx b/src/sage/rings/finite_rings/integer_mod.pyx index d3cf6ad027b..a8253f0edb5 100644 --- a/src/sage/rings/finite_rings/integer_mod.pyx +++ b/src/sage/rings/finite_rings/integer_mod.pyx @@ -638,7 +638,7 @@ cdef class IntegerMod_abstract(FiniteRingElement): else: return sib(self.parent())(v) - def log(self, b=None, order=None): + def log(self, b=None, order=None, check=False): r""" Compute the discrete logarithm of this element to base `b`, that is, @@ -655,8 +655,11 @@ cdef class IntegerMod_abstract(FiniteRingElement): ``R`` is the parent of ``self``. - ``order`` -- integer (unused), the order of ``b``. - This argument is unused, only there for coherence of - api with finite field elements. + This argument is normally unused, only there for + coherence of apis with finite field elements. + + - ``check`` -- boolean (default: ``False``). If set, + test whether the given ``order`` is correct. OUTPUT: @@ -785,6 +788,11 @@ cdef class IntegerMod_abstract(FiniteRingElement): if not b.is_unit(): raise ValueError(f"logarithm with base {b} is not defined since it is not a unit modulo {b.modulus()}") + if check: + from sage.groups.generic import has_order + if not has_order(b, order, '*'): + raise ValueError('b does not have the provided order') + cdef Integer n = Integer() cdef Integer m = one_Z cdef Integer q, na, nb From 14de61ea8f74d7278907d6173ae24db5a80816b8 Mon Sep 17 00:00:00 2001 From: AZ-0 <35401882+AZ-0@users.noreply.github.com> Date: Sun, 14 Jul 2024 00:17:10 +0200 Subject: [PATCH 206/231] add tests for check=True in element_ntl_gf2e.pyx and integer_mod.pyx --- src/sage/rings/finite_rings/element_ntl_gf2e.pyx | 8 ++++++++ src/sage/rings/finite_rings/integer_mod.pyx | 11 ++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/sage/rings/finite_rings/element_ntl_gf2e.pyx b/src/sage/rings/finite_rings/element_ntl_gf2e.pyx index ef177234b18..15306564442 100644 --- a/src/sage/rings/finite_rings/element_ntl_gf2e.pyx +++ b/src/sage/rings/finite_rings/element_ntl_gf2e.pyx @@ -1281,6 +1281,14 @@ cdef class FiniteField_ntl_gf2eElement(FinitePolyExtElement): Traceback (most recent call last): ... ValueError: no logarithm of z50 exists to base z50^49 + z50^46 + z50^45 + z50^44 + z50^41 + z50^34 + z50^33 + z50^32 + z50^27 + z50^25 + z50^24 + z50^21 + z50^18 + z50^17 + z50^16 + z50^15 + z50^12 + z50^11 + z50^10 + z50^8 + z50^7 + z50^3 + z50^2 + + An example for ``check=True``:: + + sage: F. = GF(2^5, impl='ntl') + sage: t.log(t, 3^4, check=True) + Traceback (most recent call last): + ... + ValueError: base does not have the provided order AUTHORS: diff --git a/src/sage/rings/finite_rings/integer_mod.pyx b/src/sage/rings/finite_rings/integer_mod.pyx index a8253f0edb5..ba05076cc47 100644 --- a/src/sage/rings/finite_rings/integer_mod.pyx +++ b/src/sage/rings/finite_rings/integer_mod.pyx @@ -767,6 +767,15 @@ cdef class IntegerMod_abstract(FiniteRingElement): sage: R(1).factor() 1 + An example for ``check=True``:: + + sage: F = GF(127, impl='modn') + sage: t = F.primitive_element() + sage: t.log(t, 57, check=True) + Traceback (most recent call last): + ... + ValueError: base does not have the provided order + AUTHORS: - David Joyner and William Stein (2005-11) @@ -791,7 +800,7 @@ cdef class IntegerMod_abstract(FiniteRingElement): if check: from sage.groups.generic import has_order if not has_order(b, order, '*'): - raise ValueError('b does not have the provided order') + raise ValueError('base does not have the provided order') cdef Integer n = Integer() cdef Integer m = one_Z From 8c52b0ddc72fd5ceb02b7c460683d4bd08714790 Mon Sep 17 00:00:00 2001 From: Matthias Goerner <1239022+unhyperbolic@users.noreply.github.com> Date: Wed, 10 Jul 2024 19:04:53 -0700 Subject: [PATCH 207/231] Implementing tight intervals in ComplexIntervalFieldElement.__invert__ - thus for complex interval division. The implementation is inspired by Rokne-Lancaster 1971. Some history: - The first implementation of returning tight intervals was commit 84ba655 (see ticket #19964). - That implementation had bugs (returning too small intervals) and was reverted to fix ticket #37941. - This change is the second implementation. --- src/sage/rings/complex_interval.pyx | 429 +++++++++++++++++++++++++++- 1 file changed, 415 insertions(+), 14 deletions(-) diff --git a/src/sage/rings/complex_interval.pyx b/src/sage/rings/complex_interval.pyx index 5b3064688b0..575829d256c 100644 --- a/src/sage/rings/complex_interval.pyx +++ b/src/sage/rings/complex_interval.pyx @@ -1166,24 +1166,161 @@ cdef class ComplexIntervalFieldElement(FieldElement): - [RL1971]_ """ - cdef ComplexIntervalFieldElement x + cdef ComplexIntervalFieldElement result x = self._new() - cdef mpfi_t t0, t1 - mpfi_init2(t0, self._prec) - mpfi_init2(t1, self._prec) - - mpfi_sqr(t0, self.__re) - mpfi_sqr(t1, self.__im) - - mpfi_add(t0, t0, t1) # now t0 is the norm - mpfi_div(x.__re, self.__re, t0) # x.__re = self.__re/norm + if mpfi_nan_p(self.__re) or mpfi_nan_p(self.__im): + # Return NaN if any input is NaN + return x - mpfi_neg(t1, self.__im) - mpfi_div(x.__im, t1, t0) # x.__im = -self.__im/norm + if mpfi_has_zero(self.__re) and mpfi_has_zero(self.__im): + # Return NaN when dividing by (a complex interval containing) zero. + return x - mpfi_clear(t0) - mpfi_clear(t1) + # The algorithm roughly follows [RL1971]. + # + # However, we deviate from [RL1971] significantly and the + # documentation here is self-contained and hopefully easier + # to follow than [RL1971]. There is a visualization at: + # https://www.shadertoy.com/view/M3VXWG + # + # Note that [RL1971] has several mistakes. For example, when analyzing + # the second case where y1 < 0 and y2 > 0 (and x1 >= 0 from earlier + # assumptions), they have a subcase "y_1 >= x_1". That inequality can + # never be true given the earlier assumptions and should be + # "-y_1 >= x_1". + + # To maximize symmetry considerations, we actually compute the + # circle inversion (z |-> conjugate(1/z)) and conjugate at the end. + + # Let the input be the complex interval [xmin, xmax] + [ymin, ymax] * I. + # + # We say that the complex interval is in standard form if either: + # (I) It is contained within the first quadrant. Furthermore its + # left bottom corner is on or below the north east diagonal. + # That is 0 <= ymin <= xmin. Or: + # (II) It is contained within the first and fourth quadrant crossing + # the (positive) x-Axis. Furthermore, its midpoint is above the + # x-Axis. + # That is 0 < xmin; ymin < 0 < ymax and |ymin| <= |ymax|. + # + # Since we already guarded against the input containing zero, we always + # can and will bring it into standard form by negating or swapping the + # real and imaginary part. + + cdef mpfr_t xmin, xmax, ymin, ymax + mpfr_init2(xmin, self._prec) + mpfr_init2(xmax, self._prec) + mpfr_init2(ymin, self._prec) + mpfr_init2(ymax, self._prec) + + mpfi_get_left(xmin, self.__re) + mpfi_get_right(xmax, self.__re) + mpfi_get_left(ymin, self.__im) + mpfi_get_right(ymax, self.__im) + + # Record what mirror symmetries we applied to undo them later. + # + # We assume that we flip about the coordinate axes before flipping + # about the north east diagonal. + cdef bint negated_x = False + cdef bint negated_y = False + cdef bint swapped_xy = False + + # Record whether we are in case (II). + cdef bint crosses_x_axis = False + + ######################################################################## + # Now bring the input into standard form. + + if mpfr_sgn(ymax) <= 0: + # Interval below (and possibly touching) x-Axis, flip about it. + _negate_interval(ymin, ymax) + negated_y = True + elif mpfr_sgn(ymin) < 0: + # Interval crosses x-Axis + crosses_x_axis = True + # else: Interval is above x-Axis + + # Negating interval for y and swapping do not commute, so + # order of the above and below if-block is important. + + if mpfr_sgn(xmax) <= 0: + # Interval left of (and possibly touching) y-Axis, flip about it. + _negate_interval(xmin, xmax) + negated_x = True + elif mpfr_sgn(xmin) < 0: + # Interval crosses y-Axis, swap to make it cross x-Axis instead. + mpfr_swap(xmin, ymin) + mpfr_swap(xmax, ymax) + swapped_xy = True + crosses_x_axis = True + # else: Interval is right of y-Axis + + if crosses_x_axis: + # Case (II). Ensure standard condition |ymax| >= |ymin| + if mpfr_cmpabs(ymin, ymax) > 0: + _negate_interval(ymin, ymax) + # Note that we negate after potentially swapping. + # Determine what we should have negated before swapping instead. + if swapped_xy: + # negated_x cannot be True already. + negated_x = True + else: + # negated_y cannot be True already. + negated_y = True + else: + # Case (I). Ensure standard condition |ymin| <= |xmin|. + if mpfr_cmp(xmin, ymin) < 0: + mpfr_swap(xmin, ymin) + mpfr_swap(xmax, ymax) + swapped_xy = True + + ######################################################################## + # Apply circle inversion + + # Result will be [amin, amax] + [bmin, bmax] * I. + cdef mpfr_t amin, amax, bmin, bmax + + mpfr_init2(amin, self._prec) + mpfr_init2(amax, self._prec) + mpfr_init2(bmin, self._prec) + mpfr_init2(bmax, self._prec) + + _circle_invert_standard( + amin, amax, bmin, bmax, + xmin, xmax, ymin, ymax, + crosses_x_axis, self._prec) + + ######################################################################## + # Undo symmetries applied above. + + if swapped_xy: + mpfr_swap(amin, bmin) + mpfr_swap(amax, bmax) + + if negated_x: + _negate_interval(amin, amax) + + # We sneak in the promised conjugation by + # inverting negated_y. + if not negated_y: + _negate_interval(bmin, bmax) + + ######################################################################## + # Write out result and free memory + + mpfi_interv_fr(x.__re, amin, amax) + mpfi_interv_fr(x.__im, bmin, bmax) + + mpfr_clear(xmin) + mpfr_clear(xmax) + mpfr_clear(ymin) + mpfr_clear(ymax) + mpfr_clear(amin) + mpfr_clear(amax) + mpfr_clear(bmin) + mpfr_clear(bmax) return x @@ -1988,6 +2125,270 @@ cdef class ComplexIntervalFieldElement(FieldElement): return ComplexBallField(self.prec())(self).zeta(a).\ _complex_mpfi_(self._parent) +cdef _negate_interval(mpfr_ptr xmin, mpfr_ptr xmax): + """ + Negate interval with endpoints xmin and xmax in place. + """ + mpfr_swap(xmin, xmax) + mpfr_neg(xmin, xmin, MPFR_RNDD) + mpfr_neg(xmax, xmax, MPFR_RNDU) + +cdef _inversion_coordinate( + mpfr_ptr result, mpfr_ptr tmp, + mpfr_srcptr x, mpfr_srcptr y, mpfr_rnd_t rnd_denom, mpfr_rnd_t rnd): + """ + Compute the x-coordinate of the image of the point (x,y) under inversion. + That is compute x / (x^2 + y^2). + + rnd_denom determines how to round when computing the denominator. + rnd determines how to round when doing the division. + + This function expects the callee to allocate and pass an mpfr number tmp + that will be used for intermediate computations. This way, an allocated + mpfr number can be used in multiple calculations. + """ + + mpfr_sqr(tmp, x, rnd_denom) + mpfr_sqr(result, y, rnd_denom) + mpfr_add(tmp, tmp, result, rnd_denom) + mpfr_div(result, x, tmp, rnd) + +cdef _inversion_coordinate_pos_down( + mpfr_ptr result, mpfr_ptr tmp, + mpfr_srcptr x, mpfr_srcptr y): + """ + Computes a lower bound for x / (x^2 + y^2) assuming that x is non-negative. + + Note that the result will not be NaN as long as x or y is positive. + """ + + # Let us check that we do not get NaN. + # We need to check mpfr_div since it could return NaN if we divide by zero + # (it currently returns +/-inf, but the documentation says this might be + # subject to change). + # We round up when computing the denominator and thus should get something + # positive if x or y is positive. Even if, say, x is so small that squaring + # produces something smaller than the smallest positive mpfr floating point + # number, we get something non-zero because we round up. + + _inversion_coordinate( + result, tmp, x, y, + MPFR_RNDU, # denominator rounding + MPFR_RNDD) # division rounding + +cdef _inversion_coordinate_pos_up( + mpfr_ptr result, mpfr_ptr tmp, + mpfr_srcptr x, mpfr_srcptr y): + """ + Computes an upper bound for x / (x^2 + y^2) assuming that x is non-negative. + """ + _inversion_coordinate( + result, tmp, x, y, + MPFR_RNDD, # denominator rounding + MPFR_RNDU) # division rounding + +cdef _inversion_coordinate_neg_down( + mpfr_ptr result, mpfr_ptr tmp, + mpfr_srcptr x, mpfr_srcptr y): + """ + Computes a lower bound for x / (x^2 + y^2) assuming that x is non-positive. + """ + _inversion_coordinate( + result, tmp, x, y, + MPFR_RNDD, # denominator rounding + MPFR_RNDD) # division rounding + +cdef _circle_invert_standard( + mpfr_ptr amin, mpfr_ptr amax, mpfr_ptr bmin, mpfr_ptr bmax, + mpfr_srcptr xmin, mpfr_srcptr xmax, mpfr_srcptr ymin, mpfr_srcptr ymax, + bint crosses_x_axis, mpfr_prec_t prec): + """ + Assumes that the input [xmin, xmax] + [ymin, ymax] * I is in standard form + as described above in ComplexIntervalFieldElement.__invert__ with + crosses_x_axis saying whether case (II) applies. + + Computes a complex interval [amin, amax] + [bmin, bmax] * I containing + the image of the input under circle inversion f(z) = conjugate(1/z). + """ + + # Note that, by the maximum principle, it is sufficient to consider the + # image of the boundary of the input rect which will be formed by four + # arcs or line segments. + + # It is useful to do a case analysis by considering whether the input + # crosses the x-Axis, the north east or south east diagonal, respectively. + # + # Given standard form, the input also has to cross the north east + # diagonal and x-Axis if it corsses the south east diagonal. + # + # Thus, we are left with five cases: + # + # NE diagonal x-Axis SE diagonal. + # 1. + # 2. crosses + # 3. crosses + # 4. crosses crosses + # 5. crosses crosses crosses + + # The reader can go to https://www.shadertoy.com/view/M3VXWG to explore + # the different cases visually. + + # Case 1 is the easiest (and the generic case for small intervals). + # + # Consider the images + # f(xmin + ymin * I), ..., f(xmax + ymax * I) + # of the four corners of the input rect under inversion f. + # Now consider the the axis-parallel rectangle R that these images span. + # In general, the image of the input rect might not be contained in R. + # In case 1, however, (and only in case 1) it is and we furthermore know + # which image is mapped to which edge of R. Thus, we have: + # + # amin = Re(f(xmax + ymax * I)) # Image of right top corner + # amax = Re(f(xmin + ymin * I)) # left bottom corner + # bmin = Im(f(xmax + ymin * I)) # right bottom corner + # = Re(f(ymin + xmax * I)) + # bmax = Im(f(xmin + ymax * I)) # left top corner + # = Re(f(ymax + xmin * I)) + # + # Re(f(...)) can be computed with the correct rounding using one of the + # helper functions such as _inversion_coordinate_pos_down. + + # For the other cases, we might need to consider the images of two corners + # and take the minimum to compute, say amin. + + # Furthermore, we also need to consider the image of t + xmin * I which is + # a circle touching the y-Axis at the origin. Depending on which of the + # diagonals and x-Axis the input rect crosses, we need to expand R to + # include the lowest, highest or rightmost point on this circle for the + # correct result. + # + # For example, we have + # amax = 1 / xmin for case 2 and bmax = 1 / (2 * ymin) for case 3. + # + + cdef bint crosses_NE_diagonal = mpfr_cmp(ymax, xmin) > 0 + cdef bint crosses_both_diagonals = False + # Using that input can only cross south east diagonal if it crosses + # x-Axis and north east diagonal. + if crosses_x_axis and crosses_NE_diagonal: + crosses_both_diagonals = mpfr_cmpabs(ymin, xmin) > 0 + + # Some temporary variables + cdef mpfr_t tmp, min2 + + mpfr_init2(tmp, prec) + if crosses_NE_diagonal: + # Temporary variable needed only in some cases. + mpfr_init2(min2, prec) + + ######################################################################## + # Compute amin + + # Use image of right top corner + _inversion_coordinate_pos_down(amin, tmp, xmax, ymax) + + if crosses_NE_diagonal: + # Also use image of left top corner. + + # This is because in this case, the image of the left top corner + # can be left of the image of the right top corner. + + _inversion_coordinate_pos_down(min2, tmp, xmin, ymax) + + # Note that mpfr_min does not return NaN if one (but not the other) + # input is NaN. This could be a problem. Luckily, + # _inversion_coordinate_pos_down never produces NaN. + mpfr_min(amin, amin, min2, MPFR_RNDD) + + # Note that we do not need to consider the images of the left or right + # bottom corner here. Not even in case 5. + # This is because in standard form, the top edge is further aways from + # the x-Axis than the bottom edge. Thus, the images of the left and + # right corner of the top edge is left of those of the bottom edge, + # respectively. + + # Potential optimization: if bmax >= amax, we only need to use the + # image of the left top corner and skip computing the image of the + # right top corner. + + ######################################################################## + # Compute amax + + if crosses_x_axis: + # Use rightmost point on the circle that is the image of + # image of t + xmin * I + mpfr_ui_div(amax, 1, xmin, MPFR_RNDU) + else: + # Use image of left bottom corner + _inversion_coordinate_pos_up(amax, tmp, xmin, ymin) + + ######################################################################## + # Compute bmax + + # In case 5, bmin can reuse bmax (up to sign), so we compute bmax first. + + if crosses_NE_diagonal: + # Use highest point on the circle that is the image of + # t + xmin * I. That is bmax = 1 / (2 * xmin). + if crosses_x_axis: + # Re-use amax = 1 / xmin. + # We can just copy the mantissa and decrease the exponent by 1. + mpfr_div_2ui(bmax, amax, 1, MPFR_RNDU) + else: + # Compute bmax from scratch. + mpfr_ui_div(bmax, 1, xmin, MPFR_RNDU) + mpfr_div_2ui(bmax, bmax, 1, MPFR_RNDU) + else: + # Use image of of left top corner + _inversion_coordinate_pos_up(bmax, tmp, ymax, xmin) + + ######################################################################## + # Compute bmin + + # bmin is probably the hardest to compute. + + cdef bint right_edge_crosses_NE_diagonal + + if crosses_x_axis: + # ymin and thus bmin will be negative. + if crosses_both_diagonals: + # We are in case 5. + # + # Use lowest point on the circle that is the image of + # t + xmin * I. That is bmin = -1 / (2 * xmin). + # + # We can reuse bmax = 1 / (2 * xmin). + mpfr_neg(bmin, bmax, MPFR_RNDD) + else: + # Use image of left bottom corner. + _inversion_coordinate_neg_down(bmin, tmp, ymin, xmin) + else: + # ymin and thus bmin will be non-negative. + + # Use image of right bottom corner. + _inversion_coordinate_pos_down(bmin, tmp, ymin, xmax) + + if crosses_NE_diagonal: + right_edge_crosses_NE_diagonal = mpfr_cmp(ymax, xmax) > 0 + if right_edge_crosses_NE_diagonal: + # Also use image of right top corner. + # + # This is similar to the computation of amin which also + # considered a second corner when crosses_NE_diagonal. + # + # In particular, the same comment about NaN applies. + # + _inversion_coordinate_pos_down(min2, tmp, ymax, xmax) + + # See comment about NaN above. + mpfr_min(bmin, bmin, min2, MPFR_RNDD) + + ######################################################################## + # Free memory + + mpfr_clear(tmp) + if crosses_NE_diagonal: + mpfr_clear(min2) def make_ComplexIntervalFieldElement0( fld, re, im ): """ From a39dd3ea78f204ce5ee36934a218aa01e7098a63 Mon Sep 17 00:00:00 2001 From: Matthias Goerner <1239022+unhyperbolic@users.noreply.github.com> Date: Sat, 13 Jul 2024 13:38:41 -0700 Subject: [PATCH 208/231] Updating tests in complex_interval.pyx due to reintroducing tight complex interval division. --- src/sage/rings/complex_interval.pyx | 30 ++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/sage/rings/complex_interval.pyx b/src/sage/rings/complex_interval.pyx index 575829d256c..30b27d44cb5 100644 --- a/src/sage/rings/complex_interval.pyx +++ b/src/sage/rings/complex_interval.pyx @@ -799,16 +799,16 @@ cdef class ComplexIntervalFieldElement(FieldElement): sage: b = CIF(-1, (2, 3)) sage: c = a/b sage: c.endpoints() - (0.200000000000000 - 2.00000000000000*I, - 2.30000000000000 - 0.500000000000000*I, - 0.200000000000000 - 0.500000000000000*I, - 2.30000000000000 - 2.00000000000000*I) + (0.500000000000000 - 1.60000000000000*I, + 1.50000000000000 - 0.600000000000000*I, + 0.500000000000000 - 0.600000000000000*I, + 1.50000000000000 - 1.60000000000000*I) sage: c = b/a sage: c.endpoints() - (0.100000000000000 + 0.250000000000000*I, - 1.15000000000000 + 1.00000000000000*I, - 0.100000000000000 + 1.00000000000000*I, - 1.15000000000000 + 0.250000000000000*I) + (0.246153846153846 + 0.317647058823529*I, + 0.841176470588236 + 0.761538461538462*I, + 0.246153846153846 + 0.761538461538462*I, + 0.841176470588236 + 0.317647058823529*I) """ return self * right.__invert__() @@ -1135,10 +1135,10 @@ cdef class ComplexIntervalFieldElement(FieldElement): sage: a = CIF((1, 2), (3, 4)) sage: c = a.__invert__() sage: c.endpoints() - (0.0500000000000000 - 0.400000000000000*I, - 0.200000000000000 - 0.150000000000000*I, - 0.0500000000000000 - 0.150000000000000*I, - 0.200000000000000 - 0.400000000000000*I) + (0.0588235294117647 - 0.300000000000000*I, + 0.153846153846154 - 0.200000000000000*I, + 0.0588235294117647 - 0.200000000000000*I, + 0.153846153846154 - 0.300000000000000*I) TESTS: @@ -1155,7 +1155,7 @@ cdef class ComplexIntervalFieldElement(FieldElement): Test that the bug reported in :issue:`25414` has been fixed:: sage: 1 / CIF(RIF(-1 ,1), 0) - [-infinity .. +infinity] + [0.0000000000000000 .. +infinity]*I + [.. NaN ..] + [.. NaN ..]*I Test that the bug reported in :issue:`37927` is fixed:: @@ -2013,7 +2013,7 @@ cdef class ComplexIntervalFieldElement(FieldElement): sage: CIF(1,1).tan() 0.27175258531952? + 1.08392332733870?*I sage: CIF(2).tan() - -2.18503986326152? + -2.185039863261519? sage: CIF(0,2).tan() 0.964027580075817?*I """ @@ -2102,7 +2102,7 @@ cdef class ComplexIntervalFieldElement(FieldElement): sage: CIF(2).tanh() 0.964027580075817? sage: CIF(0,2).tanh() - -2.18503986326152?*I + -2.185039863261519?*I """ return self.sinh() / self.cosh() From 32568caef0e486eea6e16c50c00263afd0f63265 Mon Sep 17 00:00:00 2001 From: Matthias Goerner <1239022+unhyperbolic@users.noreply.github.com> Date: Sat, 13 Jul 2024 15:11:45 -0700 Subject: [PATCH 209/231] Updating tests due to reintroducing tight complex interval division. This only touches baselines that were touched in commit 8d59b12a063e9 where the first implementation of tight complex interval division was reverted. This change resets most of the baselines to what they were just before that commit 8d59b12a063e9. --- .../arithmetic_dynamics/projective_ds.py | 2 +- src/sage/matrix/matrix0.pyx | 2 +- src/sage/matrix/matrix2.pyx | 46 ++++++++++--------- .../rings/polynomial/binary_form_reduce.py | 4 +- src/sage/rings/qqbar.py | 14 +++--- src/sage/schemes/curves/zariski_vankampen.py | 2 +- .../schemes/projective/projective_morphism.py | 4 +- .../expression_conversion_algebraic.py | 4 +- 8 files changed, 40 insertions(+), 38 deletions(-) diff --git a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py index a04cf57a28d..223e2b9a3e7 100644 --- a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py +++ b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py @@ -6103,7 +6103,7 @@ def reduced_form(self, **kwds): sage: f.reduced_form(prec=30, smallest_coeffs=False) Traceback (most recent call last): ... - ValueError: accuracy of Newton's root not within tolerance(0.00009... > 1e-06), increase precision + ValueError: accuracy of Newton's root not within tolerance(0.00008... > 1e-06), increase precision sage: f.reduced_form(smallest_coeffs=False) ( Dynamical System of Projective Space of dimension 1 over Rational Field diff --git a/src/sage/matrix/matrix0.pyx b/src/sage/matrix/matrix0.pyx index 83edc74c16d..b792627346b 100644 --- a/src/sage/matrix/matrix0.pyx +++ b/src/sage/matrix/matrix0.pyx @@ -1974,7 +1974,7 @@ cdef class Matrix(sage.structure.element.Matrix): sage: K = (A - e).kernel() sage: P = K.basis_matrix() sage: P.str() - '[ 1.000000000000000? + 0.?e-17*I -2.116651487479748? + 0.0255565807096352?*I -0.2585224251020429? + 0.288602340904754?*I -0.4847545623533090? - 1.871890760086142?*I]' + '[ 1.000000000000000? + 0.?e-17*I -2.116651487479748? + 0.0255565807096352?*I -0.2585224251020429? + 0.2886023409047535?*I -0.4847545623533090? - 1.871890760086142?*I]' Use single-row delimiters where appropriate:: diff --git a/src/sage/matrix/matrix2.pyx b/src/sage/matrix/matrix2.pyx index 0b51d5c1df7..37042bafa43 100644 --- a/src/sage/matrix/matrix2.pyx +++ b/src/sage/matrix/matrix2.pyx @@ -10589,23 +10589,24 @@ cdef class Matrix(Matrix1): ....: [-1, 1, -6, -6, 5]]) sage: Q, R = A.QR() sage: Q - [ -0.4588314677411235? -0.1260506983326509? 0.3812120831224489? -0.394573711338418? -0.687440062597?] - [ -0.4588314677411235? 0.4726901187474409? -0.05198346588033394? 0.717294125164660? -0.220962877263?] - [ 0.2294157338705618? 0.6617661662464172? 0.6619227988762521? -0.180872093737548? 0.1964114464561?] - [ 0.6882472016116853? 0.1890760474989764? -0.2044682991293135? 0.096630296654307? -0.662888631790?] + [ -0.4588314677411235? -0.1260506983326509? 0.3812120831224489? -0.394573711338418? -0.6874400625964?] + [ -0.4588314677411235? 0.4726901187474409? -0.05198346588033394? 0.7172941251646595? -0.2209628772631?] + [ 0.2294157338705618? 0.6617661662464172? 0.6619227988762521? -0.1808720937375480? 0.1964114464561?] + [ 0.6882472016116853? 0.1890760474989764? -0.2044682991293135? 0.0966302966543065? -0.6628886317894?] [ -0.2294157338705618? 0.5357154679137663? -0.609939332995919? -0.536422031427112? 0.0245514308070?] sage: R [ 4.358898943540674? -0.4588314677411235? 13.07669683062202? 6.194224814505168? 2.982404540317303?] [ 0 1.670171752907625? 0.5987408170800917? -1.292019657909672? 6.207996892883057?] - [ 0 0 5.444401659866974? 5.468660610611130? -0.682716185228386?] - [ 0 0 0 1.027626039419836? -3.61930014968662?] - [ 0 0 0 0 0.02455143080702?] + [ 0 0 5.444401659866974? 5.468660610611130? -0.6827161852283857?] + [ 0 0 0 1.027626039419836? -3.619300149686620?] + [ 0 0 0 0 0.024551430807012?] + sage: Q.conjugate_transpose()*Q - [1.000000000000000? 0.?e-18 0.?e-17 0.?e-15 0.?e-12] - [ 0.?e-18 1.000000000000000? 0.?e-16 0.?e-15 0.?e-12] - [ 0.?e-17 0.?e-16 1.000000000000000? 0.?e-15 0.?e-12] - [ 0.?e-15 0.?e-15 0.?e-15 1.000000000000000? 0.?e-12] - [ 0.?e-12 0.?e-12 0.?e-12 0.?e-12 1.000000000000?] + [1.000000000000000? 0.?e-18 0.?e-17 0.?e-16 0.?e-13] + [ 0.?e-18 1.000000000000000? 0.?e-17 0.?e-16 0.?e-13] + [ 0.?e-17 0.?e-17 1.000000000000000? 0.?e-16 0.?e-13] + [ 0.?e-16 0.?e-16 0.?e-16 1.000000000000000? 0.?e-13] + [ 0.?e-13 0.?e-13 0.?e-13 0.?e-13 1.0000000000000?] sage: Q * R == A True @@ -10621,24 +10622,25 @@ cdef class Matrix(Matrix1): sage: Q, R = A.QR() sage: Q [ -0.7302967433402215? 0.2070566455055649? + 0.5383472783144687?*I 0.2463049809998642? - 0.0764456358723292?*I 0.2381617683194332? - 0.1036596032779695?*I] - [ 0.0912870929175277? -0.2070566455055649? - 0.3778783780476559?*I 0.3786559533863032? - 0.1952221495524667?*I 0.701244450214469? - 0.364371165098660?*I] - [ 0.6390096504226938? + 0.0912870929175277?*I 0.1708217325420910? + 0.6677576817554466?*I -0.03411475806452072? + 0.04090198741767143?*I 0.3140171085506763? - 0.0825191718705412?*I] + [ 0.0912870929175277? -0.2070566455055649? - 0.3778783780476559?*I 0.3786559533863033? - 0.1952221495524667?*I 0.701244450214469? - 0.3643711650986595?*I] + [ 0.6390096504226938? + 0.0912870929175277?*I 0.1708217325420910? + 0.6677576817554466?*I -0.03411475806452072? + 0.04090198741767143?*I 0.3140171085506764? - 0.0825191718705412?*I] [ 0.1825741858350554? + 0.0912870929175277?*I -0.03623491296347385? + 0.0724698259269477?*I 0.8632284069415110? + 0.06322839976356195?*I -0.4499694867611521? - 0.0116119181208918?*I] sage: R [ 10.95445115010333? 0.?e-18 - 1.917028951268082?*I 5.385938482134133? - 2.190890230020665?*I -0.2738612787525831? - 2.190890230020665?*I] - [ 0 4.829596256417300? + 0.?e-17*I -0.869637911123373? - 5.864879483945125?*I 0.993871898426712? - 0.3054085521207082?*I] + [ 0 4.829596256417300? + 0.?e-18*I -0.869637911123373? - 5.864879483945125?*I 0.993871898426712? - 0.3054085521207082?*I] [ 0 0 12.00160760935814? + 0.?e-16*I -0.2709533402297273? + 0.4420629644486323?*I] [ 0 0 0 1.942963944258992? + 0.?e-16*I] sage: Q.conjugate_transpose()*Q [1.000000000000000? + 0.?e-19*I 0.?e-18 + 0.?e-17*I 0.?e-17 + 0.?e-17*I 0.?e-16 + 0.?e-16*I] [ 0.?e-18 + 0.?e-17*I 1.000000000000000? + 0.?e-17*I 0.?e-17 + 0.?e-17*I 0.?e-16 + 0.?e-16*I] - [ 0.?e-17 + 0.?e-17*I 0.?e-17 + 0.?e-17*I 1.000000000000000? + 0.?e-16*I 0.?e-16 + 0.?e-16*I] - [ 0.?e-16 + 0.?e-16*I 0.?e-16 + 0.?e-16*I 0.?e-16 + 0.?e-16*I 1.000000000000000? + 0.?e-15*I] + [ 0.?e-17 + 0.?e-17*I 0.?e-17 + 0.?e-17*I 1.000000000000000? + 0.?e-17*I 0.?e-16 + 0.?e-16*I] + [ 0.?e-16 + 0.?e-16*I 0.?e-16 + 0.?e-16*I 0.?e-16 + 0.?e-16*I 1.000000000000000? + 0.?e-16*I] + sage: Q*R - A [ 0.?e-17 0.?e-17 + 0.?e-17*I 0.?e-16 + 0.?e-16*I 0.?e-16 + 0.?e-16*I] - [ 0.?e-18 0.?e-17 + 0.?e-17*I 0.?e-16 + 0.?e-16*I 0.?e-15 + 0.?e-15*I] + [ 0.?e-18 0.?e-17 + 0.?e-17*I 0.?e-16 + 0.?e-16*I 0.?e-16 + 0.?e-16*I] [0.?e-17 + 0.?e-18*I 0.?e-17 + 0.?e-17*I 0.?e-16 + 0.?e-16*I 0.?e-16 + 0.?e-16*I] - [0.?e-18 + 0.?e-18*I 0.?e-18 + 0.?e-17*I 0.?e-16 + 0.?e-16*I 0.?e-15 + 0.?e-16*I] + [0.?e-18 + 0.?e-18*I 0.?e-18 + 0.?e-18*I 0.?e-16 + 0.?e-16*I 0.?e-16 + 0.?e-16*I] A rank-deficient rectangular matrix, with both values of the ``full`` keyword. :: @@ -12328,9 +12330,9 @@ cdef class Matrix(Matrix1): sage: # needs sage.combinat sage.libs.pari sage: _, T = A.is_similar(B, transformation=True) sage: T - [ 1.0000000000000? + 0.?e-13*I 0.?e-13 + 0.?e-13*I 0.?e-13 + 0.?e-13*I] - [-0.6666666666667? + 0.?e-13*I 0.16666666666667? + 0.?e-14*I -0.8333333333334? + 0.?e-13*I] - [ 0.6666666666667? + 0.?e-13*I 0.?e-13 + 0.?e-13*I -0.333333333334? + 0.?e-13*I] + [ 1.00000000000000? + 0.?e-14*I 0.?e-14 + 0.?e-14*I 0.?e-14 + 0.?e-14*I] + [-0.66666666666667? + 0.?e-15*I 0.166666666666667? + 0.?e-15*I -0.83333333333334? + 0.?e-14*I] + [ 0.66666666666667? + 0.?e-14*I 0.?e-14 + 0.?e-14*I -0.33333333333333? + 0.?e-14*I] sage: T.change_ring(QQ) [ 1 0 0] [-2/3 1/6 -5/6] diff --git a/src/sage/rings/polynomial/binary_form_reduce.py b/src/sage/rings/polynomial/binary_form_reduce.py index 6afb11155cf..8b6134ec59b 100644 --- a/src/sage/rings/polynomial/binary_form_reduce.py +++ b/src/sage/rings/polynomial/binary_form_reduce.py @@ -79,8 +79,8 @@ def covariant_z0(F, z0_cov=False, prec=53, emb=None, error_limit=0.000001): sage: F = -x^8 + 6*x^7*y - 7*x^6*y^2 - 12*x^5*y^3 + 27*x^4*y^4\ ....: - 4*x^3*y^5 - 19*x^2*y^6 + 10*x*y^7 - 5*y^8 sage: covariant_z0(F, prec=80) - (0.64189877107807122203369 + 1.1852516565091601348355*I, - 3134.5148284344627168275) + (0.64189877107807122203366 + 1.1852516565091601348355*I, + 3134.5148284344627168276) :: diff --git a/src/sage/rings/qqbar.py b/src/sage/rings/qqbar.py index 73e8878150c..0122ab20ab3 100644 --- a/src/sage/rings/qqbar.py +++ b/src/sage/rings/qqbar.py @@ -543,14 +543,14 @@ ....: (83132288614462248899077910195645998*a + 254420831388756945210526696075302411552001)*y^2) sage: lc = lc.change_ring(QQbar) sage: lc.roots(CIF) - [(-1.0005054922387982573627768714?, 2), - (-1.0000000000000000000000000000?, 2), - (-0.9999999996626050731848036720993?, 1), + [(-1.000505492239?, 2), + (-1.000000000000?, 2), + (-0.999999999662605?, 1), (0, 2), - (1.0000000000000000000000000000?, 2), - (1.0005054922387982573627768714?, 2), - (0.999999586737109168744488? + 0.?e-43*I, 1), - (0.999999999662605073184804? + 0.?e-43*I, 1)] + (1.000000000000?, 2), + (1.000505492239?, 2), + (0.999999587? + 0.?e-11*I, 1), + (0.999999999? + 0.?e-11*I, 1)] Check that issue:`37927` is fixed:: diff --git a/src/sage/schemes/curves/zariski_vankampen.py b/src/sage/schemes/curves/zariski_vankampen.py index 7dec97439db..8260b3db92f 100644 --- a/src/sage/schemes/curves/zariski_vankampen.py +++ b/src/sage/schemes/curves/zariski_vankampen.py @@ -608,7 +608,7 @@ def newton(f, x0, i0): sage: n 0.0? sage: n.real().endpoints() - (-0.0460743801652894, 0.0291454081632654) + (-0.0147727272727274, 0.00982142857142862) sage: n.imag().endpoints() (0.000000000000000, -0.000000000000000) """ diff --git a/src/sage/schemes/projective/projective_morphism.py b/src/sage/schemes/projective/projective_morphism.py index 339406cd9d6..2baab7e5cda 100644 --- a/src/sage/schemes/projective/projective_morphism.py +++ b/src/sage/schemes/projective/projective_morphism.py @@ -1764,10 +1764,10 @@ def _number_field_from_algebraics(self): Scheme morphism: From: Projective Space of dimension 1 over Number Field in a with defining polynomial y^4 + 3*y^2 + 1 - with a = 0.?e-151 + 0.618033988749895?*I + with a = 0.?e-113 + 0.618033988749895?*I To: Projective Space of dimension 2 over Number Field in a with defining polynomial y^4 + 3*y^2 + 1 - with a = 0.?e-151 + 0.618033988749895?*I + with a = 0.?e-113 + 0.618033988749895?*I Defn: Defined on coordinates by sending (x : y) to (x^2 + (a^3 + 2*a)*x*y + 3*y^2 : y^2 : (2*a^2 + 3)*x*y) diff --git a/src/sage/symbolic/expression_conversion_algebraic.py b/src/sage/symbolic/expression_conversion_algebraic.py index 11314aaeb70..a8b932c75f2 100644 --- a/src/sage/symbolic/expression_conversion_algebraic.py +++ b/src/sage/symbolic/expression_conversion_algebraic.py @@ -146,9 +146,9 @@ def composition(self, ex, operator): sage: a.composition(complex_root_of(x^5 - 1, 3), complex_root_of) 0.3090169943749474? - 0.9510565162951536?*I sage: a.composition(complex_root_of(x^2 + 1, 0), complex_root_of) - 1.?e-884 - 0.9999999999999999?*I + 1.?e-683 - 0.9999999999999999?*I sage: a.composition(complex_root_of(x^2 + 1, 1), complex_root_of) - 1.?e-884 + 0.9999999999999999?*I + 1.?e-683 + 0.9999999999999999?*I TESTS:: From 26b8ab29649a0e462bfb0dcf87b9abf228da0eb4 Mon Sep 17 00:00:00 2001 From: Justin Carel Date: Sun, 14 Jul 2024 14:09:20 +0200 Subject: [PATCH 210/231] remove whitespaces from blank lines --- src/sage/rings/finite_rings/element_givaro.pyx | 2 +- src/sage/rings/finite_rings/element_ntl_gf2e.pyx | 2 +- src/sage/rings/finite_rings/integer_mod.pyx | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sage/rings/finite_rings/element_givaro.pyx b/src/sage/rings/finite_rings/element_givaro.pyx index c3df38a0fc6..4b229011bbb 100644 --- a/src/sage/rings/finite_rings/element_givaro.pyx +++ b/src/sage/rings/finite_rings/element_givaro.pyx @@ -1436,7 +1436,7 @@ cdef class FiniteField_givaroElement(FinitePolyExtElement): sage: a = b^7 sage: a.log(b) 7 - + TESTS: An example for ``check=True``:: diff --git a/src/sage/rings/finite_rings/element_ntl_gf2e.pyx b/src/sage/rings/finite_rings/element_ntl_gf2e.pyx index 15306564442..e4f7e57fcb9 100644 --- a/src/sage/rings/finite_rings/element_ntl_gf2e.pyx +++ b/src/sage/rings/finite_rings/element_ntl_gf2e.pyx @@ -1281,7 +1281,7 @@ cdef class FiniteField_ntl_gf2eElement(FinitePolyExtElement): Traceback (most recent call last): ... ValueError: no logarithm of z50 exists to base z50^49 + z50^46 + z50^45 + z50^44 + z50^41 + z50^34 + z50^33 + z50^32 + z50^27 + z50^25 + z50^24 + z50^21 + z50^18 + z50^17 + z50^16 + z50^15 + z50^12 + z50^11 + z50^10 + z50^8 + z50^7 + z50^3 + z50^2 - + An example for ``check=True``:: sage: F. = GF(2^5, impl='ntl') diff --git a/src/sage/rings/finite_rings/integer_mod.pyx b/src/sage/rings/finite_rings/integer_mod.pyx index ba05076cc47..abb92d41ff7 100644 --- a/src/sage/rings/finite_rings/integer_mod.pyx +++ b/src/sage/rings/finite_rings/integer_mod.pyx @@ -653,11 +653,11 @@ cdef class IntegerMod_abstract(FiniteRingElement): - ``b`` -- a unit modulo `n`. If ``b`` is not given, ``R.multiplicative_generator()`` is used, where ``R`` is the parent of ``self``. - + - ``order`` -- integer (unused), the order of ``b``. This argument is normally unused, only there for coherence of apis with finite field elements. - + - ``check`` -- boolean (default: ``False``). If set, test whether the given ``order`` is correct. From dc7c2f3d926dab31f08ed87063d1cfcc80b95a79 Mon Sep 17 00:00:00 2001 From: Newtech66 Date: Mon, 15 Jul 2024 15:00:26 +0530 Subject: [PATCH 211/231] Initial commit --- src/sage/groups/perm_gps/permgroup.py | 68 +++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/src/sage/groups/perm_gps/permgroup.py b/src/sage/groups/perm_gps/permgroup.py index 2d265216519..962058f57d1 100644 --- a/src/sage/groups/perm_gps/permgroup.py +++ b/src/sage/groups/perm_gps/permgroup.py @@ -1581,6 +1581,74 @@ def smallest_moved_point(self): p = self._libgap_().SmallestMovedPoint() return self._domain_from_gap[Integer(p)] + @cached_method + def disjoint_direct_product_decomposition(self): + r""" + Returns the finest partition of `self.domain()` such that `self` + is isomorphic to the direct product of the projections of `self` + onto each part of the partition. Each part is a union of orbits + of `self`. + + EXAMPLES:: + sage: H = PermutationGroup([[(1,2,3),(7,9,8),(10,12,11)],[(4,5,6),(7,8,9),(10,11,12)],[(5,6),(8,9),(11,12)],[(7,8,9),(10,11,12)]]) + sage: S = H.disjoint_direct_product_decomposition();S + {{1, 2, 3}, {4, 5, 6, 7, 8, 9, 10, 11, 12}} + sage: A = libgap.Stabilizer(H, list(S[0]), libgap.OnTuples);A + Group([ (7,8,9)(10,11,12), (5,6)(8,9)(11,12), (4,5,6)(7,8,9)(10,11,12) ]) + sage: B = libgap.Stabilizer(H, list(S[1]), libgap.OnTuples);B + Group([ (1,2,3) ]) + sage: T = PermutationGroup(gap_group=libgap.DirectProduct(A,B)) + sage T.is_isomorphic(H) + True + """ + from sage.combinat.set_partition import SetPartition + from sage.sets.disjoint_set import DisjointSet + H = self._libgap_() + if self.is_trivial(): + return SetPartition(DisjointSet(self.domain())) + if libgap.NrMovedPoints(H) == self.degree() and libgap.IsTransitive(H): + return SetPartition([self.domain()]) + O = libgap.Orbits(H) + k = len(O) + OrbitMapping = dict() + for i in range(k): + for x in O[i]: + OrbitMapping[x]=i + C = libgap.StabChain(H,libgap.Concatenation(O)) + X = libgap.StrongGeneratorsStabChain(C) + P = DisjointSet(k) + R = libgap.List([]) + identity = libgap.Identity(H) + for i in range(k-1): + libgap.Append(R,O[i]) + Xp = libgap.List([]) + while True: + try: + if libgap.IsSubset(O[i],C['orbit']): + C = C['stabilizer'] + else: + break + except ValueError: #this should catch a GAPError but I don't know how to make it work + break + for x in X: + xs = libgap.SiftedPermutation(C,x) + if xs != identity: + cj = OrbitMapping[libgap.SmallestMovedPoint(libgap.RestrictedPerm(x,R))] + libgap.Add(Xp,xs) + if libgap.RestrictedPerm(xs,O[i+1]) != identity: + P.union(i+1,cj) + else: + libgap.Add(Xp,x) + X = Xp + final_partition = DisjointSet(self.domain()) + for part in P: + grp = [self._domain_from_gap[Integer(x)] + for i in part + for x in O[i]] + for i in range(1,len(grp)): + final_partition.union(grp[0],grp[i]) + return SetPartition(final_partition) + def representative_action(self, x, y): r""" Return an element of ``self`` that maps `x` to `y` if it exists. From 69064893c437aaf7ee206839115a51caea9f37eb Mon Sep 17 00:00:00 2001 From: Andrew Tonks <48631703+0-andy-0@users.noreply.github.com> Date: Mon, 15 Jul 2024 11:58:11 +0200 Subject: [PATCH 212/231] Update ncsf.py Correction lines 184-189: Psi is not the tensor algebra on the primitives but on the generators of this free Lie algebra. --- src/sage/combinat/ncsf_qsym/ncsf.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/sage/combinat/ncsf_qsym/ncsf.py b/src/sage/combinat/ncsf_qsym/ncsf.py index 65b03741885..731aa742ece 100644 --- a/src/sage/combinat/ncsf_qsym/ncsf.py +++ b/src/sage/combinat/ncsf_qsym/ncsf.py @@ -182,8 +182,11 @@ class NonCommutativeSymmetricFunctions(UniqueRepresentation, Parent): bialgebra structure, which cooperates with the grading to form a connected graded bialgebra. Thus, as any connected graded bialgebra, ``Psi`` is a Hopf algebra. Over ``QQ`` (or any other `\QQ`-algebra), - this Hopf algebra ``Psi`` is isomorphic to the tensor algebra of - its space of primitive elements. + this Hopf algebra ``Psi`` is isomorphic to the universal enveloping + algebra of its space of primitive elements. Here, the primitives + form a countably generated free Lie algebra, so ``Psi`` is isomorphic + to the tensor algebra on a countably infinite dimensional vector + space. The antipode is an anti-algebra morphism; in the ``Psi`` basis, it sends the generators to their opposites and changes their sign if From e15b61bb6a191b48353996e977a37ea8076e8854 Mon Sep 17 00:00:00 2001 From: Newtech66 Date: Mon, 15 Jul 2024 17:41:38 +0530 Subject: [PATCH 213/231] Added citation and minor fixes --- src/doc/en/reference/references/index.rst | 5 +++ src/sage/groups/perm_gps/permgroup.py | 37 +++++++++++++---------- 2 files changed, 26 insertions(+), 16 deletions(-) diff --git a/src/doc/en/reference/references/index.rst b/src/doc/en/reference/references/index.rst index b7725c7848b..93e142baf93 100644 --- a/src/doc/en/reference/references/index.rst +++ b/src/doc/en/reference/references/index.rst @@ -1658,6 +1658,11 @@ REFERENCES: .. [CIA] CIA Factbook 09 https://www.cia.gov/library/publications/the-world-factbook/ +.. [CJ2022] \M. Chang, C. Jefferson, *Disjoint direct product decomposition + of permutation groups*, Journal of Symbolic Computation (2022), + Volume 108, pages 1-16. :doi:`10.1016/j.jsc.2021.04.003`. + Preprint: :arxiv:`2004.11618v3`. + .. [CK1986] \R. Calderbank, W.M. Kantor, *The geometry of two-weight codes*, Bull. London Math. Soc. 18(1986) 97-122. diff --git a/src/sage/groups/perm_gps/permgroup.py b/src/sage/groups/perm_gps/permgroup.py index 962058f57d1..1006bf7643b 100644 --- a/src/sage/groups/perm_gps/permgroup.py +++ b/src/sage/groups/perm_gps/permgroup.py @@ -1584,12 +1584,17 @@ def smallest_moved_point(self): @cached_method def disjoint_direct_product_decomposition(self): r""" - Returns the finest partition of `self.domain()` such that `self` - is isomorphic to the direct product of the projections of `self` + Returns the finest partition of the underlying set such that ``self`` + is isomorphic to the direct product of the projections of ``self`` onto each part of the partition. Each part is a union of orbits - of `self`. + of ``self``. + + The algorithm is from [CJ2022]_, which runs in time polynomial in + `n \cdot |G|`, where `n` is the degree of the group and `|G|` is + the size of a generating set, see Theorem 4.5. EXAMPLES:: + sage: H = PermutationGroup([[(1,2,3),(7,9,8),(10,12,11)],[(4,5,6),(7,8,9),(10,11,12)],[(5,6),(8,9),(11,12)],[(7,8,9),(10,11,12)]]) sage: S = H.disjoint_direct_product_decomposition();S {{1, 2, 3}, {4, 5, 6, 7, 8, 9, 10, 11, 12}} @@ -1598,7 +1603,7 @@ def disjoint_direct_product_decomposition(self): sage: B = libgap.Stabilizer(H, list(S[1]), libgap.OnTuples);B Group([ (1,2,3) ]) sage: T = PermutationGroup(gap_group=libgap.DirectProduct(A,B)) - sage T.is_isomorphic(H) + sage: T.is_isomorphic(H) True """ from sage.combinat.set_partition import SetPartition @@ -1613,40 +1618,40 @@ def disjoint_direct_product_decomposition(self): OrbitMapping = dict() for i in range(k): for x in O[i]: - OrbitMapping[x]=i - C = libgap.StabChain(H,libgap.Concatenation(O)) + OrbitMapping[x] = i + C = libgap.StabChain(H, libgap.Concatenation(O)) X = libgap.StrongGeneratorsStabChain(C) P = DisjointSet(k) R = libgap.List([]) identity = libgap.Identity(H) for i in range(k-1): - libgap.Append(R,O[i]) + libgap.Append(R, O[i]) Xp = libgap.List([]) while True: try: - if libgap.IsSubset(O[i],C['orbit']): + if libgap.IsSubset(O[i], C['orbit']): C = C['stabilizer'] else: break except ValueError: #this should catch a GAPError but I don't know how to make it work break for x in X: - xs = libgap.SiftedPermutation(C,x) + xs = libgap.SiftedPermutation(C, x) if xs != identity: - cj = OrbitMapping[libgap.SmallestMovedPoint(libgap.RestrictedPerm(x,R))] - libgap.Add(Xp,xs) - if libgap.RestrictedPerm(xs,O[i+1]) != identity: - P.union(i+1,cj) + cj = OrbitMapping[libgap.SmallestMovedPoint(libgap.RestrictedPerm(x, R))] + libgap.Add(Xp, xs) + if libgap.RestrictedPerm(xs, O[i+1]) != identity: + P.union(i+1, cj) else: - libgap.Add(Xp,x) + libgap.Add(Xp, x) X = Xp final_partition = DisjointSet(self.domain()) for part in P: grp = [self._domain_from_gap[Integer(x)] for i in part for x in O[i]] - for i in range(1,len(grp)): - final_partition.union(grp[0],grp[i]) + for i in range(1, len(grp)): + final_partition.union(grp[0], grp[i]) return SetPartition(final_partition) def representative_action(self, x, y): From badcf18eb4feb45c7e97dee633cac6559446baba Mon Sep 17 00:00:00 2001 From: Newtech66 Date: Mon, 15 Jul 2024 18:03:26 +0530 Subject: [PATCH 214/231] Add finest partition check to doctest --- src/sage/groups/perm_gps/permgroup.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/sage/groups/perm_gps/permgroup.py b/src/sage/groups/perm_gps/permgroup.py index 1006bf7643b..9356e996cbb 100644 --- a/src/sage/groups/perm_gps/permgroup.py +++ b/src/sage/groups/perm_gps/permgroup.py @@ -1605,6 +1605,10 @@ def disjoint_direct_product_decomposition(self): sage: T = PermutationGroup(gap_group=libgap.DirectProduct(A,B)) sage: T.is_isomorphic(H) True + sage: PermutationGroup(PermutationGroup(gap_group=A).gens(),domain=list(S[1])).disjoint_direct_product_decomposition() + {{4, 5, 6, 7, 8, 9, 10, 11, 12}} + sage: PermutationGroup(PermutationGroup(gap_group=B).gens(),domain=list(S[0])).disjoint_direct_product_decomposition() + {{1, 2, 3}} """ from sage.combinat.set_partition import SetPartition from sage.sets.disjoint_set import DisjointSet From fc78fd0f92e32c1798865a57688ee480b5299383 Mon Sep 17 00:00:00 2001 From: Andrew Tonks <48631703+0-andy-0@users.noreply.github.com> Date: Mon, 15 Jul 2024 14:52:29 +0200 Subject: [PATCH 215/231] Update ncsf.py trailing whitespace removed --- src/sage/combinat/ncsf_qsym/ncsf.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sage/combinat/ncsf_qsym/ncsf.py b/src/sage/combinat/ncsf_qsym/ncsf.py index 731aa742ece..dbab31a0080 100644 --- a/src/sage/combinat/ncsf_qsym/ncsf.py +++ b/src/sage/combinat/ncsf_qsym/ncsf.py @@ -182,10 +182,10 @@ class NonCommutativeSymmetricFunctions(UniqueRepresentation, Parent): bialgebra structure, which cooperates with the grading to form a connected graded bialgebra. Thus, as any connected graded bialgebra, ``Psi`` is a Hopf algebra. Over ``QQ`` (or any other `\QQ`-algebra), - this Hopf algebra ``Psi`` is isomorphic to the universal enveloping - algebra of its space of primitive elements. Here, the primitives - form a countably generated free Lie algebra, so ``Psi`` is isomorphic - to the tensor algebra on a countably infinite dimensional vector + this Hopf algebra ``Psi`` is isomorphic to the universal enveloping + algebra of its space of primitive elements. Here, the primitives + form a countably generated free Lie algebra, so ``Psi`` is isomorphic + to the tensor algebra on a countably infinite dimensional vector space. The antipode is an anti-algebra morphism; in the ``Psi`` basis, it From 6512c4615aedb9d0ecb6652e2e19e89392d043d0 Mon Sep 17 00:00:00 2001 From: Newtech66 Date: Mon, 15 Jul 2024 20:14:58 +0530 Subject: [PATCH 216/231] Add new example to doctest --- src/sage/groups/perm_gps/permgroup.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/sage/groups/perm_gps/permgroup.py b/src/sage/groups/perm_gps/permgroup.py index 9356e996cbb..cd9d08ec5de 100644 --- a/src/sage/groups/perm_gps/permgroup.py +++ b/src/sage/groups/perm_gps/permgroup.py @@ -1590,11 +1590,13 @@ def disjoint_direct_product_decomposition(self): of ``self``. The algorithm is from [CJ2022]_, which runs in time polynomial in - `n \cdot |G|`, where `n` is the degree of the group and `|G|` is + `n \cdot |X|`, where `n` is the degree of the group and `|X|` is the size of a generating set, see Theorem 4.5. EXAMPLES:: + The example from the original paper:: + sage: H = PermutationGroup([[(1,2,3),(7,9,8),(10,12,11)],[(4,5,6),(7,8,9),(10,11,12)],[(5,6),(8,9),(11,12)],[(7,8,9),(10,11,12)]]) sage: S = H.disjoint_direct_product_decomposition();S {{1, 2, 3}, {4, 5, 6, 7, 8, 9, 10, 11, 12}} @@ -1609,6 +1611,14 @@ def disjoint_direct_product_decomposition(self): {{4, 5, 6, 7, 8, 9, 10, 11, 12}} sage: PermutationGroup(PermutationGroup(gap_group=B).gens(),domain=list(S[0])).disjoint_direct_product_decomposition() {{1, 2, 3}} + + Counting the number of connected subgroups:: + + sage: # optional -- internet + sage: seq = [sum(1 for G in SymmetricGroup(n).conjugacy_classes_subgroups() if len(G.disjoint_direct_product_decomposition()) == 1) for n in range(1,8)];seq + [1, 1, 2, 6, 6, 27, 20] + sage: oeis(seq) + 0: A005226: Number of atomic species of degree n; also number of connected permutation groups of degree n. """ from sage.combinat.set_partition import SetPartition from sage.sets.disjoint_set import DisjointSet From 449efdc12e6482c50d76811dcb2ac3a7fff81a6f Mon Sep 17 00:00:00 2001 From: Newtech66 Date: Tue, 16 Jul 2024 14:36:22 +0530 Subject: [PATCH 217/231] Minor improvements --- src/sage/groups/perm_gps/permgroup.py | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/src/sage/groups/perm_gps/permgroup.py b/src/sage/groups/perm_gps/permgroup.py index cd9d08ec5de..7a1c4db04a0 100644 --- a/src/sage/groups/perm_gps/permgroup.py +++ b/src/sage/groups/perm_gps/permgroup.py @@ -1593,16 +1593,16 @@ def disjoint_direct_product_decomposition(self): `n \cdot |X|`, where `n` is the degree of the group and `|X|` is the size of a generating set, see Theorem 4.5. - EXAMPLES:: + EXAMPLES: The example from the original paper:: sage: H = PermutationGroup([[(1,2,3),(7,9,8),(10,12,11)],[(4,5,6),(7,8,9),(10,11,12)],[(5,6),(8,9),(11,12)],[(7,8,9),(10,11,12)]]) - sage: S = H.disjoint_direct_product_decomposition();S + sage: S = H.disjoint_direct_product_decomposition(); S {{1, 2, 3}, {4, 5, 6, 7, 8, 9, 10, 11, 12}} - sage: A = libgap.Stabilizer(H, list(S[0]), libgap.OnTuples);A + sage: A = libgap.Stabilizer(H, list(S[0]), libgap.OnTuples); A Group([ (7,8,9)(10,11,12), (5,6)(8,9)(11,12), (4,5,6)(7,8,9)(10,11,12) ]) - sage: B = libgap.Stabilizer(H, list(S[1]), libgap.OnTuples);B + sage: B = libgap.Stabilizer(H, list(S[1]), libgap.OnTuples); B Group([ (1,2,3) ]) sage: T = PermutationGroup(gap_group=libgap.DirectProduct(A,B)) sage: T.is_isomorphic(H) @@ -1614,10 +1614,9 @@ def disjoint_direct_product_decomposition(self): Counting the number of connected subgroups:: - sage: # optional -- internet sage: seq = [sum(1 for G in SymmetricGroup(n).conjugacy_classes_subgroups() if len(G.disjoint_direct_product_decomposition()) == 1) for n in range(1,8)];seq [1, 1, 2, 6, 6, 27, 20] - sage: oeis(seq) + sage: oeis(seq) # optional -- internet 0: A005226: Number of atomic species of degree n; also number of connected permutation groups of degree n. """ from sage.combinat.set_partition import SetPartition @@ -1659,14 +1658,11 @@ def disjoint_direct_product_decomposition(self): else: libgap.Add(Xp, x) X = Xp - final_partition = DisjointSet(self.domain()) - for part in P: - grp = [self._domain_from_gap[Integer(x)] - for i in part - for x in O[i]] - for i in range(1, len(grp)): - final_partition.union(grp[0], grp[i]) - return SetPartition(final_partition) + return SetPartition([ + [self._domain_from_gap[Integer(x)] + for i in part + for x in O[i]] for part in P] + + [[x] for x in self.fixed_points()]) def representative_action(self, x, y): r""" From 941cb98d50ad05cf5b570ccf679e421be12e30e9 Mon Sep 17 00:00:00 2001 From: Newtech66 Date: Tue, 16 Jul 2024 14:44:30 +0530 Subject: [PATCH 218/231] Minor fix --- src/sage/groups/perm_gps/permgroup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/groups/perm_gps/permgroup.py b/src/sage/groups/perm_gps/permgroup.py index 7a1c4db04a0..87540379001 100644 --- a/src/sage/groups/perm_gps/permgroup.py +++ b/src/sage/groups/perm_gps/permgroup.py @@ -1612,9 +1612,9 @@ def disjoint_direct_product_decomposition(self): sage: PermutationGroup(PermutationGroup(gap_group=B).gens(),domain=list(S[0])).disjoint_direct_product_decomposition() {{1, 2, 3}} - Counting the number of connected subgroups:: + Counting the number of "connected" permutation groups of degree `n`:: - sage: seq = [sum(1 for G in SymmetricGroup(n).conjugacy_classes_subgroups() if len(G.disjoint_direct_product_decomposition()) == 1) for n in range(1,8)];seq + sage: seq = [sum(1 for G in SymmetricGroup(n).conjugacy_classes_subgroups() if len(G.disjoint_direct_product_decomposition()) == 1) for n in range(1,8)]; seq [1, 1, 2, 6, 6, 27, 20] sage: oeis(seq) # optional -- internet 0: A005226: Number of atomic species of degree n; also number of connected permutation groups of degree n. From c64c43a2e266736c8485b42387fc0325c73ef397 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Tue, 16 Jul 2024 16:05:23 +0200 Subject: [PATCH 219/231] moving ideal_monoid to the category of rings --- .../finite_dimensional_algebra.py | 41 +++++++---- src/sage/categories/rings.py | 22 ++++++ .../rings/function_field/order_polymod.py | 6 +- src/sage/rings/ring.pxd | 1 - src/sage/rings/ring.pyx | 68 ------------------- 5 files changed, 56 insertions(+), 82 deletions(-) diff --git a/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra.py b/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra.py index 4779f1ba1dd..3eb076e8e89 100644 --- a/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra.py +++ b/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra.py @@ -450,10 +450,13 @@ def ideal(self, gens=None, given_by_matrix=False, side=None): - ``side`` -- ignored but necessary for coercions + The algebra ``A`` has to be in the category of associative algebras. + EXAMPLES:: + sage: cat = Algebras(GF(3)).FiniteDimensional().WithBasis() sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), - ....: Matrix([[0, 1], [0, 0]])]) + ....: Matrix([[0, 1], [0, 0]])], category=cat) sage: A.ideal(A([1,1])) Ideal (e0 + e1) of Finite-dimensional algebra of degree 2 over Finite Field of size 3 @@ -748,6 +751,8 @@ def quotient_map(self, ideal): """ Return the quotient of ``self`` by ``ideal``. + ``self`` has to be in the category of associative and unital algebras. + INPUT: - ``ideal`` -- a :class:`FiniteDimensionalAlgebraIdeal` @@ -759,8 +764,9 @@ def quotient_map(self, ideal): EXAMPLES:: + sage: cat = Algebras(GF(3)).FiniteDimensional().WithBasis() sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), - ....: Matrix([[0, 1], [0, 0]])]) + ....: Matrix([[0, 1], [0, 0]])], category=cat) sage: q0 = A.quotient_map(A.zero_ideal()); q0 Morphism from Finite-dimensional algebra of degree 2 over Finite Field of size 3 @@ -785,7 +791,8 @@ def quotient_map(self, ideal): v[0,p] = 1 v = self.element_class(self, v) table.append(f.solve_right(v.matrix() * f)) - B = FiniteDimensionalAlgebra(k, table) + cat = self.category() + B = FiniteDimensionalAlgebra(k, table, category=cat) return self.hom(f, codomain=B, check=False) def maximal_ideal(self): @@ -794,8 +801,9 @@ def maximal_ideal(self): .. NOTE:: - ``self`` must be unitary, commutative, associative and local - (have a unique maximal ideal). + ``self`` has to be in the category of unitary, commutative + and associative algebras as in the examples below. It must + moreover be local (have a unique maximal ideal). OUTPUT: @@ -805,15 +813,17 @@ def maximal_ideal(self): EXAMPLES:: + sage: cat = CommutativeAlgebras(GF(3)).FiniteDimensional().WithBasis() sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), - ....: Matrix([[0, 1], [0, 0]])]) + ....: Matrix([[0, 1], [0, 0]])], category=cat) sage: A.maximal_ideal() # needs sage.rings.finite_rings Ideal (0, e1) of Finite-dimensional algebra of degree 2 over Finite Field of size 3 + sage: cat = CommutativeAlgebras(QQ).FiniteDimensional().WithBasis() sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0,0], [0,1,0], [0,0,0]]), ....: Matrix([[0,1,0], [0,0,0], [0,0,0]]), - ....: Matrix([[0,0,0], [0,0,0], [0,0,1]])]) + ....: Matrix([[0,0,0], [0,0,0], [0,0,1]])], category=cat) sage: B.maximal_ideal() # needs sage.libs.pari Traceback (most recent call last): ... @@ -839,7 +849,8 @@ def primary_decomposition(self): .. NOTE:: - ``self`` must be unitary, commutative and associative. + ``self`` has to be in the category of unitary, commutative + and associative algebras as in the examples below. OUTPUT: @@ -848,8 +859,9 @@ def primary_decomposition(self): EXAMPLES:: + sage: cat = CommutativeAlgebras(GF(3)).FiniteDimensional().WithBasis() sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), - ....: Matrix([[0, 1], [0, 0]])]) + ....: Matrix([[0, 1], [0, 0]])], category=cat) sage: A.primary_decomposition() # needs sage.rings.finite_rings [Morphism from Finite-dimensional algebra of degree 2 over Finite Field of size 3 @@ -857,9 +869,10 @@ def primary_decomposition(self): given by matrix [1 0] [0 1]] + sage: cat = CommutativeAlgebras(QQ).FiniteDimensional().WithBasis() sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0,0], [0,1,0], [0,0,0]]), ....: Matrix([[0,1,0], [0,0,0], [0,0,0]]), - ....: Matrix([[0,0,0], [0,0,0], [0,0,1]])]) + ....: Matrix([[0,0,0], [0,0,0], [0,0,1]])], category=cat) sage: B.primary_decomposition() # needs sage.libs.pari [Morphism from Finite-dimensional algebra of degree 3 over Rational Field @@ -914,14 +927,18 @@ def maximal_ideals(self): """ Return a list consisting of all maximal ideals of ``self``. + The algebra ``self`` has to be in the category of associative algebras. + EXAMPLES:: + sage: cat = Algebras(GF(3)).FiniteDimensional().WithBasis() sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), - ....: Matrix([[0, 1], [0, 0]])]) + ....: Matrix([[0, 1], [0, 0]])], category=cat) sage: A.maximal_ideals() # needs sage.rings.finite_rings [Ideal (e1) of Finite-dimensional algebra of degree 2 over Finite Field of size 3] - sage: B = FiniteDimensionalAlgebra(QQ, []) + sage: cat = Algebras(QQ).FiniteDimensional().WithBasis() + sage: B = FiniteDimensionalAlgebra(QQ, [], category=cat) sage: B.maximal_ideals() [] """ diff --git a/src/sage/categories/rings.py b/src/sage/categories/rings.py index b1ffb1db328..4fbdf90e368 100644 --- a/src/sage/categories/rings.py +++ b/src/sage/categories/rings.py @@ -667,6 +667,28 @@ def ideal_monoid(self): sage: MS.ideal_monoid() is MS.ideal_monoid() # needs sage.modules True + + More examples:: + + sage: # needs sage.combinat sage.modules + sage: F. = FreeAlgebra(ZZ, 3) + sage: I = F * [x*y + y*z, x^2 + x*y - y*x - y^2] * F + sage: Q = F.quotient(I) + sage: Q.ideal_monoid() + Monoid of ideals of Quotient of Free Algebra on 3 generators (x, y, z) + over Integer Ring by the ideal (x*y + y*z, x^2 + x*y - y*x - y^2) + sage: F. = FreeAlgebra(ZZ, implementation='letterplace') + sage: I = F * [x*y + y*z, x^2 + x*y - y*x - y^2] * F + sage: Q = F.quo(I) + sage: Q.ideal_monoid() + Monoid of ideals of Quotient of Free Associative Unital Algebra + on 3 generators (x, y, z) over Integer Ring + by the ideal (x*y + y*z, x*x + x*y - y*x - y*y) + + sage: ZZ.ideal_monoid() + Monoid of ideals of Integer Ring + sage: R. = QQ[]; R.ideal_monoid() + Monoid of ideals of Univariate Polynomial Ring in x over Rational Field """ try: from sage.rings.ideal_monoid import IdealMonoid diff --git a/src/sage/rings/function_field/order_polymod.py b/src/sage/rings/function_field/order_polymod.py index ad760aad0b6..099fb4caf82 100644 --- a/src/sage/rings/function_field/order_polymod.py +++ b/src/sage/rings/function_field/order_polymod.py @@ -17,6 +17,7 @@ # **************************************************************************** from sage.arith.functions import lcm +from sage.categories.commutative_algebras import CommutativeAlgebras from sage.misc.cachefunc import cached_method from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing @@ -649,7 +650,10 @@ def decomposition(self, ideal): # matrices_reduced give the multiplication matrices used to form the # algebra O mod pO. matrices_reduced = list(map(lambda M: M.mod(p), matrices)) - A = FiniteDimensionalAlgebra(k, matrices_reduced) + cat = CommutativeAlgebras(k).FiniteDimensional().WithBasis() + A = FiniteDimensionalAlgebra(k, matrices_reduced, + assume_associative=True, + category=cat) # Each prime ideal of the algebra A corresponds to a prime ideal of O, # and since the algebra is an Artinian ring, all of its prime ideals diff --git a/src/sage/rings/ring.pxd b/src/sage/rings/ring.pxd index 726f571161f..1b0c21e1dd3 100644 --- a/src/sage/rings/ring.pxd +++ b/src/sage/rings/ring.pxd @@ -8,7 +8,6 @@ cdef class Ring(ParentWithGens): cdef public object _one_element cdef public object _zero_ideal cdef public object _unit_ideal - cdef public object _ideal_monoid cdef class CommutativeRing(Ring): diff --git a/src/sage/rings/ring.pyx b/src/sage/rings/ring.pyx index d546fca961b..c222149d1c6 100644 --- a/src/sage/rings/ring.pyx +++ b/src/sage/rings/ring.pyx @@ -338,36 +338,6 @@ cdef class Ring(ParentWithGens): # initialisation has finished. return self._category or _Rings - def ideal_monoid(self): - """ - Return the monoid of ideals of this ring. - - EXAMPLES:: - - sage: # needs sage.combinat sage.modules - sage: F. = FreeAlgebra(ZZ, 3) - sage: I = F * [x*y + y*z, x^2 + x*y - y*x - y^2] * F - sage: Q = F.quotient(I) - sage: Q.ideal_monoid() - Monoid of ideals of Quotient of Free Algebra on 3 generators (x, y, z) - over Integer Ring by the ideal (x*y + y*z, x^2 + x*y - y*x - y^2) - sage: F. = FreeAlgebra(ZZ, implementation='letterplace') - sage: I = F * [x*y + y*z, x^2 + x*y - y*x - y^2] * F - sage: Q = F.quo(I) - sage: Q.ideal_monoid() - Monoid of ideals of Quotient of Free Associative Unital Algebra - on 3 generators (x, y, z) over Integer Ring - by the ideal (x*y + y*z, x*x + x*y - y*x - y*y) - - """ - if self._ideal_monoid is not None: - return self._ideal_monoid - else: - from sage.rings.noncommutative_ideals import IdealMonoid_nc - M = IdealMonoid_nc(self) - self._ideal_monoid = M - return M - def ideal(self, *args, **kwds): """ Return the ideal defined by ``x``, i.e., generated by ``x``. @@ -947,25 +917,6 @@ cdef class Ring(ParentWithGens): """ return self(randint(-bound,bound)) - def ideal_monoid(self): - """ - Return the monoid of ideals of this ring. - - EXAMPLES:: - - sage: ZZ.ideal_monoid() - Monoid of ideals of Integer Ring - sage: R.=QQ[]; R.ideal_monoid() - Monoid of ideals of Univariate Polynomial Ring in x over Rational Field - """ - if self._ideal_monoid is not None: - return self._ideal_monoid - else: - from sage.rings.ideal_monoid import IdealMonoid - M = IdealMonoid(self) - self._ideal_monoid = M - return M - @cached_method def epsilon(self): """ @@ -1188,25 +1139,6 @@ cdef class CommutativeRing(Ring): """ raise NotImplementedError - def ideal_monoid(self): - """ - Return the monoid of ideals of this ring. - - EXAMPLES:: - - sage: ZZ.ideal_monoid() - Monoid of ideals of Integer Ring - sage: R.=QQ[]; R.ideal_monoid() - Monoid of ideals of Univariate Polynomial Ring in x over Rational Field - """ - if self._ideal_monoid is not None: - return self._ideal_monoid - else: - from sage.rings.ideal_monoid import IdealMonoid - M = IdealMonoid(self) - self._ideal_monoid = M - return M - def extension(self, poly, name=None, names=None, **kwds): """ Algebraically extends self by taking the quotient ``self[x] / (f(x))``. From 8fc8cdef9e5128e9a3520fa186f0b94d2be9a5df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Tue, 16 Jul 2024 16:47:21 +0200 Subject: [PATCH 220/231] fix doctest --- src/doc/en/thematic_tutorials/coercion_and_categories.rst | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/doc/en/thematic_tutorials/coercion_and_categories.rst b/src/doc/en/thematic_tutorials/coercion_and_categories.rst index 516ac714e13..b55fe562555 100644 --- a/src/doc/en/thematic_tutorials/coercion_and_categories.rst +++ b/src/doc/en/thematic_tutorials/coercion_and_categories.rst @@ -115,7 +115,6 @@ This base class provides a lot more methods than a general parent:: '_coerce_impl', '_default_category', '_gens', - '_ideal_monoid', '_latex_names', '_list', '_one_element', @@ -132,7 +131,6 @@ This base class provides a lot more methods than a general parent:: 'gen', 'gens', 'ideal', - 'ideal_monoid', 'integral_closure', 'is_commutative', 'is_field', From 7489731cd9818a630be338e0ab2a708b6fdf310d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Tue, 16 Jul 2024 17:39:43 +0200 Subject: [PATCH 221/231] remove old note --- src/sage/categories/rings.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/sage/categories/rings.py b/src/sage/categories/rings.py index 4fbdf90e368..47777ce5711 100644 --- a/src/sage/categories/rings.py +++ b/src/sage/categories/rings.py @@ -644,13 +644,6 @@ def ideal_monoid(self): """ The monoid of the ideals of this ring. - .. NOTE:: - - The code is copied from the base class of rings. - This is since there are rings that do not inherit - from that class, such as matrix algebras. See - :issue:`7797`. - EXAMPLES:: sage: # needs sage.modules From ce5552c8f5892b57986135782c79bebbd232fbf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Tue, 16 Jul 2024 17:53:54 +0200 Subject: [PATCH 222/231] fix more doctests --- .../finite_dimensional_algebra_ideal.py | 31 ++++++++++++++----- .../finite_dimensional_algebra_morphism.py | 12 +++++-- 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_ideal.py b/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_ideal.py index 72744da3904..53f2660306d 100644 --- a/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_ideal.py +++ b/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_ideal.py @@ -1,6 +1,8 @@ # sage.doctest: needs sage.rings.finite_rings (because all doctests use GF) """ -Ideals of Finite Algebras +Ideals of Finite Dimensional Algebras + +It is necessary to use algebras in the category of associative algebras. """ # **************************************************************************** @@ -39,8 +41,10 @@ class FiniteDimensionalAlgebraIdeal(Ideal_generic): EXAMPLES:: + sage: cat = CommutativeAlgebras(GF(3)).FiniteDimensional().WithBasis() sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), - ....: Matrix([[0, 1], [0, 0]])]) + ....: Matrix([[0, 1], [0, 0]])], + ....: category=cat) sage: A.ideal(A([0,1])) Ideal (e1) of Finite-dimensional algebra of degree 2 over Finite Field of size 3 """ @@ -48,8 +52,10 @@ def __init__(self, A, gens=None, given_by_matrix=False): """ EXAMPLES:: + sage: cat = CommutativeAlgebras(GF(3)).FiniteDimensional().WithBasis() sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), - ....: Matrix([[0, 1], [0, 0]])]) + ....: Matrix([[0, 1], [0, 0]])], + ....: category=cat) sage: I = A.ideal(A([0,1])) sage: TestSuite(I).run(skip="_test_category") # Currently ideals are not using the category framework """ @@ -78,8 +84,10 @@ def _richcmp_(self, other, op): TESTS:: + sage: cat = CommutativeAlgebras(GF(3)).FiniteDimensional().WithBasis() sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), - ....: Matrix([[0, 1], [0, 0]])]) + ....: Matrix([[0, 1], [0, 0]])], + ....: category=cat) sage: I = A.ideal(A([1,1])) sage: J = A.ideal(A([0,1])) sage: I == J @@ -90,7 +98,8 @@ def _richcmp_(self, other, op): True sage: A2 = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), - ....: Matrix([[0, 1], [0, 0]])]) + ....: Matrix([[0, 1], [0, 0]])], + ....: category=cat) sage: A is A2 True sage: A == A2 @@ -134,8 +143,10 @@ def __contains__(self, elt): """ EXAMPLES:: + sage: cat = CommutativeAlgebras(GF(3)).FiniteDimensional().WithBasis() sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), - ....: Matrix([[0, 1], [0, 0]])]) + ....: Matrix([[0, 1], [0, 0]])], + ....: category=cat) sage: J = A.ideal(A([0,1])) sage: A([0,1]) in J True @@ -152,8 +163,10 @@ def basis_matrix(self): EXAMPLES:: + sage: cat = CommutativeAlgebras(GF(3)).FiniteDimensional().WithBasis() sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), - ....: Matrix([[0, 1], [0, 0]])]) + ....: Matrix([[0, 1], [0, 0]])], + ....: category=cat) sage: I = A.ideal(A([1,1])) sage: I.basis_matrix() [1 0] @@ -168,8 +181,10 @@ def vector_space(self): EXAMPLES:: + sage: cat = CommutativeAlgebras(GF(3)).FiniteDimensional().WithBasis() sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), - ....: Matrix([[0, 1], [0, 0]])]) + ....: Matrix([[0, 1], [0, 0]])], + ....: category=cat) sage: I = A.ideal(A([1,1])) sage: I.vector_space() Vector space of degree 2 and dimension 2 over Finite Field of size 3 diff --git a/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_morphism.py b/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_morphism.py index 997d1376a6f..ad043f68207 100644 --- a/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_morphism.py +++ b/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_morphism.py @@ -84,8 +84,10 @@ def _repr_(self): r""" TESTS:: + sage: cat = CommutativeAlgebras(QQ).FiniteDimensional().WithBasis() sage: A = FiniteDimensionalAlgebra(QQ, [Matrix([[1, 0], [0, 1]]), - ....: Matrix([[0, 1], [0, 0]])]) + ....: Matrix([[0, 1], [0, 0]])], + ....: category=cat) sage: I = A.maximal_ideal() # needs sage.libs.pari sage: q = A.quotient_map(I) # needs sage.libs.pari sage: q._repr_() # needs sage.libs.pari @@ -98,8 +100,10 @@ def __call__(self, x): """ TESTS:: + sage: cat = CommutativeAlgebras(QQ).FiniteDimensional().WithBasis() sage: A = FiniteDimensionalAlgebra(QQ, [Matrix([[1, 0], [0, 1]]), - ....: Matrix([[0, 1], [0, 0]])]) + ....: Matrix([[0, 1], [0, 0]])], + ....: category=cat) sage: I = A.maximal_ideal() # needs sage.libs.pari sage: q = A.quotient_map(I) # needs sage.libs.pari sage: q(0) == 0 and q(1) == 1 # needs sage.libs.pari @@ -180,8 +184,10 @@ def inverse_image(self, I): EXAMPLES:: + sage: cat = CommutativeAlgebras(QQ).FiniteDimensional().WithBasis() sage: A = FiniteDimensionalAlgebra(QQ, [Matrix([[1, 0], [0, 1]]), - ....: Matrix([[0, 1], [0, 0]])]) + ....: Matrix([[0, 1], [0, 0]])], + ....: category=cat) sage: I = A.maximal_ideal() # needs sage.libs.pari sage: q = A.quotient_map(I) # needs sage.libs.pari sage: B = q.codomain() # needs sage.libs.pari From 561bf1ab2a9f4c0bc7004eca35e08ce98f81a891 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Tue, 16 Jul 2024 21:15:42 +0200 Subject: [PATCH 223/231] pep8 cleanup in ode.pyx --- src/sage/calculus/ode.pyx | 149 ++++++++++++++++++-------------------- 1 file changed, 72 insertions(+), 77 deletions(-) diff --git a/src/sage/calculus/ode.pyx b/src/sage/calculus/ode.pyx index 1d4aef35b7b..c1209d59470 100644 --- a/src/sage/calculus/ode.pyx +++ b/src/sage/calculus/ode.pyx @@ -8,15 +8,15 @@ AUTHORS: - Robert Marik (2010 - fixed docstrings) """ -#***************************************************************************** +# **************************************************************************** # Copyright (C) 2004,2005,2006 Joshua Kantor # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. -# http://www.gnu.org/licenses/ -#***************************************************************************** +# https://www.gnu.org/licenses/ +# **************************************************************************** from cysignals.memory cimport sig_malloc, sig_free from cysignals.signals cimport sig_on, sig_off @@ -32,7 +32,7 @@ cdef class PyFunctionWrapper: cdef object the_parameters cdef int y_n - cdef set_yn(self,x): + cdef set_yn(self, x): self.y_n = x cdef class ode_system: @@ -53,31 +53,28 @@ cdef int c_f_compiled(double t, const double *y, double *dydt, void *params) noe cdef int status cdef ode_system wrapper wrapper = params - status = wrapper.c_f(t, y, dydt) # Could add parameters + status = wrapper.c_f(t, y, dydt) # Could add parameters return status cdef int c_jac(double t, const double *y, double *dfdy, double *dfdt, void *params) noexcept: cdef int i cdef int j cdef int y_n - cdef int param_n cdef PyFunctionWrapper wrapper wrapper = params y_n = wrapper.y_n - y_list = [] - for i in range(y_n): - y_list.append(y[i]) + y_list = [y[i] for i in range(y_n)] try: - if len(wrapper.the_parameters)==0: - jac_list=wrapper.the_jacobian(t,y_list) + if len(wrapper.the_parameters) == 0: + jac_list = wrapper.the_jacobian(t, y_list) else: - jac_list=wrapper.the_jacobian(t,y_list,wrapper.the_parameters) + jac_list = wrapper.the_jacobian(t, y_list, wrapper.the_parameters) for i in range(y_n): for j in range(y_n): - dfdy[i*y_n+j]=jac_list[i][j] + dfdy[i * y_n + j] = jac_list[i][j] for i in range(y_n): - dfdt[i]=jac_list[y_n][i] + dfdt[i] = jac_list[y_n][i] return GSL_SUCCESS except Exception: @@ -86,7 +83,6 @@ cdef int c_jac(double t, const double *y, double *dfdy, double *dfdt, void *para cdef int c_f(double t, const double *y, double *dydt, void *params) noexcept: cdef int i cdef int y_n - cdef int param_n cdef PyFunctionWrapper wrapper wrapper = params @@ -96,9 +92,9 @@ cdef int c_f(double t, const double *y, double *dydt, void *params) noexcept: y_list.append(y[i]) try: if len(wrapper.the_parameters)!=0: - dydt_list=wrapper.the_function(t,y_list,wrapper.the_parameters) + dydt_list = wrapper.the_function(t, y_list, wrapper.the_parameters) else: - dydt_list=wrapper.the_function(t,y_list) + dydt_list = wrapper.the_function(t, y_list) for i in range(y_n): dydt[i] = dydt_list[i] return GSL_SUCCESS @@ -344,9 +340,8 @@ class ode_solver(): sage: from tempfile import NamedTemporaryFile sage: with NamedTemporaryFile(suffix=".png") as f: ....: T.plot_solution(i=0, filename=f.name) - """ - def __init__(self,function=None,jacobian=None,h = 1e-2,error_abs=1e-10,error_rel=1e-10, a=False,a_dydt=False,scale_abs=False,algorithm="rkf45",y_0=None,t_span=None,params = []): + def __init__(self, function=None, jacobian=None, h=1e-2, error_abs=1e-10, error_rel=1e-10, a=False, a_dydt=False, scale_abs=False, algorithm="rkf45", y_0=None, t_span=None, params=[]): self.function = function self.jacobian = jacobian self.h = h @@ -403,23 +398,23 @@ class ode_solver(): pts = self.interpolate_solution(i) G = line2d(pts, **kwds) else: - pts = [(t,y[i]) for t,y in self.solution] + pts = [(t, y[i]) for t, y in self.solution] from sage.plot.point import point2d - G = point2d([(t,y[i]) for t,y in self.solution], **kwds) + G = point2d([(t, y[i]) for t, y in self.solution], **kwds) if filename is None: G.show() else: G.save(filename=filename) - def ode_solve(self,t_span=False,y_0=False,num_points=False,params=[]): - cdef double h # step size + def ode_solve(self, t_span=False, y_0=False, num_points=False, params=[]): + cdef double h # step size h = self.h cdef int i cdef int j cdef int type cdef int dim - cdef PyFunctionWrapper wrapper #struct to pass information into GSL C function - self.params=params + cdef PyFunctionWrapper wrapper # struct to pass information into GSL C function + self.params = params if t_span: self.t_span = t_span @@ -427,7 +422,7 @@ class ode_solver(): self.y_0 = y_0 dim = len(self.y_0) - type = isinstance(self.function,ode_system) + type = isinstance(self.function, ode_system) if type == 0: wrapper = PyFunctionWrapper() if self.function is not None: @@ -438,11 +433,11 @@ class ode_solver(): wrapper.the_jacobian = None else: wrapper.the_jacobian = self.jacobian - if self.params==[] and len(sage_getargspec(wrapper.the_function)[0])==2: - wrapper.the_parameters=[] - elif self.params==[] and len(sage_getargspec(wrapper.the_function)[0])>2: + if self.params == [] and len(sage_getargspec(wrapper.the_function)[0]) == 2: + wrapper.the_parameters = [] + elif self.params == [] and len(sage_getargspec(wrapper.the_function)[0]) > 2: raise ValueError("ODE system has a parameter but no parameters specified") - elif self.params!=[]: + elif self.params != []: wrapper.the_parameters = self.params wrapper.y_n = dim @@ -452,30 +447,30 @@ class ode_solver(): cdef double * scale_abs_array scale_abs_array=NULL - y = sig_malloc(sizeof(double)*(dim)) + y = sig_malloc(sizeof(double) * dim) if y == NULL: raise MemoryError("error allocating memory") result = [] - v = [0]*dim + v = [0] * dim cdef gsl_odeiv_step_type * T for i in range(dim): # copy initial conditions into C array y[i] = self.y_0[i] if self.algorithm == "rkf45": - T=gsl_odeiv_step_rkf45 + T = gsl_odeiv_step_rkf45 elif self.algorithm == "rk2": - T=gsl_odeiv_step_rk2 + T = gsl_odeiv_step_rk2 elif self.algorithm == "rk4": - T=gsl_odeiv_step_rk4 + T = gsl_odeiv_step_rk4 elif self.algorithm == "rkck": - T=gsl_odeiv_step_rkck + T = gsl_odeiv_step_rkck elif self.algorithm == "rk8pd": - T=gsl_odeiv_step_rk8pd + T = gsl_odeiv_step_rk8pd elif self.algorithm == "rk2imp": - T= gsl_odeiv_step_rk2imp + T = gsl_odeiv_step_rk2imp elif self.algorithm == "rk4imp": - T= gsl_odeiv_step_rk4imp + T = gsl_odeiv_step_rk4imp elif self.algorithm == "bsimp": T = gsl_odeiv_step_bsimp if not type and self.jacobian is None: @@ -488,38 +483,38 @@ class ode_solver(): raise TypeError("algorithm not valid") cdef gsl_odeiv_step * s - s = gsl_odeiv_step_alloc (T, dim) - if s==NULL: + s = gsl_odeiv_step_alloc(T, dim) + if s == NULL: sig_free(y) raise MemoryError("error setting up solver") cdef gsl_odeiv_control * c if not self.a and not self.a_dydt: - c = gsl_odeiv_control_y_new (self.error_abs, self.error_rel) + c = gsl_odeiv_control_y_new(self.error_abs, self.error_rel) elif self.a and self.a_dydt: if not self.scale_abs: - c = gsl_odeiv_control_standard_new(self.error_abs,self.error_rel,self.a,self.a_dydt) - elif hasattr(self.scale_abs,'__len__'): + c = gsl_odeiv_control_standard_new(self.error_abs, self.error_rel, self.a, self.a_dydt) + elif hasattr(self.scale_abs, '__len__'): if len(self.scale_abs) == dim: - scale_abs_array = sig_malloc(dim*sizeof(double)) + scale_abs_array = sig_malloc(dim * sizeof(double)) for i in range(dim): - scale_abs_array[i]=self.scale_abs[i] - c = gsl_odeiv_control_scaled_new(self.error_abs,self.error_rel,self.a,self.a_dydt,scale_abs_array,dim) + scale_abs_array[i] = self.scale_abs[i] + c = gsl_odeiv_control_scaled_new(self.error_abs, self.error_rel, self.a, self.a_dydt, scale_abs_array, dim) if c == NULL: - gsl_odeiv_control_free (c) - gsl_odeiv_step_free (s) + gsl_odeiv_control_free(c) + gsl_odeiv_step_free(s) sig_free(y) sig_free(scale_abs_array) raise MemoryError("error setting up solver") cdef gsl_odeiv_evolve * e - e = gsl_odeiv_evolve_alloc(dim) + e = gsl_odeiv_evolve_alloc(dim) if e == NULL: - gsl_odeiv_control_free (c) - gsl_odeiv_step_free (s) + gsl_odeiv_control_free(c) + gsl_odeiv_step_free(s) sig_free(y) sig_free(scale_abs_array) raise MemoryError("error setting up solver") @@ -540,59 +535,59 @@ class ode_solver(): import copy cdef int n - if len(self.t_span)==2 and num_points: + if len(self.t_span) == 2 and num_points: try: n = num_points except TypeError: - gsl_odeiv_evolve_free (e) - gsl_odeiv_control_free (c) - gsl_odeiv_step_free (s) + gsl_odeiv_evolve_free(e) + gsl_odeiv_control_free(c) + gsl_odeiv_step_free(s) sig_free(y) sig_free(scale_abs_array) raise TypeError("numpoints must be integer") result.append((self.t_span[0], self.y_0)) - delta = (self.t_span[1]-self.t_span[0])/(1.0*num_points) + delta = (self.t_span[1] - self.t_span[0]) / (1.0 * num_points) t = self.t_span[0] - t_end = self.t_span[0]+delta + t_end = self.t_span[0] + delta for i in range(1, n + 1): - while (t < t_end): + while t < t_end: try: sig_on() - status = gsl_odeiv_evolve_apply (e, c, s, &sys, &t, t_end, &h, y) + status = gsl_odeiv_evolve_apply(e, c, s, &sys, &t, t_end, &h, y) sig_off() - if (status != GSL_SUCCESS): + if status != GSL_SUCCESS: raise RuntimeError except RuntimeError: - gsl_odeiv_evolve_free (e) - gsl_odeiv_control_free (c) - gsl_odeiv_step_free (s) + gsl_odeiv_evolve_free(e) + gsl_odeiv_control_free(c) + gsl_odeiv_step_free(s) sig_free(y) sig_free(scale_abs_array) raise ValueError("error solving") for j in range(dim): - v[j]= y[j] - result.append( (t,copy.copy(v)) ) + v[j] = y[j] + result.append((t, copy.copy(v))) t = t_end - t_end= t+delta + t_end = t + delta else: n = len(self.t_span) result.append((self.t_span[0], self.y_0)) t = self.t_span[0] for i in range(1, n): - t_end=self.t_span[i] - while (t < t_end): + t_end = self.t_span[i] + while t < t_end: try: sig_on() - status = gsl_odeiv_evolve_apply (e, c, s, &sys, &t, t_end, &h, y) + status = gsl_odeiv_evolve_apply(e, c, s, &sys, &t, t_end, &h, y) sig_off() - if (status != GSL_SUCCESS): + if status != GSL_SUCCESS: raise RuntimeError except RuntimeError: - gsl_odeiv_evolve_free (e) - gsl_odeiv_control_free (c) - gsl_odeiv_step_free (s) + gsl_odeiv_evolve_free(e) + gsl_odeiv_control_free(c) + gsl_odeiv_step_free(s) sig_free(y) sig_free(scale_abs_array) raise ValueError("error solving") @@ -603,9 +598,9 @@ class ode_solver(): t = self.t_span[i] - gsl_odeiv_evolve_free (e) - gsl_odeiv_control_free (c) - gsl_odeiv_step_free (s) + gsl_odeiv_evolve_free(e) + gsl_odeiv_control_free(c) + gsl_odeiv_step_free(s) sig_free(y) sig_free(scale_abs_array) self.solution = result From 2d8e920602cd80250987c363c971ebeaa041d53b Mon Sep 17 00:00:00 2001 From: Newtech66 Date: Wed, 17 Jul 2024 02:06:31 +0530 Subject: [PATCH 224/231] More minor fixes --- src/sage/groups/perm_gps/permgroup.py | 31 ++++++++++++++++----------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/src/sage/groups/perm_gps/permgroup.py b/src/sage/groups/perm_gps/permgroup.py index 87540379001..d97aad93b03 100644 --- a/src/sage/groups/perm_gps/permgroup.py +++ b/src/sage/groups/perm_gps/permgroup.py @@ -1584,7 +1584,7 @@ def smallest_moved_point(self): @cached_method def disjoint_direct_product_decomposition(self): r""" - Returns the finest partition of the underlying set such that ``self`` + Return the finest partition of the underlying set such that ``self`` is isomorphic to the direct product of the projections of ``self`` onto each part of the partition. Each part is a union of orbits of ``self``. @@ -1612,6 +1612,13 @@ def disjoint_direct_product_decomposition(self): sage: PermutationGroup(PermutationGroup(gap_group=B).gens(),domain=list(S[0])).disjoint_direct_product_decomposition() {{1, 2, 3}} + An example with a different domain:: + + sage: PermutationGroup([[('a','c','d'),('b','e')]]).disjoint_direct_product_decomposition() + {{'a', 'c', 'd'}, {'b', 'e'}} + sage: PermutationGroup([[('a','c','d','b','e')]]).disjoint_direct_product_decomposition() + {{'a', 'b', 'c', 'd', 'e'}} + Counting the number of "connected" permutation groups of degree `n`:: sage: seq = [sum(1 for G in SymmetricGroup(n).conjugacy_classes_subgroups() if len(G.disjoint_direct_product_decomposition()) == 1) for n in range(1,8)]; seq @@ -1622,22 +1629,22 @@ def disjoint_direct_product_decomposition(self): from sage.combinat.set_partition import SetPartition from sage.sets.disjoint_set import DisjointSet H = self._libgap_() - if self.is_trivial(): - return SetPartition(DisjointSet(self.domain())) - if libgap.NrMovedPoints(H) == self.degree() and libgap.IsTransitive(H): - return SetPartition([self.domain()]) - O = libgap.Orbits(H) - k = len(O) + # sort each orbit and order list by smallest element of each orbit + O = libgap.List([libgap.ShallowCopy(orbit) for orbit in libgap.Orbits(H)]) + for orbit in O: + libgap.Sort(orbit) + O.Sort() + num_orbits = len(O) OrbitMapping = dict() - for i in range(k): + for i in range(num_orbits): for x in O[i]: OrbitMapping[x] = i C = libgap.StabChain(H, libgap.Concatenation(O)) X = libgap.StrongGeneratorsStabChain(C) - P = DisjointSet(k) + P = DisjointSet(num_orbits) R = libgap.List([]) identity = libgap.Identity(H) - for i in range(k-1): + for i in range(num_orbits-1): libgap.Append(R, O[i]) Xp = libgap.List([]) while True: @@ -1646,14 +1653,14 @@ def disjoint_direct_product_decomposition(self): C = C['stabilizer'] else: break - except ValueError: #this should catch a GAPError but I don't know how to make it work + except ValueError: break for x in X: xs = libgap.SiftedPermutation(C, x) if xs != identity: - cj = OrbitMapping[libgap.SmallestMovedPoint(libgap.RestrictedPerm(x, R))] libgap.Add(Xp, xs) if libgap.RestrictedPerm(xs, O[i+1]) != identity: + cj = OrbitMapping[libgap.SmallestMovedPoint(libgap.RestrictedPerm(x, R))] P.union(i+1, cj) else: libgap.Add(Xp, x) From c8417edf83091dadf3072d157d9d286958da531b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Wed, 17 Jul 2024 07:33:01 +0200 Subject: [PATCH 225/231] suggested detail --- src/sage/calculus/ode.pyx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/calculus/ode.pyx b/src/sage/calculus/ode.pyx index c1209d59470..0db64d86fe0 100644 --- a/src/sage/calculus/ode.pyx +++ b/src/sage/calculus/ode.pyx @@ -91,7 +91,7 @@ cdef int c_f(double t, const double *y, double *dydt, void *params) noexcept: for i in range(y_n): y_list.append(y[i]) try: - if len(wrapper.the_parameters)!=0: + if len(wrapper.the_parameters) != 0: dydt_list = wrapper.the_function(t, y_list, wrapper.the_parameters) else: dydt_list = wrapper.the_function(t, y_list) @@ -497,7 +497,7 @@ class ode_solver(): c = gsl_odeiv_control_standard_new(self.error_abs, self.error_rel, self.a, self.a_dydt) elif hasattr(self.scale_abs, '__len__'): if len(self.scale_abs) == dim: - scale_abs_array = sig_malloc(dim * sizeof(double)) + scale_abs_array = sig_malloc(dim * sizeof(double)) for i in range(dim): scale_abs_array[i] = self.scale_abs[i] c = gsl_odeiv_control_scaled_new(self.error_abs, self.error_rel, self.a, self.a_dydt, scale_abs_array, dim) From b196b22e4a82c331d63e69d019eb468a276f7d1f Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 17 Jul 2024 14:44:58 +0900 Subject: [PATCH 226/231] src/sage/knots/knotinfo.py: Use block # needs --- src/sage/knots/knotinfo.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/sage/knots/knotinfo.py b/src/sage/knots/knotinfo.py index 6bc9c3a09cf..efd5da177ec 100644 --- a/src/sage/knots/knotinfo.py +++ b/src/sage/knots/knotinfo.py @@ -1520,14 +1520,16 @@ def jones_polynomial(self, variab=None, skein_normalization=False, puiseux=False of the positive crossings of the right-handed trefoil):: sage: K3_1 = KnotInfo.K3_1 - sage: K3_1j = K3_1.jones_polynomial() # needs sage.symbolic + + sage: # needs sage.symbolic + sage: K3_1j = K3_1.jones_polynomial() sage: L2a1_1j = Ljt # see note above sage: R = L2a1_1j.parent() sage: Oj = R(1) sage: t = R('t') - sage: lhs = expand(~t*K3_1j - t*Oj) # needs sage.symbolic + sage: lhs = expand(~t*K3_1j - t*Oj) sage: rhs = expand((sqrt(t) - ~sqrt(t))*L2a1_1j) - sage: bool(lhs == rhs) # needs sage.symbolic + sage: bool(lhs == rhs) True The same with the Puiseux series version:: From c1ac6185a5a89087778c1eed5f666d0639eb047a Mon Sep 17 00:00:00 2001 From: Shriya M <25shriya@gmail.com> Date: Wed, 17 Jul 2024 13:36:45 +0530 Subject: [PATCH 227/231] Updated repr() for LiftMap and QuotientMap classes --- src/sage/rings/number_field/number_field_ideal.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/rings/number_field/number_field_ideal.py b/src/sage/rings/number_field/number_field_ideal.py index a0de16c4079..979bc0dc869 100644 --- a/src/sage/rings/number_field/number_field_ideal.py +++ b/src/sage/rings/number_field/number_field_ideal.py @@ -3396,7 +3396,7 @@ def __call__(self, x): w = v * self.__M_OK_change return self.__Q( list(w) ) - def _repr_(self): + def __repr__(self): r""" Return a string representation of this QuotientMap. @@ -3464,7 +3464,7 @@ def __call__(self, x): z = (w * self.__M_OK_map).list() return self.__OK(sum(z[i] * self.__Kgen ** i for i in range(len(z)))) - def _repr_(self): + def __repr__(self): r""" Return a string representation of this QuotientMap. From a8e59c6752e75fe898460cdb050e46a6c552ac22 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 17 Jul 2024 17:21:17 +0900 Subject: [PATCH 228/231] tox.ini: Remove centos-7 from tested platforms --- .../devcontainer.json | 25 ------- .../portability-Dockerfile | 1 - .../devcontainer.json | 25 ------- .../portability-Dockerfile | 1 - .github/workflows/docker.yml | 1 - .../developer/portability_platform_table.rst | 65 ------------------- tox.ini | 1 - 7 files changed, 119 deletions(-) delete mode 100644 .devcontainer/portability-centos-7-devtoolset-gcc_11-minimal/devcontainer.json delete mode 120000 .devcontainer/portability-centos-7-devtoolset-gcc_11-minimal/portability-Dockerfile delete mode 100644 .devcontainer/portability-centos-7-devtoolset-gcc_11-standard/devcontainer.json delete mode 120000 .devcontainer/portability-centos-7-devtoolset-gcc_11-standard/portability-Dockerfile diff --git a/.devcontainer/portability-centos-7-devtoolset-gcc_11-minimal/devcontainer.json b/.devcontainer/portability-centos-7-devtoolset-gcc_11-minimal/devcontainer.json deleted file mode 100644 index 3bd9b05e616..00000000000 --- a/.devcontainer/portability-centos-7-devtoolset-gcc_11-minimal/devcontainer.json +++ /dev/null @@ -1,25 +0,0 @@ -// The command "tox -e update_docker_platforms" -// creates .devcontainer/portability-*-*/devcontainer.json -// from .devcontainer/portability-devcontainer.json.in -// See https://aka.ms/devcontainer.json for format details. -{ - "name": "centos-7-devtoolset-gcc_11-minimal (≥ 8-core)", - "build": { - "dockerfile": "portability-Dockerfile", - // See tox.ini for definitions - "args": { - "SYSTEM_FACTOR": "centos-7-devtoolset-gcc_11", - "PACKAGE_FACTOR": "minimal", - "DOCKER_TARGET": "with-targets", - "DOCKER_TAG": "dev" - } - }, - "containerEnv": { - "MAKE": "make -j4" - }, - "onCreateCommand": ".devcontainer/onCreate.sh", - "updateContentCommand": ".devcontainer/portability-updateContent.sh", - "extensions": [ - "ms-python.python" - ] -} diff --git a/.devcontainer/portability-centos-7-devtoolset-gcc_11-minimal/portability-Dockerfile b/.devcontainer/portability-centos-7-devtoolset-gcc_11-minimal/portability-Dockerfile deleted file mode 120000 index 692e2a79d64..00000000000 --- a/.devcontainer/portability-centos-7-devtoolset-gcc_11-minimal/portability-Dockerfile +++ /dev/null @@ -1 +0,0 @@ -../portability-Dockerfile \ No newline at end of file diff --git a/.devcontainer/portability-centos-7-devtoolset-gcc_11-standard/devcontainer.json b/.devcontainer/portability-centos-7-devtoolset-gcc_11-standard/devcontainer.json deleted file mode 100644 index 4a1bf2d5bbd..00000000000 --- a/.devcontainer/portability-centos-7-devtoolset-gcc_11-standard/devcontainer.json +++ /dev/null @@ -1,25 +0,0 @@ -// The command "tox -e update_docker_platforms" -// creates .devcontainer/portability-*-*/devcontainer.json -// from .devcontainer/portability-devcontainer.json.in -// See https://aka.ms/devcontainer.json for format details. -{ - "name": "centos-7-devtoolset-gcc_11-standard (≥ 8-core)", - "build": { - "dockerfile": "portability-Dockerfile", - // See tox.ini for definitions - "args": { - "SYSTEM_FACTOR": "centos-7-devtoolset-gcc_11", - "PACKAGE_FACTOR": "standard", - "DOCKER_TARGET": "with-targets", - "DOCKER_TAG": "dev" - } - }, - "containerEnv": { - "MAKE": "make -j4" - }, - "onCreateCommand": ".devcontainer/onCreate.sh", - "updateContentCommand": ".devcontainer/portability-updateContent.sh", - "extensions": [ - "ms-python.python" - ] -} diff --git a/.devcontainer/portability-centos-7-devtoolset-gcc_11-standard/portability-Dockerfile b/.devcontainer/portability-centos-7-devtoolset-gcc_11-standard/portability-Dockerfile deleted file mode 120000 index 692e2a79d64..00000000000 --- a/.devcontainer/portability-centos-7-devtoolset-gcc_11-standard/portability-Dockerfile +++ /dev/null @@ -1 +0,0 @@ -../portability-Dockerfile \ No newline at end of file diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index ebde1bfde8e..2b6d83f6e78 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -47,7 +47,6 @@ on: "fedora-38", "fedora-39", "fedora-40", - "centos-7-devtoolset-gcc_11", "centos-stream-9-python3.9", "almalinux-8-python3.9", "almalinux-9-python3.11", diff --git a/src/doc/en/developer/portability_platform_table.rst b/src/doc/en/developer/portability_platform_table.rst index 67ebb9f7c0b..617dfd0f868 100644 --- a/src/doc/en/developer/portability_platform_table.rst +++ b/src/doc/en/developer/portability_platform_table.rst @@ -1564,60 +1564,6 @@ .. |codespace-fedora-40-maximal| image:: https://github.com/codespaces/badge.svg :target: https://codespaces.new/sagemath/sage?devcontainer_path=.devcontainer%2Fportability-fedora-40-maximal%2Fdevcontainer.json -.. |image-centos-7-devtoolset-gcc_11-minimal-with-system-packages| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-centos-7-devtoolset-gcc_11-minimal-with-system-packages/size?tag=dev&label=with-system-packages&color=%23696969 - :target: https://ghcr.io/sagemath/sage/sage-centos-7-devtoolset-gcc_11-minimal-with-system-packages - -.. |image-centos-7-devtoolset-gcc_11-minimal-configured| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-centos-7-devtoolset-gcc_11-minimal-configured/latest_tag?ignore=latest,dev,*-failed&label=configured&color=%23696969 - :target: https://ghcr.io/sagemath/sage/sage-centos-7-devtoolset-gcc_11-minimal-configured - -.. |image-centos-7-devtoolset-gcc_11-minimal-with-targets-pre| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-centos-7-devtoolset-gcc_11-minimal-with-targets-pre/latest_tag?ignore=latest,dev,*-failed&label=with-targets-pre&color=%23677895 - :target: https://ghcr.io/sagemath/sage/sage-centos-7-devtoolset-gcc_11-minimal-with-targets-pre - -.. |image-centos-7-devtoolset-gcc_11-minimal-with-targets| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-centos-7-devtoolset-gcc_11-minimal-with-targets/latest_tag?ignore=latest,dev,*-failed&label=with-targets&color=%236686c1 - :target: https://ghcr.io/sagemath/sage/sage-centos-7-devtoolset-gcc_11-minimal-with-targets - -.. |image-centos-7-devtoolset-gcc_11-minimal-with-targets-optional| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-centos-7-devtoolset-gcc_11-minimal-with-targets-optional/latest_tag?ignore=latest,dev,*-failed&label=with-targets-optional&color=%236495ed - :target: https://ghcr.io/sagemath/sage/sage-centos-7-devtoolset-gcc_11-minimal-with-targets-optional - -.. |codespace-centos-7-devtoolset-gcc_11-minimal| image:: https://github.com/codespaces/badge.svg - :target: https://codespaces.new/sagemath/sage?devcontainer_path=.devcontainer%2Fportability-centos-7-devtoolset-gcc_11-minimal%2Fdevcontainer.json - -.. |image-centos-7-devtoolset-gcc_11-standard-with-system-packages| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-centos-7-devtoolset-gcc_11-standard-with-system-packages/size?tag=dev&label=with-system-packages&color=%23696969 - :target: https://ghcr.io/sagemath/sage/sage-centos-7-devtoolset-gcc_11-standard-with-system-packages - -.. |image-centos-7-devtoolset-gcc_11-standard-configured| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-centos-7-devtoolset-gcc_11-standard-configured/latest_tag?ignore=latest,dev,*-failed&label=configured&color=%23696969 - :target: https://ghcr.io/sagemath/sage/sage-centos-7-devtoolset-gcc_11-standard-configured - -.. |image-centos-7-devtoolset-gcc_11-standard-with-targets-pre| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-centos-7-devtoolset-gcc_11-standard-with-targets-pre/latest_tag?ignore=latest,dev,*-failed&label=with-targets-pre&color=%235d8a4c - :target: https://ghcr.io/sagemath/sage/sage-centos-7-devtoolset-gcc_11-standard-with-targets-pre - -.. |image-centos-7-devtoolset-gcc_11-standard-with-targets| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-centos-7-devtoolset-gcc_11-standard-with-targets/latest_tag?ignore=latest,dev,*-failed&label=with-targets&color=%2350ab2e - :target: https://ghcr.io/sagemath/sage/sage-centos-7-devtoolset-gcc_11-standard-with-targets - -.. |image-centos-7-devtoolset-gcc_11-standard-with-targets-optional| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-centos-7-devtoolset-gcc_11-standard-with-targets-optional/latest_tag?ignore=latest,dev,*-failed&label=with-targets-optional&color=%2344cc11 - :target: https://ghcr.io/sagemath/sage/sage-centos-7-devtoolset-gcc_11-standard-with-targets-optional - -.. |codespace-centos-7-devtoolset-gcc_11-standard| image:: https://github.com/codespaces/badge.svg - :target: https://codespaces.new/sagemath/sage?devcontainer_path=.devcontainer%2Fportability-centos-7-devtoolset-gcc_11-standard%2Fdevcontainer.json - -.. |image-centos-7-devtoolset-gcc_11-maximal-with-system-packages| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-centos-7-devtoolset-gcc_11-maximal-with-system-packages/size?tag=dev&label=with-system-packages&color=%23696969 - :target: https://ghcr.io/sagemath/sage/sage-centos-7-devtoolset-gcc_11-maximal-with-system-packages - -.. |image-centos-7-devtoolset-gcc_11-maximal-configured| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-centos-7-devtoolset-gcc_11-maximal-configured/latest_tag?ignore=latest,dev,*-failed&label=configured&color=%23696969 - :target: https://ghcr.io/sagemath/sage/sage-centos-7-devtoolset-gcc_11-maximal-configured - -.. |image-centos-7-devtoolset-gcc_11-maximal-with-targets-pre| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-centos-7-devtoolset-gcc_11-maximal-with-targets-pre/latest_tag?ignore=latest,dev,*-failed&label=with-targets-pre&color=%238f6b8d - :target: https://ghcr.io/sagemath/sage/sage-centos-7-devtoolset-gcc_11-maximal-with-targets-pre - -.. |image-centos-7-devtoolset-gcc_11-maximal-with-targets| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-centos-7-devtoolset-gcc_11-maximal-with-targets/latest_tag?ignore=latest,dev,*-failed&label=with-targets&color=%23b46eb2 - :target: https://ghcr.io/sagemath/sage/sage-centos-7-devtoolset-gcc_11-maximal-with-targets - -.. |image-centos-7-devtoolset-gcc_11-maximal-with-targets-optional| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-centos-7-devtoolset-gcc_11-maximal-with-targets-optional/latest_tag?ignore=latest,dev,*-failed&label=with-targets-optional&color=%23da70d6 - :target: https://ghcr.io/sagemath/sage/sage-centos-7-devtoolset-gcc_11-maximal-with-targets-optional - -.. |codespace-centos-7-devtoolset-gcc_11-maximal| image:: https://github.com/codespaces/badge.svg - :target: https://codespaces.new/sagemath/sage?devcontainer_path=.devcontainer%2Fportability-centos-7-devtoolset-gcc_11-maximal%2Fdevcontainer.json - .. |image-centos-stream-9-python3.9-minimal-with-system-packages| image:: https://ghcr-badge.egpl.dev/sagemath/sage/sage-centos-stream-9-python3.9-minimal-with-system-packages/size?tag=dev&label=with-system-packages&color=%23696969 :target: https://ghcr.io/sagemath/sage/sage-centos-stream-9-python3.9-minimal-with-system-packages @@ -2647,17 +2593,6 @@ * -    ‑*maximal* - |image-fedora-40-maximal-with-system-packages| |image-fedora-40-maximal-with-targets-pre| - - * - **centos**-7-devtoolset-gcc_11 - -    ‑*minimal* - - |image-centos-7-devtoolset-gcc_11-minimal-with-system-packages| |image-centos-7-devtoolset-gcc_11-minimal-with-targets-pre| |image-centos-7-devtoolset-gcc_11-minimal-with-targets| |image-centos-7-devtoolset-gcc_11-minimal-with-targets-optional| - - |codespace-centos-7-devtoolset-gcc_11-minimal| - * -    ‑*standard* - - |image-centos-7-devtoolset-gcc_11-standard-with-system-packages| |image-centos-7-devtoolset-gcc_11-standard-with-targets-pre| |image-centos-7-devtoolset-gcc_11-standard-with-targets| |image-centos-7-devtoolset-gcc_11-standard-with-targets-optional| - - |codespace-centos-7-devtoolset-gcc_11-standard| - * -    ‑*maximal* - - |image-centos-7-devtoolset-gcc_11-maximal-with-system-packages| |image-centos-7-devtoolset-gcc_11-maximal-with-targets-pre| - - * - **centos**-stream-9-python3.9    ‑*minimal* diff --git a/tox.ini b/tox.ini index 2d90a0ba4f8..631a47ba3f6 100644 --- a/tox.ini +++ b/tox.ini @@ -863,7 +863,6 @@ setenv = debian-{bullseye,bookworm,trixie,sid} \ linuxmint-{20.1,20.2,20.3,21,21.1,21.2,21.3} \ fedora-{30,31,32,33,34,35,36,37,38,39,40} \ - centos-7-devtoolset-gcc_11 \ centos-stream-9-python3.9 \ almalinux-{8-python3.9,9-python3.11} \ gentoo-python{3.10,3.11,3.12} \ From 47274071769801510b5c74b2104c254a10e2bdbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Wed, 17 Jul 2024 21:16:59 +0200 Subject: [PATCH 229/231] refining the category of all-commuting g-algebras --- src/sage/algebras/free_algebra.py | 5 +++-- src/sage/rings/polynomial/plural.pyx | 15 ++++++++++++--- src/sage/structure/factory.pyx | 4 ++-- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/sage/algebras/free_algebra.py b/src/sage/algebras/free_algebra.py index 00b0dfdafa7..a5d4d5182ff 100644 --- a/src/sage/algebras/free_algebra.py +++ b/src/sage/algebras/free_algebra.py @@ -892,7 +892,7 @@ def g_algebra(self, relations, names=None, order='degrevlex', check=True): """ The `G`-Algebra derived from this algebra by relations. - By default is assumed, that two variables commute. + By default it is assumed that any two variables commute. .. TODO:: @@ -935,6 +935,7 @@ def g_algebra(self, relations, names=None, order='degrevlex', check=True): (-t)*x*y + t*y + (t + 1) """ from sage.matrix.constructor import Matrix + commutative = not relations base_ring = self.base_ring() polynomial_ring = PolynomialRing(base_ring, self.gens()) @@ -970,7 +971,7 @@ def g_algebra(self, relations, names=None, order='degrevlex', check=True): from sage.rings.polynomial.plural import g_Algebra return g_Algebra(base_ring, cmat, dmat, names=names or self.variable_names(), - order=order, check=check) + order=order, check=check, commutative=commutative) def poincare_birkhoff_witt_basis(self): """ diff --git a/src/sage/rings/polynomial/plural.pyx b/src/sage/rings/polynomial/plural.pyx index d78464e1deb..cdcb01eb2d2 100644 --- a/src/sage/rings/polynomial/plural.pyx +++ b/src/sage/rings/polynomial/plural.pyx @@ -157,7 +157,7 @@ class G_AlgFactory(UniqueFactory): - ``key`` -- a 6-tuple, formed by a base ring, a tuple of names, two matrices over a polynomial ring over the base ring with the given variable names, a term order, and a category - - ``extra_args`` -- a dictionary, whose only relevant key is 'check'. + - ``extra_args`` -- a dictionary, whose only relevant key is 'check' TESTS:: @@ -174,7 +174,7 @@ class G_AlgFactory(UniqueFactory): category, check) def create_key_and_extra_args(self, base_ring, c, d, names=None, order=None, - category=None, check=None): + category=None, check=None, commutative=None): """ Create a unique key for g-algebras. @@ -186,6 +186,7 @@ class G_AlgFactory(UniqueFactory): - ``order`` -- (optional) term order - ``category`` -- (optional) category - ``check`` -- optional bool + - ``commutative`` -- optional bool TESTS:: @@ -193,6 +194,10 @@ class G_AlgFactory(UniqueFactory): sage: H = A.g_algebra({y*x:x*y-z, z*x:x*z+2*x, z*y:y*z-2*y}) sage: H is A.g_algebra({y*x:x*y-z, z*x:x*z+2*x, z*y:y*z-2*y}) # indirect doctest True + + sage: P = A.g_algebra(relations={}, order='lex') + sage: P.category() + Category of commutative algebras over Rational Field """ if names is None: raise ValueError("The generator names must be provided") @@ -213,7 +218,11 @@ class G_AlgFactory(UniqueFactory): d.set_immutable() # Get the correct category - category = check_default_category(Algebras(base_ring), category) + if commutative: + usualcat = Algebras(base_ring).Commutative() + else: + usualcat = Algebras(base_ring) + category = check_default_category(usualcat, category) # Extra arg if check is None: diff --git a/src/sage/structure/factory.pyx b/src/sage/structure/factory.pyx index ab8b5afa4a1..548e2c40a4e 100644 --- a/src/sage/structure/factory.pyx +++ b/src/sage/structure/factory.pyx @@ -171,9 +171,9 @@ cdef class UniqueFactory(SageObject): ....: return args, {'impl':kwds.get('impl', None)} ....: def create_object(self, version, key, **extra_args): ....: impl = extra_args['impl'] - ....: if impl=='C': + ....: if impl == 'C': ....: return C(*key) - ....: if impl=='D': + ....: if impl == 'D': ....: return D(*key) ....: return E(*key) ....: From 27a0fa9b4ba9824ce7a241e7b2230ee48307dc6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Thu, 18 Jul 2024 07:47:05 +0200 Subject: [PATCH 230/231] alignment in the doc --- .../finite_dimensional_algebra.py | 12 ++++++++---- .../finite_dimensional_algebra_ideal.py | 12 ++++++------ .../finite_dimensional_algebra_morphism.py | 6 +++--- 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra.py b/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra.py index 3eb076e8e89..a634b546926 100644 --- a/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra.py +++ b/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra.py @@ -456,7 +456,8 @@ def ideal(self, gens=None, given_by_matrix=False, side=None): sage: cat = Algebras(GF(3)).FiniteDimensional().WithBasis() sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), - ....: Matrix([[0, 1], [0, 0]])], category=cat) + ....: Matrix([[0, 1], [0, 0]])], + ....: category=cat) sage: A.ideal(A([1,1])) Ideal (e0 + e1) of Finite-dimensional algebra of degree 2 over Finite Field of size 3 @@ -766,7 +767,8 @@ def quotient_map(self, ideal): sage: cat = Algebras(GF(3)).FiniteDimensional().WithBasis() sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), - ....: Matrix([[0, 1], [0, 0]])], category=cat) + ....: Matrix([[0, 1], [0, 0]])], + ....: category=cat) sage: q0 = A.quotient_map(A.zero_ideal()); q0 Morphism from Finite-dimensional algebra of degree 2 over Finite Field of size 3 @@ -815,7 +817,8 @@ def maximal_ideal(self): sage: cat = CommutativeAlgebras(GF(3)).FiniteDimensional().WithBasis() sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), - ....: Matrix([[0, 1], [0, 0]])], category=cat) + ....: Matrix([[0, 1], [0, 0]])], + ....: category=cat) sage: A.maximal_ideal() # needs sage.rings.finite_rings Ideal (0, e1) of Finite-dimensional algebra of degree 2 over Finite Field of size 3 @@ -823,7 +826,8 @@ def maximal_ideal(self): sage: cat = CommutativeAlgebras(QQ).FiniteDimensional().WithBasis() sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0,0], [0,1,0], [0,0,0]]), ....: Matrix([[0,1,0], [0,0,0], [0,0,0]]), - ....: Matrix([[0,0,0], [0,0,0], [0,0,1]])], category=cat) + ....: Matrix([[0,0,0], [0,0,0], [0,0,1]])], + ....: category=cat) sage: B.maximal_ideal() # needs sage.libs.pari Traceback (most recent call last): ... diff --git a/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_ideal.py b/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_ideal.py index 53f2660306d..c328b65c5b2 100644 --- a/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_ideal.py +++ b/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_ideal.py @@ -44,7 +44,7 @@ class FiniteDimensionalAlgebraIdeal(Ideal_generic): sage: cat = CommutativeAlgebras(GF(3)).FiniteDimensional().WithBasis() sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), ....: Matrix([[0, 1], [0, 0]])], - ....: category=cat) + ....: category=cat) sage: A.ideal(A([0,1])) Ideal (e1) of Finite-dimensional algebra of degree 2 over Finite Field of size 3 """ @@ -55,7 +55,7 @@ def __init__(self, A, gens=None, given_by_matrix=False): sage: cat = CommutativeAlgebras(GF(3)).FiniteDimensional().WithBasis() sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), ....: Matrix([[0, 1], [0, 0]])], - ....: category=cat) + ....: category=cat) sage: I = A.ideal(A([0,1])) sage: TestSuite(I).run(skip="_test_category") # Currently ideals are not using the category framework """ @@ -87,7 +87,7 @@ def _richcmp_(self, other, op): sage: cat = CommutativeAlgebras(GF(3)).FiniteDimensional().WithBasis() sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), ....: Matrix([[0, 1], [0, 0]])], - ....: category=cat) + ....: category=cat) sage: I = A.ideal(A([1,1])) sage: J = A.ideal(A([0,1])) sage: I == J @@ -146,7 +146,7 @@ def __contains__(self, elt): sage: cat = CommutativeAlgebras(GF(3)).FiniteDimensional().WithBasis() sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), ....: Matrix([[0, 1], [0, 0]])], - ....: category=cat) + ....: category=cat) sage: J = A.ideal(A([0,1])) sage: A([0,1]) in J True @@ -166,7 +166,7 @@ def basis_matrix(self): sage: cat = CommutativeAlgebras(GF(3)).FiniteDimensional().WithBasis() sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), ....: Matrix([[0, 1], [0, 0]])], - ....: category=cat) + ....: category=cat) sage: I = A.ideal(A([1,1])) sage: I.basis_matrix() [1 0] @@ -184,7 +184,7 @@ def vector_space(self): sage: cat = CommutativeAlgebras(GF(3)).FiniteDimensional().WithBasis() sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), ....: Matrix([[0, 1], [0, 0]])], - ....: category=cat) + ....: category=cat) sage: I = A.ideal(A([1,1])) sage: I.vector_space() Vector space of degree 2 and dimension 2 over Finite Field of size 3 diff --git a/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_morphism.py b/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_morphism.py index ad043f68207..dfcaa1d0341 100644 --- a/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_morphism.py +++ b/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_morphism.py @@ -87,7 +87,7 @@ def _repr_(self): sage: cat = CommutativeAlgebras(QQ).FiniteDimensional().WithBasis() sage: A = FiniteDimensionalAlgebra(QQ, [Matrix([[1, 0], [0, 1]]), ....: Matrix([[0, 1], [0, 0]])], - ....: category=cat) + ....: category=cat) sage: I = A.maximal_ideal() # needs sage.libs.pari sage: q = A.quotient_map(I) # needs sage.libs.pari sage: q._repr_() # needs sage.libs.pari @@ -103,7 +103,7 @@ def __call__(self, x): sage: cat = CommutativeAlgebras(QQ).FiniteDimensional().WithBasis() sage: A = FiniteDimensionalAlgebra(QQ, [Matrix([[1, 0], [0, 1]]), ....: Matrix([[0, 1], [0, 0]])], - ....: category=cat) + ....: category=cat) sage: I = A.maximal_ideal() # needs sage.libs.pari sage: q = A.quotient_map(I) # needs sage.libs.pari sage: q(0) == 0 and q(1) == 1 # needs sage.libs.pari @@ -187,7 +187,7 @@ def inverse_image(self, I): sage: cat = CommutativeAlgebras(QQ).FiniteDimensional().WithBasis() sage: A = FiniteDimensionalAlgebra(QQ, [Matrix([[1, 0], [0, 1]]), ....: Matrix([[0, 1], [0, 0]])], - ....: category=cat) + ....: category=cat) sage: I = A.maximal_ideal() # needs sage.libs.pari sage: q = A.quotient_map(I) # needs sage.libs.pari sage: B = q.codomain() # needs sage.libs.pari From 79c047c0a22a98bea4567d182c694fd4df1aea81 Mon Sep 17 00:00:00 2001 From: Release Manager Date: Wed, 24 Jul 2024 22:57:13 +0200 Subject: [PATCH 231/231] Updated SageMath version to 10.5.beta0 --- .upstream.d/20-github.com-sagemath-sage-releases | 2 +- CITATION.cff | 4 ++-- VERSION.txt | 2 +- build/pkgs/configure/checksums.ini | 4 ++-- build/pkgs/configure/package-version.txt | 2 +- build/pkgs/sage_conf/version_requirements.txt | 2 +- build/pkgs/sage_docbuild/version_requirements.txt | 2 +- build/pkgs/sage_setup/version_requirements.txt | 2 +- build/pkgs/sage_sws2rst/version_requirements.txt | 2 +- build/pkgs/sagelib/version_requirements.txt | 2 +- build/pkgs/sagemath_bliss/version_requirements.txt | 2 +- build/pkgs/sagemath_categories/version_requirements.txt | 2 +- build/pkgs/sagemath_coxeter3/version_requirements.txt | 2 +- build/pkgs/sagemath_environment/version_requirements.txt | 2 +- build/pkgs/sagemath_mcqd/version_requirements.txt | 2 +- build/pkgs/sagemath_meataxe/version_requirements.txt | 2 +- build/pkgs/sagemath_objects/version_requirements.txt | 2 +- build/pkgs/sagemath_repl/version_requirements.txt | 2 +- build/pkgs/sagemath_sirocco/version_requirements.txt | 2 +- build/pkgs/sagemath_tdlib/version_requirements.txt | 2 +- pkgs/sage-conf/VERSION.txt | 2 +- pkgs/sage-conf_conda/VERSION.txt | 2 +- pkgs/sage-conf_pypi/VERSION.txt | 2 +- pkgs/sage-docbuild/VERSION.txt | 2 +- pkgs/sage-setup/VERSION.txt | 2 +- pkgs/sage-sws2rst/VERSION.txt | 2 +- pkgs/sagemath-bliss/VERSION.txt | 2 +- pkgs/sagemath-categories/VERSION.txt | 2 +- pkgs/sagemath-coxeter3/VERSION.txt | 2 +- pkgs/sagemath-environment/VERSION.txt | 2 +- pkgs/sagemath-mcqd/VERSION.txt | 2 +- pkgs/sagemath-meataxe/VERSION.txt | 2 +- pkgs/sagemath-objects/VERSION.txt | 2 +- pkgs/sagemath-repl/VERSION.txt | 2 +- pkgs/sagemath-sirocco/VERSION.txt | 2 +- pkgs/sagemath-tdlib/VERSION.txt | 2 +- src/VERSION.txt | 2 +- src/bin/sage-version.sh | 6 +++--- src/sage/version.py | 6 +++--- 39 files changed, 45 insertions(+), 45 deletions(-) diff --git a/.upstream.d/20-github.com-sagemath-sage-releases b/.upstream.d/20-github.com-sagemath-sage-releases index db4fdc08b38..399ee84dbd6 100644 --- a/.upstream.d/20-github.com-sagemath-sage-releases +++ b/.upstream.d/20-github.com-sagemath-sage-releases @@ -1,5 +1,5 @@ # Upstream packages as uploaded as GitHub release assets. # This file is automatically updated by the sage-update-version script. +https://github.com/sagemath/sage/releases/download/10.5/ https://github.com/sagemath/sage/releases/download/10.4/ https://github.com/sagemath/sage/releases/download/10.3/ -https://github.com/sagemath/sage/releases/download/10.2/ diff --git a/CITATION.cff b/CITATION.cff index e2b61cecf34..a84a202863d 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -4,8 +4,8 @@ title: SageMath abstract: SageMath is a free open-source mathematics software system. authors: - name: "The SageMath Developers" -version: 10.4 +version: 10.5.beta0 doi: 10.5281/zenodo.8042260 -date-released: 2024-07-19 +date-released: 2024-07-24 repository-code: "https://github.com/sagemath/sage" url: "https://www.sagemath.org/" diff --git a/VERSION.txt b/VERSION.txt index c6c45714210..391171f6ff9 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -SageMath version 10.4, Release Date: 2024-07-19 +SageMath version 10.5.beta0, Release Date: 2024-07-24 diff --git a/build/pkgs/configure/checksums.ini b/build/pkgs/configure/checksums.ini index 24b944d6a6c..4195c94ea50 100644 --- a/build/pkgs/configure/checksums.ini +++ b/build/pkgs/configure/checksums.ini @@ -1,3 +1,3 @@ tarball=configure-VERSION.tar.gz -sha1=7b7c79fc15432a1cc3d08c2f2fc610391970a727 -sha256=732dc8f003f58952b811302a48ad743dab86208d236df8843fd6b904c46aa474 +sha1=442147504b01035e9cc36d5a726c454fbebd05ba +sha256=ebd714e56d0435cfd0e8faf94d3e9fc27c91a3d7dfeb42efb5b796fda1567a64 diff --git a/build/pkgs/configure/package-version.txt b/build/pkgs/configure/package-version.txt index b2696d2b691..19a7b2187c8 100644 --- a/build/pkgs/configure/package-version.txt +++ b/build/pkgs/configure/package-version.txt @@ -1 +1 @@ -46d6ebe05583047bc9cc89904af075483e78fdae +238f042e65932c80a81e6841c10e6abcf8ed6e4f diff --git a/build/pkgs/sage_conf/version_requirements.txt b/build/pkgs/sage_conf/version_requirements.txt index 375190d9093..684b5222f75 100644 --- a/build/pkgs/sage_conf/version_requirements.txt +++ b/build/pkgs/sage_conf/version_requirements.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sage-conf ~= 10.4 +sage-conf ~= 10.5b0 diff --git a/build/pkgs/sage_docbuild/version_requirements.txt b/build/pkgs/sage_docbuild/version_requirements.txt index f164da252b8..e66e6b35b92 100644 --- a/build/pkgs/sage_docbuild/version_requirements.txt +++ b/build/pkgs/sage_docbuild/version_requirements.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sage-docbuild ~= 10.4 +sage-docbuild ~= 10.5b0 diff --git a/build/pkgs/sage_setup/version_requirements.txt b/build/pkgs/sage_setup/version_requirements.txt index fb7d287156f..bec5c5030a3 100644 --- a/build/pkgs/sage_setup/version_requirements.txt +++ b/build/pkgs/sage_setup/version_requirements.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sage-setup ~= 10.4 +sage-setup ~= 10.5b0 diff --git a/build/pkgs/sage_sws2rst/version_requirements.txt b/build/pkgs/sage_sws2rst/version_requirements.txt index 7abf79506b7..06e7a0ce057 100644 --- a/build/pkgs/sage_sws2rst/version_requirements.txt +++ b/build/pkgs/sage_sws2rst/version_requirements.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sage-sws2rst ~= 10.4 +sage-sws2rst ~= 10.5b0 diff --git a/build/pkgs/sagelib/version_requirements.txt b/build/pkgs/sagelib/version_requirements.txt index 9c4941c493e..4cfbbb2470b 100644 --- a/build/pkgs/sagelib/version_requirements.txt +++ b/build/pkgs/sagelib/version_requirements.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-standard ~= 10.4 +sagemath-standard ~= 10.5b0 diff --git a/build/pkgs/sagemath_bliss/version_requirements.txt b/build/pkgs/sagemath_bliss/version_requirements.txt index 2565f173029..dcf87c4700a 100644 --- a/build/pkgs/sagemath_bliss/version_requirements.txt +++ b/build/pkgs/sagemath_bliss/version_requirements.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-bliss ~= 10.4 +sagemath-bliss ~= 10.5b0 diff --git a/build/pkgs/sagemath_categories/version_requirements.txt b/build/pkgs/sagemath_categories/version_requirements.txt index 6b7585e509b..9128985c7ec 100644 --- a/build/pkgs/sagemath_categories/version_requirements.txt +++ b/build/pkgs/sagemath_categories/version_requirements.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-categories ~= 10.4 +sagemath-categories ~= 10.5b0 diff --git a/build/pkgs/sagemath_coxeter3/version_requirements.txt b/build/pkgs/sagemath_coxeter3/version_requirements.txt index 2b240b0cc98..571fbc0ac85 100644 --- a/build/pkgs/sagemath_coxeter3/version_requirements.txt +++ b/build/pkgs/sagemath_coxeter3/version_requirements.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-coxeter3 ~= 10.4 +sagemath-coxeter3 ~= 10.5b0 diff --git a/build/pkgs/sagemath_environment/version_requirements.txt b/build/pkgs/sagemath_environment/version_requirements.txt index acb1b9f636a..0c20cbedbf4 100644 --- a/build/pkgs/sagemath_environment/version_requirements.txt +++ b/build/pkgs/sagemath_environment/version_requirements.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-environment ~= 10.4 +sagemath-environment ~= 10.5b0 diff --git a/build/pkgs/sagemath_mcqd/version_requirements.txt b/build/pkgs/sagemath_mcqd/version_requirements.txt index 7284fdc97cc..8fd3ed6eb1e 100644 --- a/build/pkgs/sagemath_mcqd/version_requirements.txt +++ b/build/pkgs/sagemath_mcqd/version_requirements.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-mcqd ~= 10.4 +sagemath-mcqd ~= 10.5b0 diff --git a/build/pkgs/sagemath_meataxe/version_requirements.txt b/build/pkgs/sagemath_meataxe/version_requirements.txt index e41cf324ac5..cdc817a0902 100644 --- a/build/pkgs/sagemath_meataxe/version_requirements.txt +++ b/build/pkgs/sagemath_meataxe/version_requirements.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-meataxe ~= 10.4 +sagemath-meataxe ~= 10.5b0 diff --git a/build/pkgs/sagemath_objects/version_requirements.txt b/build/pkgs/sagemath_objects/version_requirements.txt index 19b35bd4a07..497e590c641 100644 --- a/build/pkgs/sagemath_objects/version_requirements.txt +++ b/build/pkgs/sagemath_objects/version_requirements.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-objects ~= 10.4 +sagemath-objects ~= 10.5b0 diff --git a/build/pkgs/sagemath_repl/version_requirements.txt b/build/pkgs/sagemath_repl/version_requirements.txt index b5cec69b83a..182219e2881 100644 --- a/build/pkgs/sagemath_repl/version_requirements.txt +++ b/build/pkgs/sagemath_repl/version_requirements.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-repl ~= 10.4 +sagemath-repl ~= 10.5b0 diff --git a/build/pkgs/sagemath_sirocco/version_requirements.txt b/build/pkgs/sagemath_sirocco/version_requirements.txt index 60fde833e03..e44083a8820 100644 --- a/build/pkgs/sagemath_sirocco/version_requirements.txt +++ b/build/pkgs/sagemath_sirocco/version_requirements.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-sirocco ~= 10.4 +sagemath-sirocco ~= 10.5b0 diff --git a/build/pkgs/sagemath_tdlib/version_requirements.txt b/build/pkgs/sagemath_tdlib/version_requirements.txt index 6461411de40..0b19dcdcfae 100644 --- a/build/pkgs/sagemath_tdlib/version_requirements.txt +++ b/build/pkgs/sagemath_tdlib/version_requirements.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-tdlib ~= 10.4 +sagemath-tdlib ~= 10.5b0 diff --git a/pkgs/sage-conf/VERSION.txt b/pkgs/sage-conf/VERSION.txt index 1be519cd2ec..87985263d9f 100644 --- a/pkgs/sage-conf/VERSION.txt +++ b/pkgs/sage-conf/VERSION.txt @@ -1 +1 @@ -10.4 +10.5.beta0 diff --git a/pkgs/sage-conf_conda/VERSION.txt b/pkgs/sage-conf_conda/VERSION.txt index 1be519cd2ec..87985263d9f 100644 --- a/pkgs/sage-conf_conda/VERSION.txt +++ b/pkgs/sage-conf_conda/VERSION.txt @@ -1 +1 @@ -10.4 +10.5.beta0 diff --git a/pkgs/sage-conf_pypi/VERSION.txt b/pkgs/sage-conf_pypi/VERSION.txt index 1be519cd2ec..87985263d9f 100644 --- a/pkgs/sage-conf_pypi/VERSION.txt +++ b/pkgs/sage-conf_pypi/VERSION.txt @@ -1 +1 @@ -10.4 +10.5.beta0 diff --git a/pkgs/sage-docbuild/VERSION.txt b/pkgs/sage-docbuild/VERSION.txt index 1be519cd2ec..87985263d9f 100644 --- a/pkgs/sage-docbuild/VERSION.txt +++ b/pkgs/sage-docbuild/VERSION.txt @@ -1 +1 @@ -10.4 +10.5.beta0 diff --git a/pkgs/sage-setup/VERSION.txt b/pkgs/sage-setup/VERSION.txt index 1be519cd2ec..87985263d9f 100644 --- a/pkgs/sage-setup/VERSION.txt +++ b/pkgs/sage-setup/VERSION.txt @@ -1 +1 @@ -10.4 +10.5.beta0 diff --git a/pkgs/sage-sws2rst/VERSION.txt b/pkgs/sage-sws2rst/VERSION.txt index 1be519cd2ec..87985263d9f 100644 --- a/pkgs/sage-sws2rst/VERSION.txt +++ b/pkgs/sage-sws2rst/VERSION.txt @@ -1 +1 @@ -10.4 +10.5.beta0 diff --git a/pkgs/sagemath-bliss/VERSION.txt b/pkgs/sagemath-bliss/VERSION.txt index 1be519cd2ec..87985263d9f 100644 --- a/pkgs/sagemath-bliss/VERSION.txt +++ b/pkgs/sagemath-bliss/VERSION.txt @@ -1 +1 @@ -10.4 +10.5.beta0 diff --git a/pkgs/sagemath-categories/VERSION.txt b/pkgs/sagemath-categories/VERSION.txt index 1be519cd2ec..87985263d9f 100644 --- a/pkgs/sagemath-categories/VERSION.txt +++ b/pkgs/sagemath-categories/VERSION.txt @@ -1 +1 @@ -10.4 +10.5.beta0 diff --git a/pkgs/sagemath-coxeter3/VERSION.txt b/pkgs/sagemath-coxeter3/VERSION.txt index 1be519cd2ec..87985263d9f 100644 --- a/pkgs/sagemath-coxeter3/VERSION.txt +++ b/pkgs/sagemath-coxeter3/VERSION.txt @@ -1 +1 @@ -10.4 +10.5.beta0 diff --git a/pkgs/sagemath-environment/VERSION.txt b/pkgs/sagemath-environment/VERSION.txt index 1be519cd2ec..87985263d9f 100644 --- a/pkgs/sagemath-environment/VERSION.txt +++ b/pkgs/sagemath-environment/VERSION.txt @@ -1 +1 @@ -10.4 +10.5.beta0 diff --git a/pkgs/sagemath-mcqd/VERSION.txt b/pkgs/sagemath-mcqd/VERSION.txt index 1be519cd2ec..87985263d9f 100644 --- a/pkgs/sagemath-mcqd/VERSION.txt +++ b/pkgs/sagemath-mcqd/VERSION.txt @@ -1 +1 @@ -10.4 +10.5.beta0 diff --git a/pkgs/sagemath-meataxe/VERSION.txt b/pkgs/sagemath-meataxe/VERSION.txt index 1be519cd2ec..87985263d9f 100644 --- a/pkgs/sagemath-meataxe/VERSION.txt +++ b/pkgs/sagemath-meataxe/VERSION.txt @@ -1 +1 @@ -10.4 +10.5.beta0 diff --git a/pkgs/sagemath-objects/VERSION.txt b/pkgs/sagemath-objects/VERSION.txt index 1be519cd2ec..87985263d9f 100644 --- a/pkgs/sagemath-objects/VERSION.txt +++ b/pkgs/sagemath-objects/VERSION.txt @@ -1 +1 @@ -10.4 +10.5.beta0 diff --git a/pkgs/sagemath-repl/VERSION.txt b/pkgs/sagemath-repl/VERSION.txt index 1be519cd2ec..87985263d9f 100644 --- a/pkgs/sagemath-repl/VERSION.txt +++ b/pkgs/sagemath-repl/VERSION.txt @@ -1 +1 @@ -10.4 +10.5.beta0 diff --git a/pkgs/sagemath-sirocco/VERSION.txt b/pkgs/sagemath-sirocco/VERSION.txt index 1be519cd2ec..87985263d9f 100644 --- a/pkgs/sagemath-sirocco/VERSION.txt +++ b/pkgs/sagemath-sirocco/VERSION.txt @@ -1 +1 @@ -10.4 +10.5.beta0 diff --git a/pkgs/sagemath-tdlib/VERSION.txt b/pkgs/sagemath-tdlib/VERSION.txt index 1be519cd2ec..87985263d9f 100644 --- a/pkgs/sagemath-tdlib/VERSION.txt +++ b/pkgs/sagemath-tdlib/VERSION.txt @@ -1 +1 @@ -10.4 +10.5.beta0 diff --git a/src/VERSION.txt b/src/VERSION.txt index 1be519cd2ec..87985263d9f 100644 --- a/src/VERSION.txt +++ b/src/VERSION.txt @@ -1 +1 @@ -10.4 +10.5.beta0 diff --git a/src/bin/sage-version.sh b/src/bin/sage-version.sh index e306177e47a..6c2ddd89a72 100644 --- a/src/bin/sage-version.sh +++ b/src/bin/sage-version.sh @@ -4,6 +4,6 @@ # which stops "setup.py develop" from rewriting it as a Python file. : # This file is auto-generated by the sage-update-version script, do not edit! -SAGE_VERSION='10.4' -SAGE_RELEASE_DATE='2024-07-19' -SAGE_VERSION_BANNER='SageMath version 10.4, Release Date: 2024-07-19' +SAGE_VERSION='10.5.beta0' +SAGE_RELEASE_DATE='2024-07-24' +SAGE_VERSION_BANNER='SageMath version 10.5.beta0, Release Date: 2024-07-24' diff --git a/src/sage/version.py b/src/sage/version.py index 0dfb7ac9745..45a12a5d561 100644 --- a/src/sage/version.py +++ b/src/sage/version.py @@ -1,5 +1,5 @@ # Sage version information for Python scripts # This file is auto-generated by the sage-update-version script, do not edit! -version = '10.4' -date = '2024-07-19' -banner = 'SageMath version 10.4, Release Date: 2024-07-19' +version = '10.5.beta0' +date = '2024-07-24' +banner = 'SageMath version 10.5.beta0, Release Date: 2024-07-24'