From 1a171d26e83b9c00e9b6f9429db1b4a8c0d578dc Mon Sep 17 00:00:00 2001 From: Markus Wageringel Date: Mon, 31 Aug 2020 21:50:48 +0200 Subject: [PATCH 001/359] 30477: fix conflict between implicit multiplication and complex literals --- src/sage/repl/preparse.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/sage/repl/preparse.py b/src/sage/repl/preparse.py index 1206835df95..be64691e613 100644 --- a/src/sage/repl/preparse.py +++ b/src/sage/repl/preparse.py @@ -1481,6 +1481,13 @@ def implicit_mul(code, level=5): sage: implicit_mul('3λ') '3*λ' + + Check support for complex literals (:trac:`30477`):: + + sage: implicit_mul('2r-1JR') + '2r-1JR' + sage: implicit_mul('1E3 + 0.3E-3rj') + '1e3 + 0.3e-3rj' """ from keyword import iskeyword keywords_py2 = ['print', 'exec'] @@ -1502,8 +1509,8 @@ def re_no_keyword(pattern, code): no_mul_token = " '''_no_mult_token_''' " code = re.sub(r'\b0x', r'0%sx' % no_mul_token, code) # hex digits code = re.sub(r'( *)time ', r'\1time %s' % no_mul_token, code) # first word may be magic 'time' - code = re.sub(r'\b(\d+(?:\.\d+)?(?:e\d+)?)([rR]\b)', r'\1%s\2' % no_mul_token, code) # exclude such things as 10r - code = re.sub(r'\b(\d+(?:\.\d+)?)e([-\d])', r'\1%se%s\2' % (no_mul_token, no_mul_token), code) # exclude such things as 1e5 + code = re.sub(r'\b(\d+(?:\.\d+)?(?:e\d+)?)(rj?\b|j?r\b)', r'\1%s\2' % no_mul_token, code, flags=re.I) # exclude such things as 10r, 10rj, 10jr + code = re.sub(r'\b(\d+(?:\.\d+)?)e([-\d])', r'\1%se%s\2' % (no_mul_token, no_mul_token), code, flags=re.I) # exclude such things as 1e5 code = re_no_keyword(r'\b((?:\d+(?:\.\d+)?)|(?:%s[0-9eEpn]*\b)) *([^\W\d(]\w*)\b' % numeric_literal_prefix, code) if level >= 2: code = re.sub(r'(\%\(L\d+\))s', r'\1%ss%s' % (no_mul_token, no_mul_token), code) # literal strings From ac5350d40241e0b09547c5acc2784a9d05d6b535 Mon Sep 17 00:00:00 2001 From: EnderWannabe Date: Wed, 16 Jun 2021 16:59:02 -0400 Subject: [PATCH 002/359] 31994: initial commit, contains zero division error --- src/doc/en/reference/references/index.rst | 3 + .../arithmetic_dynamics/projective_ds.py | 55 ++++++++++++++++++- 2 files changed, 55 insertions(+), 3 deletions(-) diff --git a/src/doc/en/reference/references/index.rst b/src/doc/en/reference/references/index.rst index a5b4d54eeed..72ee62693ff 100644 --- a/src/doc/en/reference/references/index.rst +++ b/src/doc/en/reference/references/index.rst @@ -3037,6 +3037,9 @@ REFERENCES: .. [Hutz2015] \B. Hutz. Determination of all rational preperiodic points for morphisms of PN. Mathematics of Computation, 84:291 (2015), 289-308. +.. [Hutz2019] \B. Hutz. Multipliers and invariants of endomorphisms of projective + space in dimension greater than 1 + .. [Huy2005] \D. Huybrechts : *Complex Geometry*, Springer (Berlin) (2005). diff --git a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py index e61061c5622..757a6ca05cd 100644 --- a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py +++ b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py @@ -4359,7 +4359,7 @@ def multiplier_spectra(self, n, formal=False, type='point', use_algebraic_closur return multipliers - def sigma_invariants(self, n, formal=False, embedding=None, type='point'): + def sigma_invariants(self, n, formal=False, embedding=None, type='point', return_polynomial=False): r""" Computes the values of the elementary symmetric polynomials of the ``n`` multiplier spectra of this dynamical system. @@ -4392,6 +4392,9 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point'): variable `w`. Note that if `f` is a rational function, we clear denominators for `g`. + To calculate the full polynomial defining the sigma invariants, + we follow the algorithm outlined in section 4 of [Hutz2019]_. + INPUT: - ``n`` -- a positive integer, the period @@ -4409,6 +4412,12 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point'): or ``'cycle'`` depending on whether you compute with one multiplier per point or one per cycle + - ``return polynomial`` -- (default: ``False``) boolean; + ``True`` specifies returning the polynomial which generates + the sigma invariants, see [Hutz2019]_ for the full definition. + The polynomial is always a multivariate polynomial with variables + ``w`` and ``t``. + OUTPUT: a list of elements in the base ring EXAMPLES:: @@ -4513,13 +4522,53 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point'): dom = self.domain() if not is_ProjectiveSpace(dom): raise NotImplementedError("not implemented for subschemes") - if dom.dimension_relative() > 1: - raise NotImplementedError("only implemented for dimension 1") if not embedding is None: from sage.misc.superseded import deprecation deprecation(23333, "embedding keyword no longer used") if self.degree() <= 1: raise TypeError("must have degree at least 2") + if dom.dimension_relative() > 1 or return_polynomial: + from sage.calculus.functions import jacobian + d = self.degree() + N = dom.dimension_relative() + Fn = self.nth_iterate_map(n) + base_ring = self.base_ring() + X = Fn.periodic_points(1, minimal=False, return_scheme=True) + R = PolynomialRing(base_ring, 'v', N+N+3, order='lex') + var = list(R.gens()) + R2 = PolynomialRing(base_ring, var[:N] + var[-2:]) + newR = PolynomialRing(base_ring, 'w, t', 2, order='lex') + psi = R2.hom(N*[0]+list(newR.gens()), newR) + R_zero = {R.gen(N):1} + for j in range(N+1, N+N+1): + R_zero[R.gen(j)] = 0 + t = var.pop() + w = var.pop() + var = var[:N] + sigma_polynomial = 1 + for j in range(N,-1,-1): + Xa = X.affine_patch(j) + fa = Fn.dehomogenize(j) + Pa = fa.domain() + im = [R.gen(i) for i in range(j)] + (N-j)*[0] + phi = Pa.coordinate_ring().hom(im, R) + M = t*matrix.identity(R, N) + print(jacobian([phi(F.numerator())/phi(F.denominator()) for F in fa], var)) + g = (M-jacobian([phi(F.numerator())/phi(F.denominator()) for F in fa], var)).det() + L = [phi(h) for h in Xa.defining_polynomials()] + L += [w*g.denominator()-R.gen(N)*g.numerator() + sum(R.gen(j-1)*R.gen(N+j)*g.denominator() for j in range(1,N+1))] + I = R.ideal(L) + G = I.groebner_basis() + sigma_polynomial *= psi(G[-1].specialization(R_zero)) + if return_polynomial: + return sigma_polynomial + sigmas = [] + sigma_dictionary = dict([list(reversed(i)) for i in list(sigma_polynomial)]) + degree = sigma_polynomial.degree() + for i in range(degree, -1, -1): + for j in range(degree-j, -1, -1): + sigmas.append(sigma_dictionary.pop(w**i*t**j, 0)) + return sigmas if not type in ['point', 'cycle']: raise ValueError("type must be either point or cycle") From 18c12b3dbee056f527b83d4d72dd1016c457ec3a Mon Sep 17 00:00:00 2001 From: EnderWannabe Date: Fri, 18 Jun 2021 17:14:31 -0400 Subject: [PATCH 003/359] 31994: added chow algorithm, documentation, examples --- .../arithmetic_dynamics/projective_ds.py | 101 ++++++++++++++---- 1 file changed, 79 insertions(+), 22 deletions(-) diff --git a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py index 757a6ca05cd..a4e519f22b4 100644 --- a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py +++ b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py @@ -4359,7 +4359,8 @@ def multiplier_spectra(self, n, formal=False, type='point', use_algebraic_closur return multipliers - def sigma_invariants(self, n, formal=False, embedding=None, type='point', return_polynomial=False): + def sigma_invariants(self, n, formal=False, embedding=None, type='point', + return_polynomial=False, chow=False): r""" Computes the values of the elementary symmetric polynomials of the ``n`` multiplier spectra of this dynamical system. @@ -4418,7 +4419,14 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point', return The polynomial is always a multivariate polynomial with variables ``w`` and ``t``. - OUTPUT: a list of elements in the base ring + - ``chow`` -- (default: ``False``) boolean; ``True`` specifies + using the Chow algorithm from [Hutz2019]_ to compute the sigma + invariants. While slower, the Chow algorithm does not lose + information about multiplicities. Helpful when this map has + repeated multipliers or fixed points with high multiplicity. + + OUTPUT: a list of elements in the base ring, unless ``return_polynomial`` + is ``True``, in which case a polynomial in ``w`` and ``t`` is returned. EXAMPLES:: @@ -4431,6 +4439,20 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point', return -2622661107937102104196133701280271632423/549755813888, 338523204830161116503153209450763500631714178825448006778305/72057594037927936, 0] + :: + + sage: P. = ProjectiveSpace(QQ,1) + sage: f = DynamicalSystem_projective([x^2 + 2*y^2, y^2]) + sage: poly = f.sigma_invariants(1, return_polynomial=True); poly + w^3 - 3*w^2*t + 2*w^2 + 3*w*t^2 - 4*w*t + 8*w - t^3 + 2*t^2 - 8*t + + From the full polynomial, we can easily get the one variable polynomial whose coefficients + are symmetric functions in the multipliers:: + + sage: w, t = poly.variabls() + sage: poly.subs({w:0}) + -t^3 + 2*t^2 - 8*t + :: sage: set_verbose(None) @@ -4460,10 +4482,25 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point', return sage: P. = ProjectiveSpace(QQ, 2) sage: f = DynamicalSystem_projective([x^2, y^2, z^2]) - sage: f.sigma_invariants(1) - Traceback (most recent call last): - ... - NotImplementedError: only implemented for dimension 1 + sage: f.sigma_invariants(1, return_polynomial=True, chow=True) + w^7 - 7*w^6*t^2 + 10*w^6*t - 4*w^6 + 21*w^5*t^4 - 60*w^5*t^3 + 60*w^5*t^2 - + 24*w^5*t - 35*w^4*t^6 + 150*w^4*t^5 - 240*w^4*t^4 + 176*w^4*t^3 - 48*w^4*t^2 + + 35*w^3*t^8 - 200*w^3*t^7 + 440*w^3*t^6 - 464*w^3*t^5 + 224*w^3*t^4 - 32*w^3*t^3 + - 21*w^2*t^10 + 150*w^2*t^9 - 420*w^2*t^8 + 576*w^2*t^7 - 384*w^2*t^6 + 96*w^2*t^5 + + 7*w*t^12 - 60*w*t^11 + 204*w*t^10 - 344*w*t^9 + 288*w*t^8 - 96*w*t^7 - t^14 + + 10*t^13 - 40*t^12 + 80*t^11 - 80*t^10 + 32*t^9 + + :: + + sage: P. = ProjectiveSpace(QQ, 3) + sage: f = DynamicalSystem_projective([x^2, w^2, z^2, y^2]) + sage: f.sigma_invariants(1, return_polynomial=True) + w^6 - 6*w^5*t^3 + 2*w^5*t^2 + 8*w^5*t - 8*w^5 + 15*w^4*t^6 - 10*w^4*t^5 - + 44*w^4*t^4 + 48*w^4*t^3 + 16*w^4*t^2 - 32*w^4*t - 20*w^3*t^9 + 20*w^3*t^8 + + 96*w^3*t^7 - 120*w^3*t^6 - 96*w^3*t^5 + 160*w^3*t^4 + 15*w^2*t^12 - 20*w^2*t^11 + - 104*w^2*t^10 + 152*w^2*t^9 + 192*w^2*t^8 - 320*w^2*t^7 - 64*w^2*t^6 + 128*w^2*t^5 + - 6*w*t^15 + 10*w*t^14 + 56*w*t^13 - 96*w*t^12 - 160*w*t^11 + 288*w*t^10 + 128*w*t^9 + - 256*w*t^8 + t^18 - 2*t^17 - 12*t^16 + 24*t^15 + 48*t^14 - 96*t^13 - 64*t^12 + 128*t^11 :: @@ -4534,32 +4571,52 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point', return Fn = self.nth_iterate_map(n) base_ring = self.base_ring() X = Fn.periodic_points(1, minimal=False, return_scheme=True) - R = PolynomialRing(base_ring, 'v', N+N+3, order='lex') - var = list(R.gens()) - R2 = PolynomialRing(base_ring, var[:N] + var[-2:]) newR = PolynomialRing(base_ring, 'w, t', 2, order='lex') - psi = R2.hom(N*[0]+list(newR.gens()), newR) - R_zero = {R.gen(N):1} - for j in range(N+1, N+N+1): - R_zero[R.gen(j)] = 0 - t = var.pop() - w = var.pop() - var = var[:N] + if chow: + R = PolynomialRing(base_ring, 'v', N+N+3, order='lex') + var = list(R.gens()) + R2 = PolynomialRing(base_ring, var[:N] + var[-2:]) + psi = R2.hom(N*[0]+list(newR.gens()), newR) + R_zero = {R.gen(N):1} + for j in range(N+1, N+N+1): + R_zero[R.gen(j)] = 0 + t = var.pop() + w = var.pop() + var = var[:N] + else: + R = PolynomialRing(base_ring,'v', N+2, order='lex') + psi = R.hom(N*[0] + list(newR.gens()), newR) + var = list(R.gens()) + t = var.pop() + w = var.pop() sigma_polynomial = 1 for j in range(N,-1,-1): Xa = X.affine_patch(j) fa = Fn.dehomogenize(j) Pa = fa.domain() - im = [R.gen(i) for i in range(j)] + (N-j)*[0] - phi = Pa.coordinate_ring().hom(im, R) + Ra = Pa.coordinate_ring() + if chow: + im = [R.gen(i) for i in range(j)] + (N-j)*[0] + [R.gen(i) for i in range(N, R.ngens())] + else: + im = list(R.gens())[:j] + (N-j)*[0] + [R.gen(i) for i in range(N, R.ngens())] + phi = Ra.hom(Ra.gens(), R) M = t*matrix.identity(R, N) - print(jacobian([phi(F.numerator())/phi(F.denominator()) for F in fa], var)) g = (M-jacobian([phi(F.numerator())/phi(F.denominator()) for F in fa], var)).det() - L = [phi(h) for h in Xa.defining_polynomials()] - L += [w*g.denominator()-R.gen(N)*g.numerator() + sum(R.gen(j-1)*R.gen(N+j)*g.denominator() for j in range(1,N+1))] + g_prime = w*R(g.denominator())(im)-R(g.numerator())(im) + L = [phi(h)(im) for h in Xa.defining_polynomials()] + if chow: + L += [g_prime + sum(R.gen(j-1)*R.gen(N+j)*(R(g.denominator())(im)) for j in range(1,N+1))] + else: + L += [g_prime] I = R.ideal(L) G = I.groebner_basis() - sigma_polynomial *= psi(G[-1].specialization(R_zero)) + if chow: + poly = psi(G[-1].specialization(R_zero)) + if len(list(poly)) > 0: + poly *= poly.coefficients()[0].inverse_of_unit() + sigma_polynomial *= poly + else: + sigma_polynomial *= psi(G[-1]) if return_polynomial: return sigma_polynomial sigmas = [] From 8b3ea6a41e12b82eff6d2f1c6c5c5b5124c581bf Mon Sep 17 00:00:00 2001 From: EnderWannabe Date: Fri, 18 Jun 2021 17:17:47 -0400 Subject: [PATCH 004/359] 31994: added formal parameter --- 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 f1a980d1f7e..5fa3ba31b05 100644 --- a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py +++ b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py @@ -4737,7 +4737,7 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point', N = dom.dimension_relative() Fn = self.nth_iterate_map(n) base_ring = self.base_ring() - X = Fn.periodic_points(1, minimal=False, return_scheme=True) + X = Fn.periodic_points(1, minimal=False, formal=formal, return_scheme=True) newR = PolynomialRing(base_ring, 'w, t', 2, order='lex') if chow: R = PolynomialRing(base_ring, 'v', N+N+3, order='lex') From abedd5944595c822e30fe946ddbab35c182a9eaf Mon Sep 17 00:00:00 2001 From: Alexander Date: Mon, 21 Jun 2021 16:41:24 -0400 Subject: [PATCH 005/359] 31994: updated documentation and list return --- src/doc/en/reference/references/index.rst | 2 +- .../arithmetic_dynamics/projective_ds.py | 95 +++++++++++++++---- 2 files changed, 76 insertions(+), 21 deletions(-) diff --git a/src/doc/en/reference/references/index.rst b/src/doc/en/reference/references/index.rst index 3f2eb299094..11e7d27654c 100644 --- a/src/doc/en/reference/references/index.rst +++ b/src/doc/en/reference/references/index.rst @@ -3042,7 +3042,7 @@ REFERENCES: for morphisms of PN. Mathematics of Computation, 84:291 (2015), 289-308. .. [Hutz2019] \B. Hutz. Multipliers and invariants of endomorphisms of projective - space in dimension greater than 1 + space in dimension greater than 1, :arxiv:`1908.03184`, 2019. .. [Huy2005] \D. Huybrechts : *Complex Geometry*, Springer (Berlin) (2005). diff --git a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py index 5fa3ba31b05..43211194272 100644 --- a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py +++ b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py @@ -4595,30 +4595,70 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point', OUTPUT: a list of elements in the base ring, unless ``return_polynomial`` is ``True``, in which case a polynomial in ``w`` and ``t`` is returned. + If this map is defined over `\mathbb{P}^N`, where `N > 1`, then + the first element of the list is the degree of the polynomial in `w` and + the second element is the degree of the polynomial in `t`. The rest of the + list are the coefficients of `w` and `t`, in lexographical order with `w > t`. + EXAMPLES:: - sage: P. = ProjectiveSpace(QQ,1) - sage: f = DynamicalSystem_projective([512*x^5 - 378128*x^4*y + 76594292*x^3*y^2 - 4570550136*x^2*y^3 - 2630045017*x*y^4\ - + 28193217129*y^5, 512*y^5]) + sage: P. = ProjectiveSpace(QQ, 1) + sage: f = DynamicalSystem_projective([x^2 + x*y + y^2, y^2 + x*y]) sage: f.sigma_invariants(1) - [19575526074450617/1048576, -9078122048145044298567432325/2147483648, - -2622661114909099878224381377917540931367/1099511627776, - -2622661107937102104196133701280271632423/549755813888, - 338523204830161116503153209450763500631714178825448006778305/72057594037927936, 0] + [3, 3, 1] - :: + If ``return_polynomial`` is ``True``, then following [Hutz2019]_ + we return a two variable polynomial in `w` and `t`:: - sage: P. = ProjectiveSpace(QQ,1) + sage: P. = ProjectiveSpace(QQ, 1) sage: f = DynamicalSystem_projective([x^2 + 2*y^2, y^2]) sage: poly = f.sigma_invariants(1, return_polynomial=True); poly w^3 - 3*w^2*t + 2*w^2 + 3*w*t^2 - 4*w*t + 8*w - t^3 + 2*t^2 - 8*t - From the full polynomial, we can easily get the one variable polynomial whose coefficients - are symmetric functions in the multipliers:: + From the full polynomial, we can easily recover the one variable polynomial whose coefficients + are symmetric functions in the multipliers, up to sign:: + + sage: w, t = poly.variables() + sage: poly.specialization({w:0}).monic() + t^3 - 2*t^2 + 8*t + sage: f.sigma_invariants(1) + [2, 8, 0] + + For dynamical systems on `\mathbb{P}^N`, where `N > 1`, the full polynomial + is needed to distinguish the conjugacy class. We can, however, still return + a list in this case. Here, the first element of the list is the degree in `w` and + the second element is the degree in `t`. The rest of the list are the coefficients + of the polynomial, sorted in lexographical order with `w > t`:: + + sage: P. = ProjectiveSpace(QQ, 2) + sage: f = DynamicalSystem_projective([x^2, z^2, y^2]) + sage: f.sigma_invariants(1) + [3, 6, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, -3, -2, 4, 0, + 0, 3, 4, -8, -8, 0, -1, -2, 4, 8, 0, 0, 0] + + When calculating the sigma invariants for `\mathbb{P}^N`, with `N > 1`, + the default algorithm loses information about multiplicities. Note that + the following call to sigma invariants returns a degree 6 polynomial in `w`:: + + sage: P. = ProjectiveSpace(QQ, 2) + sage: f = DynamicalSystem_projective([x^2, y^2, z^2]) + sage: f.sigma_invariants(1, return_polynomial=True) + w^6 - 6*w^5*t^2 + 8*w^5*t - 4*w^5 + 15*w^4*t^4 - 40*w^4*t^3 + 40*w^4*t^2 - + 16*w^4*t - 20*w^3*t^6 + 80*w^3*t^5 - 120*w^3*t^4 + 80*w^3*t^3 - 16*w^3*t^2 + + 15*w^2*t^8 - 80*w^2*t^7 + 160*w^2*t^6 - 144*w^2*t^5 + 48*w^2*t^4 - 6*w*t^10 + + 40*w*t^9 - 100*w*t^8 + 112*w*t^7 - 48*w*t^6 + t^12 - 8*t^11 + 24*t^10 - + 32*t^9 + 16*t^8 - sage: w, t = poly.variabls() - sage: poly.subs({w:0}) - -t^3 + 2*t^2 - 8*t + Setting ``chow`` to ``True``, while much slower, accounts correctly for multiplicities. + Note that the following returns a degree 7 polynomial in `w`:: + + sage: f.sigma_invariants(1, return_polynomial=True, chow=True) + w^7 - 7*w^6*t^2 + 10*w^6*t - 4*w^6 + 21*w^5*t^4 - 60*w^5*t^3 + 60*w^5*t^2 - + 24*w^5*t - 35*w^4*t^6 + 150*w^4*t^5 - 240*w^4*t^4 + 176*w^4*t^3 - 48*w^4*t^2 + + 35*w^3*t^8 - 200*w^3*t^7 + 440*w^3*t^6 - 464*w^3*t^5 + 224*w^3*t^4 - + 32*w^3*t^3 - 21*w^2*t^10 + 150*w^2*t^9 - 420*w^2*t^8 + 576*w^2*t^7 - + 384*w^2*t^6 + 96*w^2*t^5 + 7*w*t^12 - 60*w*t^11 + 204*w*t^10 - 344*w*t^9 + + 288*w*t^8 - 96*w*t^7 - t^14 + 10*t^13 - 40*t^12 + 80*t^11 - 80*t^10 + 32*t^9 :: @@ -4681,10 +4721,14 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point', :: - sage: P. = ProjectiveSpace(QQ,1) - sage: f = DynamicalSystem_projective([x^2 + x*y + y^2, y^2 + x*y]) + sage: P. = ProjectiveSpace(QQ, 1) + sage: f = DynamicalSystem_projective([512*x^5 - 378128*x^4*y + 76594292*x^3*y^2 - 4570550136*x^2*y^3 - 2630045017*x*y^4\ + + 28193217129*y^5, 512*y^5]) sage: f.sigma_invariants(1) - [3, 3, 1] + [19575526074450617/1048576, -9078122048145044298567432325/2147483648, + -2622661114909099878224381377917540931367/1099511627776, + -2622661107937102104196133701280271632423/549755813888, + 338523204830161116503153209450763500631714178825448006778305/72057594037927936, 0] :: @@ -4719,6 +4763,15 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point', sage: f = DynamicalSystem_projective([x^2 + (t/(t^2+1))*y^2, y^2], P) sage: f.sigma_invariants(1) [2, 4*t/(t^2 + 1), 0] + + :: + + sage: R. = QQ[] + sage: N. = NumberField(w^2 + 1) + sage: P. = ProjectiveSpace(N, 2) + sage: f = DynamicalSystem_projective([x^2, y^2, z^2]) + sage: f.sigma_invariants(1) == f.change_ring(QQ).sigma_invariants(1) + True """ n = ZZ(n) if n < 1: @@ -4788,9 +4841,11 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point', return sigma_polynomial sigmas = [] sigma_dictionary = dict([list(reversed(i)) for i in list(sigma_polynomial)]) - degree = sigma_polynomial.degree() - for i in range(degree, -1, -1): - for j in range(degree-j, -1, -1): + degree_w, degree_t = sigma_polynomial.degrees() + w, t = sigma_polynomial.variables() + sigmas += [degree_w, degree_t] + for i in range(degree_w, -1, -1): + for j in range(degree_t, -1, -1): sigmas.append(sigma_dictionary.pop(w**i*t**j, 0)) return sigmas if not type in ['point', 'cycle']: From 1a5a601ce0791605d4535e38aac0757a737cca69 Mon Sep 17 00:00:00 2001 From: Alexander Date: Wed, 30 Jun 2021 14:01:51 -0400 Subject: [PATCH 006/359] 31994: removed duplicate example --- .../dynamics/arithmetic_dynamics/projective_ds.py | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py index 43211194272..9fab7208f9d 100644 --- a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py +++ b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py @@ -4685,18 +4685,6 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point', sage: f.sigma_invariants(2, type='point', formal=True) [0, 0] - :: - - sage: P. = ProjectiveSpace(QQ, 2) - sage: f = DynamicalSystem_projective([x^2, y^2, z^2]) - sage: f.sigma_invariants(1, return_polynomial=True, chow=True) - w^7 - 7*w^6*t^2 + 10*w^6*t - 4*w^6 + 21*w^5*t^4 - 60*w^5*t^3 + 60*w^5*t^2 - - 24*w^5*t - 35*w^4*t^6 + 150*w^4*t^5 - 240*w^4*t^4 + 176*w^4*t^3 - 48*w^4*t^2 - + 35*w^3*t^8 - 200*w^3*t^7 + 440*w^3*t^6 - 464*w^3*t^5 + 224*w^3*t^4 - 32*w^3*t^3 - - 21*w^2*t^10 + 150*w^2*t^9 - 420*w^2*t^8 + 576*w^2*t^7 - 384*w^2*t^6 + 96*w^2*t^5 - + 7*w*t^12 - 60*w*t^11 + 204*w*t^10 - 344*w*t^9 + 288*w*t^8 - 96*w*t^7 - t^14 + - 10*t^13 - 40*t^12 + 80*t^11 - 80*t^10 + 32*t^9 - :: sage: P. = ProjectiveSpace(QQ, 3) From 89a417d19a8402e51465167def9712505e088f58 Mon Sep 17 00:00:00 2001 From: bhutz Date: Tue, 6 Jul 2021 12:15:40 -0500 Subject: [PATCH 007/359] 31994 - added some comments to code --- .../arithmetic_dynamics/projective_ds.py | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py index 1e97b485cce..3389423177b 100644 --- a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py +++ b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py @@ -53,6 +53,7 @@ class initialization directly. # **************************************************************************** from sage.arith.misc import is_prime +from sage.calculus.functions import jacobian from sage.categories.fields import Fields from sage.categories.function_fields import FunctionFields from sage.categories.number_fields import NumberFields @@ -4635,6 +4636,8 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point', OUTPUT: a list of elements in the base ring, unless ``return_polynomial`` is ``True``, in which case a polynomial in ``w`` and ``t`` is returned. + The variable ``t`` is the variable of the characteristic + polynomials of the multipliers. If this map is defined over `\mathbb{P}^N`, where `N > 1`, then the first element of the list is the degree of the polynomial in `w` and @@ -4814,7 +4817,6 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point', if self.degree() <= 1: raise TypeError("must have degree at least 2") if dom.dimension_relative() > 1 or return_polynomial: - from sage.calculus.functions import jacobian d = self.degree() N = dom.dimension_relative() Fn = self.nth_iterate_map(n) @@ -4822,10 +4824,13 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point', X = Fn.periodic_points(1, minimal=False, formal=formal, return_scheme=True) newR = PolynomialRing(base_ring, 'w, t', 2, order='lex') if chow: + # create full polynomial ring R = PolynomialRing(base_ring, 'v', N+N+3, order='lex') var = list(R.gens()) + # create polynomial ring for result R2 = PolynomialRing(base_ring, var[:N] + var[-2:]) psi = R2.hom(N*[0]+list(newR.gens()), newR) + # create substition to set extra variables to 0 R_zero = {R.gen(N):1} for j in range(N+1, N+N+1): R_zero[R.gen(j)] = 0 @@ -4839,26 +4844,37 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point', t = var.pop() w = var.pop() sigma_polynomial = 1 + # go through each affine patch to avoid repeating periodic points + # setting the visited coordiantes to 0 as we go for j in range(N,-1,-1): Xa = X.affine_patch(j) fa = Fn.dehomogenize(j) Pa = fa.domain() Ra = Pa.coordinate_ring() + # create the images for the Hom to the ring we will do the elimination over + # with done affine patch coordinates as 0 if chow: im = [R.gen(i) for i in range(j)] + (N-j)*[0] + [R.gen(i) for i in range(N, R.ngens())] else: im = list(R.gens())[:j] + (N-j)*[0] + [R.gen(i) for i in range(N, R.ngens())] phi = Ra.hom(Ra.gens(), R) + # create polymomial that evaluates to the characteristic polynomial M = t*matrix.identity(R, N) g = (M-jacobian([phi(F.numerator())/phi(F.denominator()) for F in fa], var)).det() + # create the terms of the sigma invariants prod(w-lambda) g_prime = w*R(g.denominator())(im)-R(g.numerator())(im) + # move the defining polynomials to the polynomial ring L = [phi(h)(im) for h in Xa.defining_polynomials()] + # add the appropriate final polynomial to compute the sigma invariant polynomial + # via a Poisson product in elimination if chow: L += [g_prime + sum(R.gen(j-1)*R.gen(N+j)*(R(g.denominator())(im)) for j in range(1,N+1))] else: L += [g_prime] I = R.ideal(L) + # since R is lex ordering, this is an elimination step G = I.groebner_basis() + # the polynomial we need is the one just in w and t if chow: poly = psi(G[-1].specialization(R_zero)) if len(list(poly)) > 0: @@ -4868,6 +4884,8 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point', sigma_polynomial *= psi(G[-1]) if return_polynomial: return sigma_polynomial + # if we are returing a numerical list, read off the coefficients + # in order of degree adjusting sign appropriately sigmas = [] sigma_dictionary = dict([list(reversed(i)) for i in list(sigma_polynomial)]) degree_w, degree_t = sigma_polynomial.degrees() From 2be2b66071cf5744d87ee178158748ddb71a9073 Mon Sep 17 00:00:00 2001 From: Alexander Date: Tue, 6 Jul 2021 18:31:29 -0400 Subject: [PATCH 008/359] 31994: added flattening --- .../arithmetic_dynamics/projective_ds.py | 72 ++++++++++++++----- 1 file changed, 54 insertions(+), 18 deletions(-) diff --git a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py index 34f97366328..dc3f0934826 100644 --- a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py +++ b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py @@ -4634,7 +4634,8 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point', - ``type`` -- (default: ``'point'``) string; either ``'point'`` or ``'cycle'`` depending on whether you compute with one - multiplier per point or one per cycle + multiplier per point or one per cycle. Not implemented for + dimension greater than 1. - ``return polynomial`` -- (default: ``False``) boolean; ``True`` specifies returning the polynomial which generates @@ -4691,8 +4692,8 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point', sage: P. = ProjectiveSpace(QQ, 2) sage: f = DynamicalSystem_projective([x^2, z^2, y^2]) sage: f.sigma_invariants(1) - [3, 6, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, -3, -2, 4, 0, - 0, 3, 4, -8, -8, 0, -1, -2, 4, 8, 0, 0, 0] + [3, 6, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 3, -2, -4, 0, 0, 3, -4, -8, 8, 0, + 1, -2, -4, 8, 0, 0, 0] When calculating the sigma invariants for `\mathbb{P}^N`, with `N > 1`, the default algorithm loses information about multiplicities. Note that @@ -4830,33 +4831,61 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point', deprecation(23333, "embedding keyword no longer used") if self.degree() <= 1: raise TypeError("must have degree at least 2") + if not type in ['point', 'cycle']: + raise ValueError("type must be either point or cycle") if dom.dimension_relative() > 1 or return_polynomial: + if type == 'cycle': + raise NotImplementedError('cycle not implemented for dimension greater than 1') + base_ring = self.base_ring() + if isinstance(base_ring, FractionField_1poly_field) or is_FunctionField(base_ring): + raise NotImplementedError('Sigma invariants not implemented for fraction function fields.' + + 'Clear denominators and use the polynomial ring instead.') d = self.degree() N = dom.dimension_relative() Fn = self.nth_iterate_map(n) - base_ring = self.base_ring() - X = Fn.periodic_points(1, minimal=False, formal=formal, return_scheme=True) - newR = PolynomialRing(base_ring, 'w, t', 2, order='lex') + if not base_ring.is_field(): + F = FractionField(base_ring) + Fn.normalize_coordinates() + X = Fn.change_ring(base_ring).periodic_points(1, minimal=False, formal=formal, return_scheme=True) + X = X.change_ring(F) + else: + F = base_ring + X = Fn.periodic_points(1, minimal=False, formal=formal, return_scheme=True) + newR_unordered = PolynomialRing(base_ring, 'w, t', 2) + newR = newR_unordered.change_ring(order='lex') if chow: # create full polynomial ring - R = PolynomialRing(base_ring, 'v', N+N+3, order='lex') + R_unordered = PolynomialRing(base_ring, 'v', 2*N+3) + R = R_unordered.change_ring(order='lex') var = list(R.gens()) # create polynomial ring for result R2 = PolynomialRing(base_ring, var[:N] + var[-2:]) psi = R2.hom(N*[0]+list(newR.gens()), newR) # create substition to set extra variables to 0 R_zero = {R.gen(N):1} - for j in range(N+1, N+N+1): + for j in range(N+1, 2*N+1): R_zero[R.gen(j)] = 0 t = var.pop() w = var.pop() var = var[:N] else: - R = PolynomialRing(base_ring,'v', N+2, order='lex') - psi = R.hom(N*[0] + list(newR.gens()), newR) + R_unordered = PolynomialRing(base_ring, 'v', N+2) + R = R_unordered.change_ring(order='lex') + psi = R_unordered.hom(N*[0] + list(newR_unordered.gens()), newR_unordered) var = list(R.gens()) t = var.pop() w = var.pop() + if is_FractionField(F): + if is_PolynomialRing(F.ring()) or is_MPolynomialRing(F.ring()): + flat_phi = FlatteningMorphism(R) + flatR_unordered = flat_phi.codomain() + Id = matrix.identity(len(flatR_unordered.gens()) - len(F.gens())) + Id2 = matrix.identity(len(F.gens())) + from sage.matrix.special import block_matrix + b = block_matrix([[ZZ(0), Id],[Id2, ZZ(0)]]) + from sage.rings.polynomial.term_order import TermOrder + flatR = flatR_unordered.change_ring(order=TermOrder(b)) + unflat_phi = UnflatteningMorphism(flatR_unordered, R) sigma_polynomial = 1 # go through each affine patch to avoid repeating periodic points # setting the visited coordiantes to 0 as we go @@ -4871,7 +4900,7 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point', im = [R.gen(i) for i in range(j)] + (N-j)*[0] + [R.gen(i) for i in range(N, R.ngens())] else: im = list(R.gens())[:j] + (N-j)*[0] + [R.gen(i) for i in range(N, R.ngens())] - phi = Ra.hom(Ra.gens(), R) + phi = Ra.hom(R.gens()[0:len(Ra.gens())]) # create polymomial that evaluates to the characteristic polynomial M = t*matrix.identity(R, N) g = (M-jacobian([phi(F.numerator())/phi(F.denominator()) for F in fa], var)).det() @@ -4886,16 +4915,25 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point', else: L += [g_prime] I = R.ideal(L) + if is_FractionField(F): + I = flatR.ideal([flat_phi(poly) for poly in I.gens()]) # since R is lex ordering, this is an elimination step G = I.groebner_basis() # the polynomial we need is the one just in w and t if chow: - poly = psi(G[-1].specialization(R_zero)) + if is_FractionField(F): + unflattened = unflat_phi(G[-1]) + else: + unflattened = G[-1] + poly = psi(unflattened.specialization(R_zero)) if len(list(poly)) > 0: poly *= poly.coefficients()[0].inverse_of_unit() sigma_polynomial *= poly else: - sigma_polynomial *= psi(G[-1]) + if is_FractionField(F): + sigma_polynomial *= psi(unflat_phi(flatR_unordered(G[-1]))) + else: + sigma_polynomial *= psi(flatR_unordered(G[-1])) if return_polynomial: return sigma_polynomial # if we are returing a numerical list, read off the coefficients @@ -4905,12 +4943,10 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point', degree_w, degree_t = sigma_polynomial.degrees() w, t = sigma_polynomial.variables() sigmas += [degree_w, degree_t] - for i in range(degree_w, -1, -1): - for j in range(degree_t, -1, -1): - sigmas.append(sigma_dictionary.pop(w**i*t**j, 0)) + for i in range(degree_w+1): + for j in range(degree_t+1): + sigmas.append((-1)**(i+j)*sigma_dictionary.pop(w**(degree_w - i)*t**(degree_t - j), 0)) return sigmas - if not type in ['point', 'cycle']: - raise ValueError("type must be either point or cycle") base_ring = dom.base_ring() if is_FractionField(base_ring): From a410756fc54563375e4b641ad1e90ccda70a1a74 Mon Sep 17 00:00:00 2001 From: Alexander Date: Tue, 6 Jul 2021 18:43:07 -0400 Subject: [PATCH 009/359] 31994: added support for fraction fields of polynomial rings --- .../dynamics/arithmetic_dynamics/projective_ds.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py index ee6e70b90b6..827bf50ec1d 100644 --- a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py +++ b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py @@ -4841,9 +4841,6 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point', if type == 'cycle': raise NotImplementedError('cycle not implemented for dimension greater than 1') base_ring = self.base_ring() - if isinstance(base_ring, FractionField_1poly_field) or is_FunctionField(base_ring): - raise NotImplementedError('Sigma invariants not implemented for fraction function fields.' - + 'Clear denominators and use the polynomial ring instead.') d = self.degree() N = dom.dimension_relative() Fn = self.nth_iterate_map(n) @@ -4854,7 +4851,14 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point', X = X.change_ring(F) else: F = base_ring - X = Fn.periodic_points(1, minimal=False, formal=formal, return_scheme=True) + if is_FractionField(base_ring): + if is_MPolynomialRing(base_ring.ring()) or is_PolynomialRing(base_ring.ring()): + Fn.normalize_coordinates() + Fn_ring = Fn.change_ring(base_ring.ring()) + X = Fn_ring.periodic_points(1, minimal=False, formal=formal, return_scheme=True) + X = X.change_ring(F) + else: + X = Fn.periodic_points(1, minimal=False, formal=formal, return_scheme=True) newR_unordered = PolynomialRing(base_ring, 'w, t', 2) newR = newR_unordered.change_ring(order='lex') if chow: From 97c33ffeb9fb050c63dc705d236343cda69967fc Mon Sep 17 00:00:00 2001 From: Alexander Date: Wed, 7 Jul 2021 12:28:33 -0400 Subject: [PATCH 010/359] 31994: added examples, simpler code for polynomial rings --- .../arithmetic_dynamics/projective_ds.py | 69 ++++++++++--------- 1 file changed, 38 insertions(+), 31 deletions(-) diff --git a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py index 827bf50ec1d..1f17c04cfd6 100644 --- a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py +++ b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py @@ -4781,6 +4781,14 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point', -2622661107937102104196133701280271632423/549755813888, 338523204830161116503153209450763500631714178825448006778305/72057594037927936, 0] + :: + + sage: P. = ProjectiveSpace(GF(5), 2) + sage: f = DynamicalSystem([x^2, y^2, z^2]) + sage: f.sigma_invariants(1, return_polynomial=True) + w^6 - w^5*t^2 - 2*w^5*t + w^5 - w^4*t - w^3*t^2 + w^2*t^5 - + 2*w^2*t^4 - w*t^10 + 2*w*t^7 + 2*w*t^6 + t^12 + 2*t^11 - t^10 - 2*t^9 + t^8 + :: sage: R. = QQ[] @@ -4793,6 +4801,24 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point', sage: f.sigma_invariants(2, formal=True, type='cycle') [4*c + 4] + :: + + sage: R. = QQ[] + sage: P. = ProjectiveSpace(R, 1) + sage: f = DynamicalSystem([x^2 + c*y^2, y^2]) + sage: f.sigma_invariants(1, return_polynomial=True) + w^3 + (-3)*w^2*t + 2*w^2 + 3*w*t^2 + (-4)*w*t + 4*c*w - t^3 + 2*t^2 + (-4*c)*t + sage: f.sigma_invariants(2, formal=True, return_polynomial=True) + w^2 + (-2)*w*t + (8*c + 8)*w + t^2 + (-8*c - 8)*t + 16*c^2 + 32*c + 16 + + :: + + sage: R. = QQ[] + sage: P. = ProjectiveSpace(R, 2) + sage: f = DynamicalSystem([x^2 + c*z^2, y^2 + d*z^2, z^2]) + sage: len(dict(f.sigma_invariants(1, return_polynomial=True))) + 51 + doubled fixed point:: sage: P. = ProjectiveSpace(QQ, 1) @@ -4847,7 +4873,7 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point', if not base_ring.is_field(): F = FractionField(base_ring) Fn.normalize_coordinates() - X = Fn.change_ring(base_ring).periodic_points(1, minimal=False, formal=formal, return_scheme=True) + X = Fn.periodic_points(1, minimal=False, formal=formal, return_scheme=True) X = X.change_ring(F) else: F = base_ring @@ -4859,15 +4885,15 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point', X = X.change_ring(F) else: X = Fn.periodic_points(1, minimal=False, formal=formal, return_scheme=True) - newR_unordered = PolynomialRing(base_ring, 'w, t', 2) - newR = newR_unordered.change_ring(order='lex') + newR = PolynomialRing(F, 'w, t', 2, order='lex') + if not base_ring.is_field(): + ringR = PolynomialRing(base_ring, 'w, t', 2, order='lex') if chow: # create full polynomial ring - R_unordered = PolynomialRing(base_ring, 'v', 2*N+3) - R = R_unordered.change_ring(order='lex') + R = PolynomialRing(F, 'v', 2*N+3, order='lex') var = list(R.gens()) # create polynomial ring for result - R2 = PolynomialRing(base_ring, var[:N] + var[-2:]) + R2 = PolynomialRing(F, var[:N] + var[-2:]) psi = R2.hom(N*[0]+list(newR.gens()), newR) # create substition to set extra variables to 0 R_zero = {R.gen(N):1} @@ -4877,23 +4903,11 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point', w = var.pop() var = var[:N] else: - R_unordered = PolynomialRing(base_ring, 'v', N+2) - R = R_unordered.change_ring(order='lex') - psi = R_unordered.hom(N*[0] + list(newR_unordered.gens()), newR_unordered) + R = PolynomialRing(F, 'v', N+2, order='lex') + psi = R.hom(N*[0] + list(newR.gens()), newR) var = list(R.gens()) t = var.pop() w = var.pop() - if is_FractionField(F): - if is_PolynomialRing(F.ring()) or is_MPolynomialRing(F.ring()): - flat_phi = FlatteningMorphism(R) - flatR_unordered = flat_phi.codomain() - Id = matrix.identity(len(flatR_unordered.gens()) - len(F.gens())) - Id2 = matrix.identity(len(F.gens())) - from sage.matrix.special import block_matrix - b = block_matrix([[ZZ(0), Id],[Id2, ZZ(0)]]) - from sage.rings.polynomial.term_order import TermOrder - flatR = flatR_unordered.change_ring(order=TermOrder(b)) - unflat_phi = UnflatteningMorphism(flatR_unordered, R) sigma_polynomial = 1 # go through each affine patch to avoid repeating periodic points # setting the visited coordiantes to 0 as we go @@ -4923,25 +4937,18 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point', else: L += [g_prime] I = R.ideal(L) - if is_FractionField(F): - I = flatR.ideal([flat_phi(poly) for poly in I.gens()]) # since R is lex ordering, this is an elimination step G = I.groebner_basis() # the polynomial we need is the one just in w and t if chow: - if is_FractionField(F): - unflattened = unflat_phi(G[-1]) - else: - unflattened = G[-1] - poly = psi(unflattened.specialization(R_zero)) + poly = psi(G[-1].specialization(R_zero)) if len(list(poly)) > 0: poly *= poly.coefficients()[0].inverse_of_unit() sigma_polynomial *= poly else: - if is_FractionField(F): - sigma_polynomial *= psi(unflat_phi(flatR_unordered(G[-1]))) - else: - sigma_polynomial *= psi(flatR_unordered(G[-1])) + sigma_polynomial *= psi(G[-1]) + if not base_ring.is_field(): + sigma_polynomial = ringR(sigma_polynomial) if return_polynomial: return sigma_polynomial # if we are returing a numerical list, read off the coefficients From d220330d79ea8b1a7e206e31e49989f1b189f03f Mon Sep 17 00:00:00 2001 From: Alexander Date: Wed, 7 Jul 2021 12:33:47 -0400 Subject: [PATCH 011/359] 31994: fixed n > 1 --- .../arithmetic_dynamics/projective_ds.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py index 1f17c04cfd6..913d715529a 100644 --- a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py +++ b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py @@ -4808,7 +4808,7 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point', sage: f = DynamicalSystem([x^2 + c*y^2, y^2]) sage: f.sigma_invariants(1, return_polynomial=True) w^3 + (-3)*w^2*t + 2*w^2 + 3*w*t^2 + (-4)*w*t + 4*c*w - t^3 + 2*t^2 + (-4*c)*t - sage: f.sigma_invariants(2, formal=True, return_polynomial=True) + sage: f.sigma_invariants(2, chow=True, formal=True, return_polynomial=True) w^2 + (-2)*w*t + (8*c + 8)*w + t^2 + (-8*c - 8)*t + 16*c^2 + 32*c + 16 :: @@ -4869,22 +4869,23 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point', base_ring = self.base_ring() d = self.degree() N = dom.dimension_relative() - Fn = self.nth_iterate_map(n) + f = copy(self) + Fn = f.nth_iterate_map(n) if not base_ring.is_field(): F = FractionField(base_ring) - Fn.normalize_coordinates() - X = Fn.periodic_points(1, minimal=False, formal=formal, return_scheme=True) + f.normalize_coordinates() + X = f.periodic_points(n, minimal=False, formal=formal, return_scheme=True) X = X.change_ring(F) else: F = base_ring if is_FractionField(base_ring): if is_MPolynomialRing(base_ring.ring()) or is_PolynomialRing(base_ring.ring()): - Fn.normalize_coordinates() - Fn_ring = Fn.change_ring(base_ring.ring()) - X = Fn_ring.periodic_points(1, minimal=False, formal=formal, return_scheme=True) + f.normalize_coordinates() + f_ring = f.change_ring(base_ring.ring()) + X = f_ring.periodic_points(n, minimal=False, formal=formal, return_scheme=True) X = X.change_ring(F) else: - X = Fn.periodic_points(1, minimal=False, formal=formal, return_scheme=True) + X = f.periodic_points(n, minimal=False, formal=formal, return_scheme=True) newR = PolynomialRing(F, 'w, t', 2, order='lex') if not base_ring.is_field(): ringR = PolynomialRing(base_ring, 'w, t', 2, order='lex') From c5277f2c0647b3254381ec312ec6c0ec65c85be8 Mon Sep 17 00:00:00 2001 From: Alexander Date: Wed, 7 Jul 2021 13:29:40 -0400 Subject: [PATCH 012/359] 32155: initial commit with method and documentation --- .../schemes/projective/projective_space.py | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/src/sage/schemes/projective/projective_space.py b/src/sage/schemes/projective/projective_space.py index 5327aebe5b7..1d5988e2470 100644 --- a/src/sage/schemes/projective/projective_space.py +++ b/src/sage/schemes/projective/projective_space.py @@ -79,6 +79,7 @@ # http://www.gnu.org/licenses/ # **************************************************************************** +from typing import Type from sage.arith.all import gcd, binomial, srange from sage.rings.all import (PolynomialRing, Integer, @@ -1300,6 +1301,80 @@ def veronese_embedding(self, d, CS=None, order='lex'): monomials.reverse() # order the monomials greatest to least via the given monomial order return Hom(self, CS)(monomials) + def is_linearly_independent(self, points): + r""" + Return whether the set of points is linearly independent. + + INPUT: + + - ``points`` -- a list points of this projective space. + + OUTPUT: + + - ``True`` if ``points`` is linearly independent, ``False`` otherwise. + + EXAMPLES:: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: points = [P((1, 0)), P((1, 1)), P((2, 1))] + sage: P.is_linearly_independent(points) + True + + :: + + sage: P. = ProjectiveSpace(ZZ, 2) + sage: points = [P((1, 0, 1)), P((1, 2, 1)), P((1, 3, 4))] + sage: P.is_linearly_independent(points) + True + + :: + + sage: P. = ProjectiveSpace(GF(5), 2) + sage: points = [P((1, 0, 1)), P((1, 2, 1)), P((1, 3, 4)), P((0, 0 ,1))] + sage: P.is_linearly_independent(points) + True + + :: + + sage: R. = QQ[] + sage: P. = ProjectiveSpace(R, 2) + sage: points = [P((c, 0, 1)), P((0, c, 1)), P((1, 0, 4)), P((0, 0 ,1))] + sage: P.is_linearly_independent(points) + False + + :: + + sage: R. = QQ[] + sage: P. = ProjectiveSpace(FractionField(R), 2) + sage: points = [P((c, 0, 1)), P((0, c, 1)), P((1, 3, 4)), P((0, 0 ,1))] + sage: P.is_linearly_independent(points) + True + + :: + + sage: K. = CyclotomicField(3) + sage: P. = ProjectiveSpace(K, 2) + sage: points = [P((k, k^2, 1)), P((0, k, 1)), P((1, 0, 4)), P((0, 0 ,1))] + sage: P.is_linearly_independent(points) + True + """ + if not isinstance(points, list): + raise TypeError("points must be a list") + if any(not isinstance(point, SchemeMorphism_point_projective_ring) for point in points): + raise TypeError("points must be a list of projective points") + if any(x.codomain() != self for x in points): + raise ValueError("points not in this projective space") + M = matrix([list(t) for t in points]) + N = self.dimension_relative() + if len(points) < N+1: + if M.rank() == len(points): + return True + return False + elif len(points) < N+3: + if any(l == 0 for l in M.minors(N+1)): + return False + return True + return False class ProjectiveSpace_field(ProjectiveSpace_ring): def _point_homset(self, *args, **kwds): From 6897aa406532c104b39ab4b6655f61df58834b4c Mon Sep 17 00:00:00 2001 From: Alexander Date: Thu, 8 Jul 2021 13:07:01 -0400 Subject: [PATCH 013/359] 32155: updated parameter --- .../schemes/projective/projective_space.py | 32 +++++++++++-------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/src/sage/schemes/projective/projective_space.py b/src/sage/schemes/projective/projective_space.py index 1d5988e2470..2a2d64511ad 100644 --- a/src/sage/schemes/projective/projective_space.py +++ b/src/sage/schemes/projective/projective_space.py @@ -1301,13 +1301,19 @@ def veronese_embedding(self, d, CS=None, order='lex'): monomials.reverse() # order the monomials greatest to least via the given monomial order return Hom(self, CS)(monomials) - def is_linearly_independent(self, points): + def is_linearly_independent(self, points, n=None): r""" Return whether the set of points is linearly independent. + Alternatively, specify ``n`` to check if every subset of + size ``n`` is linearly independent. + INPUT: - - ``points`` -- a list points of this projective space. + - ``points`` -- a list of points in this projective space. + + - ``n`` -- (Optional) An integer. Specifies the size of the subsets to + check for linear independence. OUTPUT: @@ -1316,7 +1322,7 @@ def is_linearly_independent(self, points): EXAMPLES:: sage: P. = ProjectiveSpace(QQ, 1) - sage: points = [P((1, 0)), P((1, 1)), P((2, 1))] + sage: points = [P((1, 0)), P((1, 1))] sage: P.is_linearly_independent(points) True @@ -1331,7 +1337,7 @@ def is_linearly_independent(self, points): sage: P. = ProjectiveSpace(GF(5), 2) sage: points = [P((1, 0, 1)), P((1, 2, 1)), P((1, 3, 4)), P((0, 0 ,1))] - sage: P.is_linearly_independent(points) + sage: P.is_linearly_independent(points, 3) True :: @@ -1339,7 +1345,7 @@ def is_linearly_independent(self, points): sage: R. = QQ[] sage: P. = ProjectiveSpace(R, 2) sage: points = [P((c, 0, 1)), P((0, c, 1)), P((1, 0, 4)), P((0, 0 ,1))] - sage: P.is_linearly_independent(points) + sage: P.is_linearly_independent(points, 3) False :: @@ -1347,7 +1353,7 @@ def is_linearly_independent(self, points): sage: R. = QQ[] sage: P. = ProjectiveSpace(FractionField(R), 2) sage: points = [P((c, 0, 1)), P((0, c, 1)), P((1, 3, 4)), P((0, 0 ,1))] - sage: P.is_linearly_independent(points) + sage: P.is_linearly_independent(points, 3) True :: @@ -1355,7 +1361,7 @@ def is_linearly_independent(self, points): sage: K. = CyclotomicField(3) sage: P. = ProjectiveSpace(K, 2) sage: points = [P((k, k^2, 1)), P((0, k, 1)), P((1, 0, 4)), P((0, 0 ,1))] - sage: P.is_linearly_independent(points) + sage: P.is_linearly_independent(points, 3) True """ if not isinstance(points, list): @@ -1364,17 +1370,17 @@ def is_linearly_independent(self, points): raise TypeError("points must be a list of projective points") if any(x.codomain() != self for x in points): raise ValueError("points not in this projective space") + if not n is None: + n = Integer(n) M = matrix([list(t) for t in points]) N = self.dimension_relative() - if len(points) < N+1: + if len(points) < n or n == None: if M.rank() == len(points): return True return False - elif len(points) < N+3: - if any(l == 0 for l in M.minors(N+1)): - return False - return True - return False + if any(l == 0 for l in M.minors(n)): + return False + return True class ProjectiveSpace_field(ProjectiveSpace_ring): def _point_homset(self, *args, **kwds): From a5b8913dcf63a1ebabef0994452b16473dc66231 Mon Sep 17 00:00:00 2001 From: EnderWannabe Date: Thu, 8 Jul 2021 14:13:41 -0400 Subject: [PATCH 014/359] 32155: fixed check for independence --- .../schemes/projective/projective_space.py | 28 +++++++++++-------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/src/sage/schemes/projective/projective_space.py b/src/sage/schemes/projective/projective_space.py index 2a2d64511ad..3ffada5e995 100644 --- a/src/sage/schemes/projective/projective_space.py +++ b/src/sage/schemes/projective/projective_space.py @@ -107,6 +107,7 @@ 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 @@ -1337,7 +1338,7 @@ def is_linearly_independent(self, points, n=None): sage: P. = ProjectiveSpace(GF(5), 2) sage: points = [P((1, 0, 1)), P((1, 2, 1)), P((1, 3, 4)), P((0, 0 ,1))] - sage: P.is_linearly_independent(points, 3) + sage: P.is_linearly_independent(points, 2) True :: @@ -1370,17 +1371,22 @@ def is_linearly_independent(self, points, n=None): raise TypeError("points must be a list of projective points") if any(x.codomain() != self for x in points): raise ValueError("points not in this projective space") - if not n is None: - n = Integer(n) - M = matrix([list(t) for t in points]) + if n is None: + M = matrix([list(t) for t in points]) + return M.rank() == len(points) + n = Integer(n) N = self.dimension_relative() - if len(points) < n or n == None: - if M.rank() == len(points): - return True - return False - if any(l == 0 for l in M.minors(n)): - return False - return True + all_subsets = Subsets(range(len(points)), n) + linearly_independent = True + for subset in all_subsets: + point_list = [] + for index in subset: + point_list.append(list(points[index])) + M = matrix(point_list) + if M.rank() != n: + linearly_independent = False + break + return linearly_independent class ProjectiveSpace_field(ProjectiveSpace_ring): def _point_homset(self, *args, **kwds): From 533213c9d6924ed009053b752e189652c055af9b Mon Sep 17 00:00:00 2001 From: EnderWannabe Date: Thu, 8 Jul 2021 14:39:09 -0400 Subject: [PATCH 015/359] 32155: added check on n --- src/sage/schemes/projective/projective_space.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/sage/schemes/projective/projective_space.py b/src/sage/schemes/projective/projective_space.py index 3ffada5e995..70e8f31ad6b 100644 --- a/src/sage/schemes/projective/projective_space.py +++ b/src/sage/schemes/projective/projective_space.py @@ -1313,8 +1313,9 @@ def is_linearly_independent(self, points, n=None): - ``points`` -- a list of points in this projective space. - - ``n`` -- (Optional) An integer. Specifies the size of the subsets to - check for linear independence. + - ``n`` -- (Optional) A positive integer less than or equal to the length + of ``points``. Specifies the size of the subsets to check for + linear independence. OUTPUT: @@ -1364,6 +1365,15 @@ def is_linearly_independent(self, points, n=None): sage: points = [P((k, k^2, 1)), P((0, k, 1)), P((1, 0, 4)), P((0, 0 ,1))] sage: P.is_linearly_independent(points, 3) True + + TESTS:: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: points = [P(1, 0), P(1, 1), P(2, 1)] + sage: P.is_linearly_independent(points, 5) + Traceback (most recent call last): + ... + ValueError: n must be a non negative integer not greater than the length of points """ if not isinstance(points, list): raise TypeError("points must be a list") @@ -1375,7 +1385,8 @@ def is_linearly_independent(self, points, n=None): M = matrix([list(t) for t in points]) return M.rank() == len(points) n = Integer(n) - N = self.dimension_relative() + if n < 1 or n > len(points): + raise ValueError('n must be a non negative integer not greater than the length of points') all_subsets = Subsets(range(len(points)), n) linearly_independent = True for subset in all_subsets: From 008d6db1a72761b7bb6f5164410685e3b5582a4d Mon Sep 17 00:00:00 2001 From: Alexander Date: Fri, 9 Jul 2021 15:37:03 -0400 Subject: [PATCH 016/359] 31994: added deformation --- .../arithmetic_dynamics/projective_ds.py | 202 +++++++++++------- 1 file changed, 122 insertions(+), 80 deletions(-) diff --git a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py index 3ca1814764a..c0d54ca16e4 100644 --- a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py +++ b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py @@ -4727,7 +4727,7 @@ def multiplier_spectra(self, n, formal=False, type='point', use_algebraic_closur return multipliers def sigma_invariants(self, n, formal=False, embedding=None, type='point', - return_polynomial=False, chow=False): + return_polynomial=False, chow=False, deform=False, check=True): r""" Computes the values of the elementary symmetric polynomials of the ``n`` multiplier spectra of this dynamical system. @@ -4790,8 +4790,26 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point', - ``chow`` -- (default: ``False``) boolean; ``True`` specifies using the Chow algorithm from [Hutz2019]_ to compute the sigma invariants. While slower, the Chow algorithm does not lose - information about multiplicities. Helpful when this map has - repeated multipliers or fixed points with high multiplicity. + information about multiplicities of the multipliers. In order + to accurately compute the sigma polynomial when there is a + repeated multiplier, ``chow`` must be ``True``. + + - ``deform`` -- (default: ``False``) boolean; ``True`` specifies + first deforming the map so that all periodic points are distinct + and then calculating the sigma invariants. In order to accurately + calculate the sigma polynomial when there is a periodic point with + multiplicity, ``deform`` must be ``True``. + + - ``check`` -- (default: ``True``) boolean; when ``True`` the degree of + the sigma polynomial is checked against the expected degree. This is + done as the sigma polynomial may drop degree if multiplicites of periodic + points or multipliers are not correctly accounted for using ``chow`` or + ``deform``. + + .. WARNING:: + + Setting ``check`` to ``False`` can lead to mathematically incorrect + answers. OUTPUT: a list of elements in the base ring, unless ``return_polynomial`` is ``True``, in which case a polynomial in ``w`` and ``t`` is returned. @@ -4799,9 +4817,7 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point', polynomials of the multipliers. If this map is defined over `\mathbb{P}^N`, where `N > 1`, then - the first element of the list is the degree of the polynomial in `w` and - the second element is the degree of the polynomial in `t`. The rest of the - list are the coefficients of `w` and `t`, in lexographical order with `w > t`. + the list is the coefficients of `w` and `t`, in lexographical order with `w > t`. EXAMPLES:: @@ -5011,85 +5027,112 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point', N = dom.dimension_relative() f = copy(self) Fn = f.nth_iterate_map(n) - if not base_ring.is_field(): - F = FractionField(base_ring) - f.normalize_coordinates() - X = f.periodic_points(n, minimal=False, formal=formal, return_scheme=True) - X = X.change_ring(F) + if deform: + # we need a model with all affine periodic points + new_f = f.affine_preperiodic_model(0, n) + new_f.normalize_coordinates() + # we now deform by a parameter t + T = base_ring['k'] + k = T.gens()[0] + Pt = ProjectiveSpace(N, R=T, names = [str(i) for i in CR.gens()]) + deformed_polys = [poly + k*Pt.gens()[-1]**d for poly in new_f.defining_polynomials()[:-1]] + deformed_polys += [new_f.defining_polynomials()[-1]] + f_deformed = DynamicalSystem(deformed_polys) + sigma_poly = sigma(f_deformed, n, chow=chow, deform=False, return_polynomial=True) + sigma_polynomial = sigma_poly.specialization({k:0}) + # we fix the ordering of the parent polynomial ring + new_parent = sigma_polynomial.parent().change_ring(order='lex') + sigma_polynomial = new_parent(sigma_polynomial) + sigma_polynomial *= sigma_polynomial.coefficients()[0].inverse_of_unit() else: - F = base_ring - if is_FractionField(base_ring): - if is_MPolynomialRing(base_ring.ring()) or is_PolynomialRing(base_ring.ring()): - f.normalize_coordinates() - f_ring = f.change_ring(base_ring.ring()) - X = f_ring.periodic_points(n, minimal=False, formal=formal, return_scheme=True) - X = X.change_ring(F) - else: + if not base_ring.is_field(): + F = FractionField(base_ring) + f.normalize_coordinates() X = f.periodic_points(n, minimal=False, formal=formal, return_scheme=True) - newR = PolynomialRing(F, 'w, t', 2, order='lex') - if not base_ring.is_field(): - ringR = PolynomialRing(base_ring, 'w, t', 2, order='lex') - if chow: - # create full polynomial ring - R = PolynomialRing(F, 'v', 2*N+3, order='lex') - var = list(R.gens()) - # create polynomial ring for result - R2 = PolynomialRing(F, var[:N] + var[-2:]) - psi = R2.hom(N*[0]+list(newR.gens()), newR) - # create substition to set extra variables to 0 - R_zero = {R.gen(N):1} - for j in range(N+1, 2*N+1): - R_zero[R.gen(j)] = 0 - t = var.pop() - w = var.pop() - var = var[:N] - else: - R = PolynomialRing(F, 'v', N+2, order='lex') - psi = R.hom(N*[0] + list(newR.gens()), newR) - var = list(R.gens()) - t = var.pop() - w = var.pop() - sigma_polynomial = 1 - # go through each affine patch to avoid repeating periodic points - # setting the visited coordiantes to 0 as we go - for j in range(N,-1,-1): - Xa = X.affine_patch(j) - fa = Fn.dehomogenize(j) - Pa = fa.domain() - Ra = Pa.coordinate_ring() - # create the images for the Hom to the ring we will do the elimination over - # with done affine patch coordinates as 0 - if chow: - im = [R.gen(i) for i in range(j)] + (N-j)*[0] + [R.gen(i) for i in range(N, R.ngens())] + X = X.change_ring(F) else: - im = list(R.gens())[:j] + (N-j)*[0] + [R.gen(i) for i in range(N, R.ngens())] - phi = Ra.hom(R.gens()[0:len(Ra.gens())]) - # create polymomial that evaluates to the characteristic polynomial - M = t*matrix.identity(R, N) - g = (M-jacobian([phi(F.numerator())/phi(F.denominator()) for F in fa], var)).det() - # create the terms of the sigma invariants prod(w-lambda) - g_prime = w*R(g.denominator())(im)-R(g.numerator())(im) - # move the defining polynomials to the polynomial ring - L = [phi(h)(im) for h in Xa.defining_polynomials()] - # add the appropriate final polynomial to compute the sigma invariant polynomial - # via a Poisson product in elimination + F = base_ring + if is_FractionField(base_ring): + if is_MPolynomialRing(base_ring.ring()) or is_PolynomialRing(base_ring.ring()): + f.normalize_coordinates() + f_ring = f.change_ring(base_ring.ring()) + X = f_ring.periodic_points(n, minimal=False, formal=formal, return_scheme=True) + X = X.change_ring(F) + else: + X = f.periodic_points(n, minimal=False, formal=formal, return_scheme=True) + newR = PolynomialRing(F, 'w, t', 2, order='lex') + if not base_ring.is_field(): + ringR = PolynomialRing(base_ring, 'w, t', 2, order='lex') if chow: - L += [g_prime + sum(R.gen(j-1)*R.gen(N+j)*(R(g.denominator())(im)) for j in range(1,N+1))] + # create full polynomial ring + R = PolynomialRing(F, 'v', 2*N+3, order='lex') + var = list(R.gens()) + # create polynomial ring for result + R2 = PolynomialRing(F, var[:N] + var[-2:]) + psi = R2.hom(N*[0]+list(newR.gens()), newR) + # create substition to set extra variables to 0 + R_zero = {R.gen(N):1} + for j in range(N+1, 2*N+1): + R_zero[R.gen(j)] = 0 + t = var.pop() + w = var.pop() + var = var[:N] else: - L += [g_prime] - I = R.ideal(L) - # since R is lex ordering, this is an elimination step - G = I.groebner_basis() - # the polynomial we need is the one just in w and t - if chow: - poly = psi(G[-1].specialization(R_zero)) - if len(list(poly)) > 0: - poly *= poly.coefficients()[0].inverse_of_unit() + R = PolynomialRing(F, 'v', N+2, order='lex') + psi = R.hom(N*[0] + list(newR.gens()), newR) + var = list(R.gens()) + t = var.pop() + w = var.pop() + sigma_polynomial = 1 + # go through each affine patch to avoid repeating periodic points + # setting the visited coordiantes to 0 as we go + for j in range(N,-1,-1): + Xa = X.affine_patch(j) + fa = Fn.dehomogenize(j) + Pa = fa.domain() + Ra = Pa.coordinate_ring() + # create the images for the Hom to the ring we will do the elimination over + # with done affine patch coordinates as 0 + if chow: + im = [R.gen(i) for i in range(j)] + (N-j)*[0] + [R.gen(i) for i in range(N, R.ngens())] + else: + im = list(R.gens())[:j] + (N-j)*[0] + [R.gen(i) for i in range(N, R.ngens())] + phi = Ra.hom(R.gens()[0:len(Ra.gens())]) + # create polymomial that evaluates to the characteristic polynomial + M = t*matrix.identity(R, N) + g = (M-jacobian([phi(F.numerator())/phi(F.denominator()) for F in fa], var)).det() + # create the terms of the sigma invariants prod(w-lambda) + g_prime = w*R(g.denominator())(im)-R(g.numerator())(im) + # move the defining polynomials to the polynomial ring + L = [phi(h)(im) for h in Xa.defining_polynomials()] + # add the appropriate final polynomial to compute the sigma invariant polynomial + # via a Poisson product in elimination + if chow: + L += [g_prime + sum(R.gen(j-1)*R.gen(N+j)*(R(g.denominator())(im)) for j in range(1,N+1))] + else: + L += [g_prime] + I = R.ideal(L) + # since R is lex ordering, this is an elimination step + G = I.groebner_basis() + # the polynomial we need is the one just in w and t + if chow: + poly = psi(G[-1].specialization(R_zero)) + if len(list(poly)) > 0: + poly *= poly.coefficients()[0].inverse_of_unit() + else: + poly = psi(G[-1]) + if not base_ring.is_field(): + denom = lcm([coeff[0].denominator() for coeff in poly]) + poly *= denom sigma_polynomial *= poly - else: - sigma_polynomial *= psi(G[-1]) - if not base_ring.is_field(): - sigma_polynomial = ringR(sigma_polynomial) + if not base_ring.is_field(): + sigma_polynomial = ringR(sigma_polynomial) + if check: + degree_w = sigma_polynomial.degrees()[0] + expected_degree = sum(d**(n*i) for i in range(N+1)) + if degree_w != expected_degree: + raise ValueError('sigma polynomial dropped degree, as multiplicities were not accounted for correctly.'+ + ' try setting chow=True or deform=True') if return_polynomial: return sigma_polynomial # if we are returing a numerical list, read off the coefficients @@ -5098,7 +5141,6 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point', sigma_dictionary = dict([list(reversed(i)) for i in list(sigma_polynomial)]) degree_w, degree_t = sigma_polynomial.degrees() w, t = sigma_polynomial.variables() - sigmas += [degree_w, degree_t] for i in range(degree_w+1): for j in range(degree_t+1): sigmas.append((-1)**(i+j)*sigma_dictionary.pop(w**(degree_w - i)*t**(degree_t - j), 0)) From fc12a328b8853299227173c7e5de4801ae1ebeae Mon Sep 17 00:00:00 2001 From: Alexander Date: Fri, 9 Jul 2021 16:40:49 -0400 Subject: [PATCH 017/359] 31994: fixed tests --- .../arithmetic_dynamics/projective_ds.py | 54 +++++++++---------- 1 file changed, 25 insertions(+), 29 deletions(-) diff --git a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py index 86c1ac2b596..cbcac881a21 100644 --- a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py +++ b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py @@ -4830,15 +4830,14 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point', For dynamical systems on `\mathbb{P}^N`, where `N > 1`, the full polynomial is needed to distinguish the conjugacy class. We can, however, still return - a list in this case. Here, the first element of the list is the degree in `w` and - the second element is the degree in `t`. The rest of the list are the coefficients - of the polynomial, sorted in lexographical order with `w > t`:: + a list in this case:: sage: P. = ProjectiveSpace(QQ, 2) sage: f = DynamicalSystem_projective([x^2, z^2, y^2]) - sage: f.sigma_invariants(1) - [3, 6, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 3, -2, -4, 0, 0, 3, -4, -8, 8, 0, - 1, -2, -4, 8, 0, 0, 0] + sage: f.sigma_invariants(1, chow=True) + [1, 7, -6, -12, 21, -36, -60, 72, 48, 35, -90, -120, 352, 96, -288, -64, 35, -120, -120, 688, -96, + -1056, 320, 384, 0, 21, -90, -60, 672, -384, -1440, 1344, 768, -768, 0, 0, 7, -36, -12, 328, -336, + -864, 1472, 384, -1536, 512, 0, 0, 0, 1, -6, 0, 64, -96, -192, 512, 0, -768, 512, 0, 0, 0, 0, 0] When calculating the sigma invariants for `\mathbb{P}^N`, with `N > 1`, the default algorithm loses information about multiplicities. Note that @@ -4846,7 +4845,7 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point', sage: P. = ProjectiveSpace(QQ, 2) sage: f = DynamicalSystem_projective([x^2, y^2, z^2]) - sage: f.sigma_invariants(1, return_polynomial=True) + sage: f.sigma_invariants(1, return_polynomial=True, check=False) w^6 - 6*w^5*t^2 + 8*w^5*t - 4*w^5 + 15*w^4*t^4 - 40*w^4*t^3 + 40*w^4*t^2 - 16*w^4*t - 20*w^3*t^6 + 80*w^3*t^5 - 120*w^3*t^4 + 80*w^3*t^3 - 16*w^3*t^2 + 15*w^2*t^8 - 80*w^2*t^7 + 160*w^2*t^6 - 144*w^2*t^5 + 48*w^2*t^4 - 6*w*t^10 + @@ -4889,18 +4888,6 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point', sage: f.sigma_invariants(2, type='point', formal=True) [0, 0] - :: - - sage: P. = ProjectiveSpace(QQ, 3) - sage: f = DynamicalSystem_projective([x^2, w^2, z^2, y^2]) - sage: f.sigma_invariants(1, return_polynomial=True) - w^6 - 6*w^5*t^3 + 2*w^5*t^2 + 8*w^5*t - 8*w^5 + 15*w^4*t^6 - 10*w^4*t^5 - - 44*w^4*t^4 + 48*w^4*t^3 + 16*w^4*t^2 - 32*w^4*t - 20*w^3*t^9 + 20*w^3*t^8 + - 96*w^3*t^7 - 120*w^3*t^6 - 96*w^3*t^5 + 160*w^3*t^4 + 15*w^2*t^12 - 20*w^2*t^11 - - 104*w^2*t^10 + 152*w^2*t^9 + 192*w^2*t^8 - 320*w^2*t^7 - 64*w^2*t^6 + 128*w^2*t^5 - - 6*w*t^15 + 10*w*t^14 + 56*w*t^13 - 96*w*t^12 - 160*w*t^11 + 288*w*t^10 + 128*w*t^9 - - 256*w*t^8 + t^18 - 2*t^17 - 12*t^16 + 24*t^15 + 48*t^14 - 96*t^13 - 64*t^12 + 128*t^11 - :: sage: K. = QuadraticField(3) @@ -4926,9 +4913,10 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point', sage: P. = ProjectiveSpace(GF(5), 2) sage: f = DynamicalSystem([x^2, y^2, z^2]) - sage: f.sigma_invariants(1, return_polynomial=True) - w^6 - w^5*t^2 - 2*w^5*t + w^5 - w^4*t - w^3*t^2 + w^2*t^5 - - 2*w^2*t^4 - w*t^10 + 2*w*t^7 + 2*w*t^6 + t^12 + 2*t^11 - t^10 - 2*t^9 + t^8 + sage: f.sigma_invariants(1, chow=True, return_polynomial=True) + w^7 - 2*w^6*t^2 + w^6 + w^5*t^4 + w^5*t + w^4*t^3 + 2*w^4*t^2 + w^3*t^5 - + w^3*t^4 - 2*w^3*t^3 - w^2*t^10 + w^2*t^7 + w^2*t^6 + w^2*t^5 + 2*w*t^12 - + w*t^10 + w*t^9 - 2*w*t^8 - w*t^7 - t^14 + 2*t^9 :: @@ -4960,6 +4948,13 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point', sage: len(dict(f.sigma_invariants(1, return_polynomial=True))) 51 + :: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: f = DynamicalSystem([x^2 + 3*y^2, x*y]) + sage: f.sigma_invariants(1, deform = True, return_polynomial=True) + w^3 - 3*w^2*t + 3*w^2 + 3*w*t^2 - 6*w*t + 3*w - t^3 + 3*t^2 - 3*t + 1 + doubled fixed point:: sage: P. = ProjectiveSpace(QQ, 1) @@ -4988,7 +4983,7 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point', sage: N. = NumberField(w^2 + 1) sage: P. = ProjectiveSpace(N, 2) sage: f = DynamicalSystem_projective([x^2, y^2, z^2]) - sage: f.sigma_invariants(1) == f.change_ring(QQ).sigma_invariants(1) + sage: #f.sigma_invariants(1, chow=True) == f.change_ring(QQ).sigma_invariants(1, chow=True) True """ n = ZZ(n) @@ -5012,6 +5007,7 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point', N = dom.dimension_relative() f = copy(self) Fn = f.nth_iterate_map(n) + CR = f.codomain().ambient_space().coordinate_ring() if deform: # we need a model with all affine periodic points new_f = f.affine_preperiodic_model(0, n) @@ -5023,7 +5019,7 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point', deformed_polys = [poly + k*Pt.gens()[-1]**d for poly in new_f.defining_polynomials()[:-1]] deformed_polys += [new_f.defining_polynomials()[-1]] f_deformed = DynamicalSystem(deformed_polys) - sigma_poly = sigma(f_deformed, n, chow=chow, deform=False, return_polynomial=True) + sigma_poly = f_deformed.sigma_invariants(n, chow=chow, deform=False, return_polynomial=True, check=False) sigma_polynomial = sigma_poly.specialization({k:0}) # we fix the ordering of the parent polynomial ring new_parent = sigma_polynomial.parent().change_ring(order='lex') @@ -5112,7 +5108,7 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point', sigma_polynomial *= poly if not base_ring.is_field(): sigma_polynomial = ringR(sigma_polynomial) - if check: + if check and not formal: degree_w = sigma_polynomial.degrees()[0] expected_degree = sum(d**(n*i) for i in range(N+1)) if degree_w != expected_degree: @@ -5124,11 +5120,11 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point', # in order of degree adjusting sign appropriately sigmas = [] sigma_dictionary = dict([list(reversed(i)) for i in list(sigma_polynomial)]) - degree_w, degree_t = sigma_polynomial.degrees() + degree_w = sigma_polynomial.degrees()[0] w, t = sigma_polynomial.variables() - for i in range(degree_w+1): - for j in range(degree_t+1): - sigmas.append((-1)**(i+j)*sigma_dictionary.pop(w**(degree_w - i)*t**(degree_t - j), 0)) + for i in range(degree_w + 1): + for j in range(2*i, -1, -1): + sigmas.append((-1)**(i+j)*sigma_dictionary.pop(w**(degree_w - i)*t**(j), 0)) return sigmas base_ring = dom.base_ring() From 7f113c7e0e7d031e351ff5d39aea8985d356ae85 Mon Sep 17 00:00:00 2001 From: Alexander Date: Mon, 12 Jul 2021 15:23:44 -0400 Subject: [PATCH 018/359] first commit with code and docs --- .../endPN_automorphism_group.py | 483 +++++++++++++++++- .../arithmetic_dynamics/projective_ds.py | 159 ++---- 2 files changed, 535 insertions(+), 107 deletions(-) diff --git a/src/sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py b/src/sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py index d46c8601b25..5bdc8c53bcc 100644 --- a/src/sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py +++ b/src/sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py @@ -8,6 +8,8 @@ Xander Faber, Michelle Manes, and Bianca Viray [FMV]_. - Joao de Faria, Ben Hutz, Bianca Thompson (11-2013): adaptation for inclusion in Sage + +- Alexander Galarraga (7-2021): Added helper functions for conjugating set """ #***************************************************************************** @@ -19,10 +21,10 @@ # http://www.gnu.org/licenses/ #***************************************************************************** -from copy import copy +from copy import copy, deepcopy from sage.combinat.subset import Subsets from sage.functions.all import sqrt -from itertools import permutations, combinations +from itertools import permutations, combinations, product from sage.matrix.constructor import matrix from sage.structure.element import is_Matrix from sage.misc.misc_c import prod @@ -34,6 +36,10 @@ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing from sage.rings.rational_field import QQ from sage.sets.primes import Primes +from sage.sets.set import Set +from sage.combinat.permutation import Arrangements +from sage.parallel.use_fork import p_iter_fork +from sage.functions.other import floor def automorphism_group_QQ_fixedpoints(rational_function, return_functions=False, iso_type=False): r""" @@ -1783,3 +1789,476 @@ def which_group(list_of_elements): return ['S_4'] else: return ['A_5'] + +def conjugating_set_initializer(f, g): + """ + Return a conjugation invariant set together with information + to reduce the combinatorics of checking all possible conjugations. + + Do not call this function directly, instead use ``f.conjugating_set(g)``. + + INPUT: + + - ``f`` -- a rational function of degree at least 2, and the same + degree as ``g`` + + - ``g`` -- a nonconstant rational function of the same + degree as ``f`` + + OUTPUT: + + A tuple of the form (``source``, ``possible_targets``). + + - ``source`` -- a conjugation invariant set, used to specify PGL elements which conjugate `f` to `g`. + a list of `n+2` points of the domain of `f`, of which no `n+1` are linearly dependent. + Used to specify a possible conjugation from `f` to `g`. + + - ``possible_targets`` -- a list of tuples of the form (``points``, ``repeated``). ``points`` + is a list of ``points`` which are possible targets for point(s) in ``source``. ``repeated`` + specifies how many points in ``source`` have points in ``points`` as their possible target. + + """ + n = f.domain().dimension_relative() + + L = Set(f.periodic_points(1)) + K = Set(g.periodic_points(1)) + P = f.codomain().ambient_space() + if len(L) != len(K): # checks maps have the same number of fixed points + return [] + + # we store fixed points an multipliers in dictionaries + # to avoid recalculating them + mult_to_point_L = {} + mult_to_point_K = {} + point_to_mult_L = {} + point_to_mult_K = {} + + # as we will calculate preimages, we differentiate points by their 'level' + # which is how many preimages of a fixed point they are, i.e. a fixed point + # has level 0, a preimage of a fixed point level 1, etc. + level = 0 + + # initializing the dictionaries + for i in range(len(L)): + mult_L = f.multiplier(L[i], 1).charpoly() + mult_K = g.multiplier(K[i], 1).charpoly() + tup_L = (mult_L, level) + tup_K = (mult_K, level) + if tup_L not in mult_to_point_L: + mult_to_point_L[tup_L] = [L[i]] + else: + mult_to_point_L[tup_L] += [L[i]] + if tup_K not in mult_to_point_K: + mult_to_point_K[tup_K] = [K[i]] + else: + mult_to_point_K[tup_K] += [K[i]] + point_to_mult_L[L[i]] = (mult_L, level) + point_to_mult_K[K[i]] = (mult_K, level) + + # we keep a dictionary which tracks how often a (multiplier, level) pair + # is repeated. As points can only be sent to points with the same (multiplier, level) + # pair, the less times a (multiplier, level) pair are repeated the better the + # combinatorics + repeated_mult_L = {} + for mult_L in mult_to_point_L: + repeated = len(mult_to_point_L[mult_L]) + if mult_L not in mult_to_point_K: + return [] + elif len(mult_to_point_K[mult_L]) != repeated: + return [] + if repeated not in repeated_mult_L: + repeated_mult_L[repeated] = [mult_to_point_L[mult_L]] + else: + repeated_mult_L[repeated] += [mult_to_point_L[mult_L]] + r = f.domain().base_ring() + more = True + + # the n+2 points to be used to specificy PGL conjugations + source = [] + + # a list of tuples of the form ((multiplier, level), repeat) where the + # (multiplier, level) pair specifies the possible targets of a point in source and repeat + # specifies how many points in source have that (multiplier, level) pair + corresponding = [] + + # we look for a set of n+2 points, of which no n+1 are linearly dependent, + # and we make sure to add the points with the best combinatorics first + for r in sorted(repeated_mult_L.keys()): + for point_lst in repeated_mult_L[r]: + for point in point_lst: + if P.is_linearly_independent(source + [point], n+1): + source.append(point) + mult = point_to_mult_L[point] + # if another point with this multiplier and level pair is in S + # then the multiplier level pair will be the last element of corresponding + if len(corresponding) != 0: + if corresponding[-1][0] == mult: + corresponding[-1][1] += 1 + else: + corresponding.append([mult, 1]) + else: + corresponding.append([mult, 1]) + if len(source) == n+2: + more = False + break + if len(source) == n+2: + break + if len(source) == n+2: + break + + # we keep 3 dictionaries to allow looping over a dictionary + i_repeated_mult = deepcopy(repeated_mult_L) # loop dictionary + a_repeated_mult = {} # loop dictionary for next iteration of loop (if necessary) + found_no_more = True + + # if we don't find enough points, we go to preimages + while more: + level += 1 + # we calculate preimages, starting with preimages with the best + # expected combinatorics + for r in sorted(i_repeated_mult.keys()): + for point_lst_L in i_repeated_mult[r]: + old_tup_L = point_to_mult_L[point_lst_L[0]] + point_lst_K = mult_to_point_K[old_tup_L] + mult_L = old_tup_L[0] + Tl = [] + Tk = [] + + # first we calculate preimages + for pnt in point_lst_L: + for preimage in f.rational_preimages(pnt): + if preimage != pnt: + Tl.append(preimage) + for pnt in point_lst_K: + for preimage in g.rational_preimages(pnt): + if preimage != pnt: + Tk.append(preimage) + if len(Tl) != len(Tk): + return [] + if len(Tl) != 0: + found_no_more = False + new_tup_L = (mult_L, level) + new_tup_K = (mult_L, level) + + # we update dictionaries with the new preimages + mult_to_point_L[new_tup_L] = Tl + mult_to_point_K[new_tup_K] = Tk + for i in range(len(Tl)): + point_to_mult_L[Tl[i]] = new_tup_L + point_to_mult_K[Tk[i]] = new_tup_K + repeated = len(Tl) + if repeated not in repeated_mult_L: + repeated_mult_L[repeated] = [Tl] + else: + repeated_mult_L[repeated] += [Tl] + if repeated not in a_repeated_mult: + a_repeated_mult[repeated] = [Tl] + else: + a_repeated_mult[repeated] += [Tl] + source = [] + corresponding = [] + for r in sorted(repeated_mult_L.keys()): + for point_lst in repeated_mult_L[r]: + for point in point_lst: + if P.is_linearly_independent(source + [point], n+1): + source.append(point) + mult = point_to_mult_L[point] + # if another point with this multiplier and level pair is in S + # then the multiplier level pair will be the last element of corresponding + if len(corresponding) != 0: + if corresponding[-1][0] == mult: + corresponding[-1][1] += 1 + else: + corresponding.append([mult, 1]) + else: + corresponding.append([mult, 1]) + if len(source) == n+2: + more = False + break + if len(source) == n+2: + break + if len(source) == n+2: + break + if not more: + break + if not more: + break + + # if no more preimages can be found, the algorithm fails + if found_no_more: + raise ValueError('no more rational preimages. try extending the base field and trying again.') + + # if we need to add more preimages, we update loop dictionaries + if more: + i_repeated_mult = deepcopy(a_repeated_mult) + a_repeated_mult = {} + found_no_more = True + + # we build a list of iterators in order to loop over the product of those iterators + possible_targets = [] + for tup in corresponding: + possible_targets.append([mult_to_point_K[tup[0]], tup[1]]) + return source, possible_targets + +def conjugating_set_helper(f, g, num_cpus, source, possible_targets): + r""" + Return the set of elements in PGL over the base ring + that conjugates ``f`` to ``g``. + + Do not call this function directly, instead do ``f.conjugate_set(g)``. + + INPUT: + + - ``f`` -- a rational function of degree at least 2, and the same + degree as ``g`` + + - ``g`` -- a rational function of the same + degree as ``f`` + + - ``num_cpus`` -- the number of threads to run in parallel + + - ``source`` -- a list of `n+2` conjugation invariant points, of which + no `n+1` are linearly dependent. + + - ``possible_targets`` -- a list of tuples of the form (``points``, ``repeated``). ``points`` + is a list of ``points`` which are possible targets for point(s) in ``source``. ``repeated`` + specifies how many points in ``source`` have points in ``points`` as their possible target. + + OUTPUT: + + a list of elements of PGL which conjugate ``f`` to ``g``. + """ + Conj = [] + P = f.domain().ambient_space() + n = f.domain().dimension_relative() + + subset_iterators = [] + + for lst in possible_targets: + subset_iterators.append(Subsets(range(len(lst[0])), lst[1])) + + # helper function for parallelization + # given a list of tuples which specify indicies of possible target points + # in possible_targets, check all arragements of those possible target points + # and if any of them define a conjugation which sends f to g, return + # those conjugations as a list + def find_conjugations_subset(tuples): + conj = [] + for tup in tuples: + target_set = [] + for i in range(len(tup)): + for j in tup[i]: + target_set.append(possible_targets[i][0][j]) + + # if there is a subset of n+1 points which is linearly dependent, + # we don't need to check any of these arrangements + if P.is_linearly_independent(target_set, n+1): + subset_arrangements = [] + for subset in tup: + subset_arrangements.append(Arrangements(subset, len(subset))) + for tup in product(*subset_arrangements): + current_target = [] + for i in range(len(tup)): + for j in tup[i]: + current_target.append(possible_targets[i][0][j]) + phi = P.point_transformation_matrix(current_target, source) + if f.conjugate(phi) == g: + conj.append(phi) + return conj + + # helper function for parallelization + # given a list of tuples which specify indicies of possible target points + # in possible_targets, check all possible target points + # and if any of them define a conjugation which sends f to g, return + # those conjugations as a list + def find_conjugations_arrangement(tuples): + conj = [] + for tup in tuples: + current_target = [] + for i in range(len(tup)): + for j in tup[i]: + current_target.append(possible_targets[i][0][j]) + phi = P.point_transformation_matrix(current_target, source) + if f.conjugate(phi) == g: + conj.append(phi) + return conj + + if num_cpus > 1: + all_subsets = list(product(*subset_iterators)) + parallel_data = [] + + # if there are enough subsets, we can divide up the work based on subsets + # and check linear independence in parallel + if len(all_subsets) > num_cpus: + for i in range(num_cpus): + start = floor(len(all_subsets)*i/num_cpus) + end = floor(len(all_subsets)*(i+1)/num_cpus) + tuples = all_subsets[start:end] + parallel_data.append(([tuples], {})) + + X = p_iter_fork(num_cpus) + for ret in X(find_conjugations_subset, parallel_data): + if ret[1]: + Conj += ret[1] + # otherwise, we need to first check linear independence of the subsets + # and then build a big list of all the arrangemenets to split among + # the threads + else: + good_targets = [] + for tup in product(*subset_iterators): + target_set = [] + for i in range(len(tup)): + for j in tup[i]: + target_set.append(possible_targets[i][0][j]) + if P.is_linearly_independent(target_set, n+1): + good_targets.append(tup) + all_arrangements = [] + for tup in good_targets: + subset_arrangements = [] + for subset in tup: + subset_arrangements.append(Arrangements(subset, len(subset))) + all_arrangements += list(product(*subset_arrangements)) + parallel_data = [] + for i in range(num_cpus): + start = floor(len(all_arrangements)*i/num_cpus) + end = floor(len(all_arrangements)*(i+1)/num_cpus) + tuples = all_arrangements[start:end] + parallel_data.append(([tuples], {})) + X = p_iter_fork(num_cpus) + for ret in X(find_conjugations_arrangement, parallel_data): + if ret[1]: + Conj += ret[1] + else: + Conj = find_conjugations_subset(product(*subset_iterators)) + return Conj + +def is_conjugate_helper(f, g, num_cpus, source, possible_targets): + r""" + Return if ``f`` is conjugate to ``g``. + + Do not call this function directly, instead do ``f.is_conjugate(g)``. + + INPUT: + + - ``f`` -- a rational function of degree at least 2, and the same + degree as ``g`` + + - ``g`` -- a rational function of the same + degree as ``f`` + + - ``num_cpus`` -- the number of threads to run in parallel + + - ``source`` -- a list of `n+2` conjugation invariant points, of which + no `n+1` are linearly dependent. + + - ``possible_targets`` -- a list of tuples of the form (``points``, ``repeated``). ``points`` + is a list of ``points`` which are possible targets for point(s) in ``source``. ``repeated`` + specifies how many points in ``source`` have points in ``points`` as their possible target. + + OUTPUT: + + a list of elements of PGL which conjugate ``f`` to ``g``. + """ + is_conj = False + P = f.domain().ambient_space() + n = f.domain().dimension_relative() + + subset_iterators = [] + + for lst in possible_targets: + subset_iterators.append(Subsets(range(len(lst[0])), lst[1])) + + # helper function for parallelization + # given a list of tuples which specify indicies of possible target points + # in possible_targets, check all arragements of those possible target points + # and if any of them define a conjugation which sends f to g, return + # those conjugations as a list + def find_conjugations_subset(tuples): + for tup in tuples: + target_set = [] + for i in range(len(tup)): + for j in tup[i]: + target_set.append(possible_targets[i][0][j]) + + # if there is a subset of n+1 points which is linearly dependent, + # we don't need to check any of these arrangements + if P.is_linearly_independent(target_set, n+1): + subset_arrangements = [] + for subset in tup: + subset_arrangements.append(Arrangements(subset, len(subset))) + for tup in product(*subset_arrangements): + current_target = [] + for i in range(len(tup)): + for j in tup[i]: + current_target.append(possible_targets[i][0][j]) + phi = P.point_transformation_matrix(current_target, source) + if f.conjugate(phi) == g: + return True + return False + + # helper function for parallelization + # given a list of tuples which specify indicies of possible target points + # in possible_targets, check all possible target points + # and if any of them define a conjugation which sends f to g, return + # those conjugations as a list + def find_conjugations_arrangement(tuples): + for tup in tuples: + current_target = [] + for i in range(len(tup)): + for j in tup[i]: + current_target.append(possible_targets[i][0][j]) + phi = P.point_transformation_matrix(current_target, source) + if f.conjugate(phi) == g: + return True + return False + + if num_cpus > 1: + all_subsets = list(product(*subset_iterators)) + parallel_data = [] + + # if there are enough subsets, we can divide up the work based on subsets + # and check linear independence in parallel + if len(all_subsets) > num_cpus: + for i in range(num_cpus): + start = floor(len(all_subsets)*i/num_cpus) + end = floor(len(all_subsets)*(i+1)/num_cpus) + tuples = all_subsets[start:end] + parallel_data.append(([tuples], {})) + + X = p_iter_fork(num_cpus) + for ret in X(find_conjugations_subset, parallel_data): + if ret[1]: + is_conj = True + break + # otherwise, we need to first check linear independence of the subsets + # and then build a big list of all the arrangemenets to split among + # the threads + else: + good_targets = [] + for tup in product(*subset_iterators): + target_set = [] + for i in range(len(tup)): + for j in tup[i]: + target_set.append(possible_targets[i][0][j]) + if P.is_linearly_independent(target_set, n+1): + good_targets.append(tup) + all_arrangements = [] + for tup in good_targets: + subset_arrangements = [] + for subset in tup: + subset_arrangements.append(Arrangements(subset, len(subset))) + all_arrangements += list(product(*subset_arrangements)) + parallel_data = [] + for i in range(num_cpus): + start = floor(len(all_arrangements)*i/num_cpus) + end = floor(len(all_arrangements)*(i+1)/num_cpus) + tuples = all_arrangements[start:end] + parallel_data.append(([tuples], {})) + X = p_iter_fork(num_cpus) + for ret in X(find_conjugations_arrangement, parallel_data): + if ret[1]: + is_conj = True + break + else: + is_conj = find_conjugations_subset(product(*subset_iterators)) + return is_conj \ No newline at end of file diff --git a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py index 1a6d5ce39ab..739aeabcfd8 100644 --- a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py +++ b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py @@ -109,6 +109,13 @@ class initialization directly. from sage.combinat.subset import Subsets from sage.symbolic.ring import SR from itertools import count, product +from .endPN_automorphism_group import ( + automorphism_group_QQ_CRT, + automorphism_group_QQ_fixedpoints, + conjugating_set_helper, + conjugating_set_initializer, + is_conjugate_helper) +from .endPN_automorphism_group import automorphism_group_FF class DynamicalSystem_projective(SchemeMorphism_polynomial_projective_space, @@ -3241,7 +3248,13 @@ def automorphism_group(self, **kwds): INPUT: - keywords: + The following keywords are used in most cases: + + - ``num_cpus`` -- (default: 1) the number of threads to use. Setting to a + larger number can greatly speed up this function. + + The following keywords are used only when the dimension of the domain is 1 and + the base ring is the rationals, but ignored in all other cases: - ``starting_prime`` -- (default: 5) the first prime to use for CRT @@ -3318,7 +3331,7 @@ def automorphism_group(self, **kwds): sage: P. = ProjectiveSpace(QQ,2) sage: f = DynamicalSystem_projective([x**2 + x*z, y**2, z**2]) - sage: f.automorphism_group() # long time + sage: f.automorphism_group() [ [1 0 0] [0 1 0] @@ -3340,10 +3353,11 @@ def automorphism_group(self, **kwds): p = kwds.get('starting_prime', 5) return_functions = kwds.get('return_functions', False) iso_type = kwds.get('iso_type', False) + num_cpus = kwds.get('num_cpus', 1) if self.domain().dimension_relative() != 1: - return self.conjugating_set(self) - if self.base_ring() != QQ and self.base_ring != ZZ: - return self.conjugating_set(self) + return self.conjugating_set(self, num_cpus) + if self.base_ring() != QQ and self.base_ring() != ZZ: + return self.conjugating_set(self, num_cpus) self.normalize_coordinates() if (self.degree() == 1) or (self.degree() == 0): raise NotImplementedError("Rational function of degree 1 not implemented.") @@ -3353,7 +3367,6 @@ def automorphism_group(self, **kwds): F = (f[0].numerator().univariate_polynomial(R))/f[0].denominator().univariate_polynomial(R) else: F = f[0].univariate_polynomial(R) - from .endPN_automorphism_group import automorphism_group_QQ_CRT, automorphism_group_QQ_fixedpoints if alg is None: if self.degree() <= 12: return automorphism_group_QQ_fixedpoints(F, return_functions, iso_type) @@ -6426,7 +6439,7 @@ def connected_rational_component(self, P, n=0): return points[0] - def conjugating_set(self, other, R=None): + def conjugating_set(self, other, R=None, num_cpus=1): r""" Return the set of elements in PGL over the base ring that conjugates one dynamical system to the other. @@ -6464,6 +6477,9 @@ def conjugating_set(self, other, R=None): - ``R`` -- a field or embedding + - ``num_cpus`` -- (default: 1) the number of threads to run in parallel. + Increasing ``num_cpus`` can potentially greatly speed up this function. + OUTPUT: Set of conjugating `n+1` by `n+1` matrices. @@ -6475,6 +6491,8 @@ def conjugating_set(self, other, R=None): - Implemented by Rebecca Lauren Miller, as part of GSOC 2016. + - Algorithmic improvement by Alexander Galarraga as part of GSOC 2021. + EXAMPLES:: sage: P. = ProjectiveSpace(QQ,1) @@ -6518,7 +6536,7 @@ def conjugating_set(self, other, R=None): sage: D8.conjugating_set(D8) Traceback (most recent call last): ... - ValueError: not enough rational preimages + ValueError: no more rational preimages. try extending the base field and trying again. :: @@ -6668,60 +6686,18 @@ def conjugating_set(self, other, R=None): return [m] #not similar return [] - # sigma invariants are invariant under conjugacy but are only implemented in dim 1 + # sigma invariants are invariant under conjugacy but are only fast in dim 1 n = f.domain().dimension_relative() if (n == 1) and (R in NumberFields() or R in FiniteFields())\ and (f.sigma_invariants(1) != g.sigma_invariants(1)): return [] - L = Set(f.periodic_points(1)) - K = Set(g.periodic_points(1)) - if len(L) != len(K): # checks maps have the same number of fixed points + tup = conjugating_set_initializer(f, g) + if tup == []: return [] - d = len(L) - r = f.domain().base_ring() - more = True - if d >= n+2: # need at least n+2 points - for i in Subsets(range(len(L)), n+2): - # make sure all n+1 subsets are linearly independent - TL = [L[il] for il in i] - Ml = matrix(r, [list(s) for s in TL]) - if not any(j == 0 for j in Ml.minors(n + 1)): - Tf = list(TL) - more = False - break - while more: - # finds preimages of fixed points - Tl = [Q for i in L for Q in f.rational_preimages(i)] - Tk = [Q for i in K for Q in g.rational_preimages(i)] - if len(Tl) != len(Tk): - return [] - L = L.union(Set(Tl)) - K = K.union(Set(Tk)) - if d == len(L): # if no new preimages then not enough points - raise ValueError("not enough rational preimages") - d = len(L) - if d >= n + 2: # makes sure all n+1 subsets are linearly independent - for i in Subsets(range(len(L)), n+2): - TL = [L[il] for il in i] - Ml = matrix(r, [list(s) for s in TL]) - if not any(j == 0 for j in Ml.minors(n + 1)): - more = False - Tf = list(TL) - break - Conj = [] - for i in Arrangements(range(len(K)),(n+2)): - TK = [K[ik] for ik in i] - # try all possible conjugations between invariant sets - try: # need all n+1 subsets linearly independent - s = f.domain().point_transformation_matrix(TK,Tf) - # finds elements of PGL that maps one map to another - if self.conjugate(s) == other: - Conj.append(s) - except (ValueError): - pass - return Conj + source, possible_targets = tup + return conjugating_set_helper(f, g, num_cpus, source, possible_targets) - def is_conjugate(self, other, R=None): + def is_conjugate(self, other, R=None, num_cpus=1): r""" Return whether two dynamical systems are conjugate over their base ring (by default) or over the ring `R` entered as an @@ -6740,6 +6716,9 @@ def is_conjugate(self, other, R=None): - ``R`` -- a field or embedding + - ``num_cpus`` -- (default: 1) the number of threads to run in parallel. + Increasing ``num_cpus`` can potentially greatly speed up this function. + OUTPUT: boolean AUTHORS: @@ -6886,57 +6865,16 @@ def is_conjugate(self, other, R=None): # so we can scale to have the determinants equal m1 = (1/det_root)*m1 return m1.is_similar(m2) - # sigma invariants are invariant under conjugacy but are only implemented in dim 1 + # sigma invariants are invariant under conjugacy but are only fast in dim 1 n = f.domain().dimension_relative() if (n==1) and (R in NumberFields() or R in FiniteFields())\ and (f.sigma_invariants(1) != g.sigma_invariants(1)): return False - L = Set(f.periodic_points(1)) - K = Set(g.periodic_points(1)) - if len(L) != len(K): # checks maps have the same number of fixed points + tup = conjugating_set_initializer(f, g) + if tup == []: return False - d = len(L) - r = f.domain().base_ring() - more = True - if d >= n+2: # need at least n+2 points - for i in Subsets(range(len(L)), n+2): - # make sure all n+1 subsets are linearly independent - TL = [L[il] for il in i] - Ml = matrix(r, [list(s) for s in TL]) - if not any(j == 0 for j in Ml.minors(n + 1)): - Tf = list(TL) - more = False - break - while more: - # finds preimages of fixed points - Tl = [Q for i in L for Q in f.rational_preimages(i)] - Tk = [Q for i in K for Q in g.rational_preimages(i)] - if len(Tl) != len(Tk): - return False - L = L.union(Set(Tl)) - K = K.union(Set(Tk)) - if d == len(L):# if no new preimages then not enough points - raise ValueError("not enough rational preimages") - d = len(L) - if d >= n + 2: # makes sure all n+1 subsets are linearly independent - for i in Subsets(range(len(L)), n+2): - TL = [L[il] for il in i] - Ml = matrix(r, [list(s) for s in TL]) - if not any(j == 0 for j in Ml.minors(n + 1)): - more = False - Tf = list(TL) - break - for i in Arrangements(range(len(K)),(n+2)): - TK = [K[ik] for ik in i] - # try all possible conjugations between invariant sets - try: # need all n+1 subsets linearly independent - s = f.domain().point_transformation_matrix(TK,Tf) - # finds elements of PGL that maps one map to another - if self.conjugate(s) == other: - return True - except (ValueError): - pass - return False + source, possible_targets = tup + return is_conjugate_helper(f, g, num_cpus, source, possible_targets) def is_polynomial(self): r""" @@ -7797,7 +7735,7 @@ def possible_periods(self, return_points=False): """ return _fast_possible_periods(self, return_points) - def automorphism_group(self, absolute=False, iso_type=False, return_functions=False): + def automorphism_group(self, **kwds): r""" Return the subgroup of `PGL2` that is the automorphism group of this dynamical system. @@ -7808,6 +7746,14 @@ def automorphism_group(self, absolute=False, iso_type=False, return_functions=Fa INPUT: + The following keywords are used when the dimension of the domain + is greater than 1: + + - ``num_cpus`` -- (default: 1) the number of threads to use. Setting to a + larger number can greatly speed up this function. + + The following keywords are used when the dimension of the domain is 1: + - ``absolute``-- (default: ``False``) boolean; if ``True``, then return the absolute automorphism group and a field of definition @@ -7887,8 +7833,12 @@ def automorphism_group(self, absolute=False, iso_type=False, return_functions=Fa [0 1] ]] """ + absolute = kwds.get('absolute', False) + iso_type = kwds.get('iso_type', False) + return_functions = kwds.get('return_functions', False) + num_cpus = kwds.get('num_cpus', 1) if self.domain().dimension_relative() != 1: - raise NotImplementedError("must be dimension 1") + return self.conjugating_set(self, num_cpus) else: f = self.dehomogenize(1) z = f[0].parent().gen() @@ -7899,7 +7849,6 @@ def automorphism_group(self, absolute=False, iso_type=False, return_functions=Fa F = f[0].numerator().polynomial(z) / f[0].denominator().polynomial(z) else: F = f[0].numerator().polynomial(z) - from .endPN_automorphism_group import automorphism_group_FF return automorphism_group_FF(F, absolute, iso_type, return_functions) def all_periodic_points(self, **kwds): From 76249f2c8e34852ae1a4a44f7cd301816063826e Mon Sep 17 00:00:00 2001 From: Alexander Date: Mon, 12 Jul 2021 15:34:36 -0400 Subject: [PATCH 019/359] 31994: doc fix --- 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 cbcac881a21..86890bea165 100644 --- a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py +++ b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py @@ -5113,7 +5113,7 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point', expected_degree = sum(d**(n*i) for i in range(N+1)) if degree_w != expected_degree: raise ValueError('sigma polynomial dropped degree, as multiplicities were not accounted for correctly.'+ - ' try setting chow=True or deform=True') + ' try setting chow=True and/or deform=True') if return_polynomial: return sigma_polynomial # if we are returing a numerical list, read off the coefficients From e6a2bb78e454b9ea266c87ceb6dcc5cb305a9136 Mon Sep 17 00:00:00 2001 From: Alexander Date: Mon, 12 Jul 2021 16:18:27 -0400 Subject: [PATCH 020/359] updated docs --- .../arithmetic_dynamics/projective_ds.py | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py index 739aeabcfd8..d4f9983d31d 100644 --- a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py +++ b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py @@ -6466,9 +6466,10 @@ def conjugating_set(self, other, R=None, num_cpus=1): ALGORITHM: Implementing invariant set algorithm from the paper [FMV2014]_. - Given that the set of `n` th preimages of fixed points is - invariant under conjugation find all elements of PGL that - take one set to another. + Uses the set of `n` th preimages of fixed points, as this set is + invariant under conjugation to find all elements of PGL that + take one set to another. Additionally, keeps track of multiplier + information to reduce the necessary combinatorics. INPUT: @@ -6552,7 +6553,7 @@ def conjugating_set(self, other, R=None, num_cpus=1): sage: P. = ProjectiveSpace(QQ,2) sage: f = DynamicalSystem_projective([x^2 + x*z, y^2, z^2]) - sage: f.conjugating_set(f) # long time + sage: f.conjugating_set(f) [ [1 0 0] [0 1 0] @@ -6706,8 +6707,10 @@ def is_conjugate(self, other, R=None, num_cpus=1): ALGORITHM: Implementing invariant set algorithm from the paper [FMV2014]_. - Given that the set of `n` th preimages is invariant under - conjugation this function finds whether two maps are conjugate. + Uses the set of `n` th preimages of fixed points, as this set is + invariant under conjugation to find all elements of PGL that + take one set to another. Additionally, keeps track of multiplier + information to reduce the necessary combinatorics. INPUT: @@ -6784,7 +6787,7 @@ def is_conjugate(self, other, R=None, num_cpus=1): sage: P. = ProjectiveSpace(QQ, 1) sage: f = DynamicalSystem_projective([-3*y^2, 3*x^2]) sage: g = DynamicalSystem_projective([-x^2 - 2*x*y, 2*x*y + y^2]) - sage: f.is_conjugate(g), f.is_conjugate(g, R=QQbar) # long time + sage: f.is_conjugate(g), f.is_conjugate(g, R=QQbar) (False, True) :: @@ -7740,9 +7743,12 @@ def automorphism_group(self, **kwds): Return the subgroup of `PGL2` that is the automorphism group of this dynamical system. - Only for dimension 1. The automorphism group is the set of `PGL2` - elements that fixed the map under conjugation. See [FMV2014]_ - for the algorithm. + The automorphism group is the set of `PGL2` elements that fixed the map under conjugation. + + For dimension 1, see [FMV2014]_ for the algorithm. + + For dimension greater than 1, we compute the conjugating set of this + dynamical system with itself. INPUT: From 2a247bb24b73bc6597ff388a4c21b9abf57cc34a Mon Sep 17 00:00:00 2001 From: Alexander Date: Mon, 12 Jul 2021 16:56:16 -0400 Subject: [PATCH 021/359] independent set calculation bug fixed --- .../endPN_automorphism_group.py | 23 ++++++++++++++++++- .../arithmetic_dynamics/projective_ds.py | 8 +++---- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/src/sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py b/src/sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py index 5bdc8c53bcc..ed3f0ed3022 100644 --- a/src/sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py +++ b/src/sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py @@ -1986,7 +1986,28 @@ def conjugating_set_initializer(f, g): # if no more preimages can be found, the algorithm fails if found_no_more: - raise ValueError('no more rational preimages. try extending the base field and trying again.') + all_points = [] + for r in sorted(repeated_mult_L.keys()): + for point_lst in repeated_mult_L[r]: + all_points += point_lst + for subset in Subsets(range(len(all_points)), n+2): + source = [] + for i in subset: + source.append(all_points[i]) + if P.is_linearly_independent(source, n+1): + more = False + corresponding = [] + mult_only = [] + for i in subset: + mult = point_to_mult_L[all_points[i]] + if mult in mult_only: + corresponding[mult_only.index(mult)][1] += 1 + else: + corresponding.append([mult, 1]) + mult_only.append(mult) + break + if more: + raise ValueError('no more rational preimages. try extending the base field and trying again.') # if we need to add more preimages, we update loop dictionaries if more: diff --git a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py index d4f9983d31d..93b8742b3e9 100644 --- a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py +++ b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py @@ -6513,7 +6513,7 @@ def conjugating_set(self, other, R=None, num_cpus=1): sage: f = DynamicalSystem_projective([x^2 + y^2, x*y]) sage: m = matrix(K, 2, 2, [1, 1, 2, 1]) sage: g = f.conjugate(m) - sage: sorted(f.conjugating_set(g)) # long time + sage: sorted(f.conjugating_set(g)) [ [-1 -1] [1 1] [ 2 1], [2 1] @@ -6524,7 +6524,7 @@ def conjugating_set(self, other, R=None, num_cpus=1): sage: K. = QuadraticField(-1) sage: P. = ProjectiveSpace(K,1) sage: D8 = DynamicalSystem_projective([y^3, x^3]) - sage: sorted(D8.conjugating_set(D8)) # long time + sage: sorted(D8.conjugating_set(D8)) [ [-1 0] [-i 0] [ 0 -1] [ 0 -i] [0 i] [0 1] [i 0] [1 0] [ 0 1], [ 0 1], [ 1 0], [ 1 0], [1 0], [1 0], [0 1], [0 1] @@ -6746,7 +6746,7 @@ def is_conjugate(self, other, R=None, num_cpus=1): sage: f = DynamicalSystem_projective([x^2 + x*y,y^2]) sage: m = matrix(QQbar, 2, 2, [1, 1, 2, 1]) sage: g = f.conjugate(m) - sage: f.is_conjugate(g) # long time + sage: f.is_conjugate(g) True :: @@ -6814,7 +6814,7 @@ def is_conjugate(self, other, R=None, num_cpus=1): sage: f = DynamicalSystem_projective([2*x^2 + 12*y*x, 11*y*x+2*y^2, x^2+z^2]) sage: m1 = matrix(QQ, 3, 3, [1,4,1,0,2,1,1,1,1]) sage: g = f.conjugate(m1) - sage: f.is_conjugate(g) # long time + sage: f.is_conjugate(g) True TESTS: From 03bd0e2100895f80b173b54dd97f3a72136dd2ea Mon Sep 17 00:00:00 2001 From: Alexander Date: Tue, 13 Jul 2021 14:01:46 -0400 Subject: [PATCH 022/359] added examples, new function --- .../endPN_automorphism_group.py | 183 +++++++++++++----- .../arithmetic_dynamics/projective_ds.py | 42 ++-- 2 files changed, 161 insertions(+), 64 deletions(-) diff --git a/src/sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py b/src/sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py index ed3f0ed3022..9ec7adbaf7e 100644 --- a/src/sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py +++ b/src/sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py @@ -1809,14 +1809,25 @@ def conjugating_set_initializer(f, g): A tuple of the form (``source``, ``possible_targets``). - - ``source`` -- a conjugation invariant set, used to specify PGL elements which conjugate `f` to `g`. - a list of `n+2` points of the domain of `f`, of which no `n+1` are linearly dependent. - Used to specify a possible conjugation from `f` to `g`. + - ``source`` -- a conjugation invariant set of `n+2` points of the domain of `f`, + of which no `n+1` are linearly dependent. Used to specify a possible conjugation + from `f` to `g`. - ``possible_targets`` -- a list of tuples of the form (``points``, ``repeated``). ``points`` is a list of ``points`` which are possible targets for point(s) in ``source``. ``repeated`` specifies how many points in ``source`` have points in ``points`` as their possible target. + EXAMPLES:: + + sage: P. = ProjectiveSpace(QQ, 2) + sage: f = DynamicalSystem([(8*x^7 - 35*x^4*y^3 - 35*x^4*z^3 - 7*x*y^6 - 140*x*y^3*z^3 \ + - 7*x*z^6), (-7*x^6*y - 35*x^3*y^4 - 140*x^3*y*z^3 + 8*y^7 - 35*y^4*z^3 \ + - 7*y*z^6), -7*x^6*z - 140*x^3*y^3*z - 35*x^3*z^4 - 7*y^6*z - 35*y^3*z^4 + 8*z^7]) + sage: from sage.dynamics.arithmetic_dynamics.endPN_automorphism_group import conjugating_set_initializer + sage: conjugating_set_initializer(f, f) + ([(-1 : 0 : 1), (0 : -1 : 1), (0 : 1 : 0), (1 : 0 : 0)], + [[[(-1 : 0 : 1), (0 : -1 : 1), (-1 : 1 : 0)], 2], + [[(0 : 1 : 0), (1 : 0 : 0), (1 : 1 : 1), (0 : 0 : 1)], 2]]) """ n = f.domain().dimension_relative() @@ -1881,30 +1892,16 @@ def conjugating_set_initializer(f, g): # specifies how many points in source have that (multiplier, level) pair corresponding = [] - # we look for a set of n+2 points, of which no n+1 are linearly dependent, - # and we make sure to add the points with the best combinatorics first - for r in sorted(repeated_mult_L.keys()): - for point_lst in repeated_mult_L[r]: - for point in point_lst: - if P.is_linearly_independent(source + [point], n+1): - source.append(point) - mult = point_to_mult_L[point] - # if another point with this multiplier and level pair is in S - # then the multiplier level pair will be the last element of corresponding - if len(corresponding) != 0: - if corresponding[-1][0] == mult: - corresponding[-1][1] += 1 - else: - corresponding.append([mult, 1]) - else: - corresponding.append([mult, 1]) - if len(source) == n+2: - more = False - break - if len(source) == n+2: - break - if len(source) == n+2: - break + # we now greedily look for a set of n+2 points, of which no n+1 are linearly dependent, + # and we make sure to add the points with the best combinatorics first. + # this check sometimes fails, i.e. sometimes there is a subset with the + # desired property which is not found. however, this check is very fast and if it + # does find a subset, then the subset will most likely minimize the combinatorics + # of checking conjugations + tup = greedy_independence_check(P, repeated_mult_L, point_to_mult_L) + if not tup is None: + more = False + source, corresponding = tup # we keep 3 dictionaries to allow looping over a dictionary i_repeated_mult = deepcopy(repeated_mult_L) # loop dictionary @@ -1955,41 +1952,28 @@ def conjugating_set_initializer(f, g): a_repeated_mult[repeated] = [Tl] else: a_repeated_mult[repeated] += [Tl] - source = [] - corresponding = [] - for r in sorted(repeated_mult_L.keys()): - for point_lst in repeated_mult_L[r]: - for point in point_lst: - if P.is_linearly_independent(source + [point], n+1): - source.append(point) - mult = point_to_mult_L[point] - # if another point with this multiplier and level pair is in S - # then the multiplier level pair will be the last element of corresponding - if len(corresponding) != 0: - if corresponding[-1][0] == mult: - corresponding[-1][1] += 1 - else: - corresponding.append([mult, 1]) - else: - corresponding.append([mult, 1]) - if len(source) == n+2: - more = False - break - if len(source) == n+2: - break - if len(source) == n+2: - break + # we again do a greedy check for a subset of n+2 points, of which no n+1 + # are linearly dependent + tup = greedy_independence_check(P, repeated_mult_L, point_to_mult_L) + if not tup is None: + more = False + source, corresponding = tup if not more: break if not more: break - # if no more preimages can be found, the algorithm fails + # if no more preimages can be found, we must check all subsets + # of size n+2 to see if there is a subset in which no n+1 points + # are linearly dependent if found_no_more: all_points = [] for r in sorted(repeated_mult_L.keys()): for point_lst in repeated_mult_L[r]: all_points += point_lst + # this loop is quite long, so we break after finding the first subset + # with the desired property. There is, however, no guarentee that the + # subset we found minimizes the combinatorics when checking conjugations for subset in Subsets(range(len(all_points)), n+2): source = [] for i in subset: @@ -2006,6 +1990,9 @@ def conjugating_set_initializer(f, g): corresponding.append([mult, 1]) mult_only.append(mult) break + # if we iterated over all subsets of size n+2, and did not find one + # in which all subsets of size n+1 are linearly independent, + # then we fail as we cannot specify conjugations if more: raise ValueError('no more rational preimages. try extending the base field and trying again.') @@ -2021,6 +2008,75 @@ def conjugating_set_initializer(f, g): possible_targets.append([mult_to_point_K[tup[0]], tup[1]]) return source, possible_targets +def greedy_independence_check(P, repeated_mult, point_to_mult): + r""" + Return a conjugation invariant set together with information + to reduce the combinatorics of checking all possible conjugations. + + This function may sometimes fail to find the conjugation invariant + set even though one exists. It is useful, however, as it is fast + and returns a set which usually minimizes the combinatorics of + checking all conjugations. + + INPUT: + + - ``P`` -- a projective space + + - ``repeated_mult`` -- a dictionary of integers to lists of points of + the projective space ``P``. The list of points should be conjugation + invariant. The keys are considered as weights, and this function attempts + to minimize the total weight + + - ``point_to_mult`` -- a dictionary of points of ``P`` to tuples of the form + (multiplier, level), where multiplier is the characteristic polynomial + of the multiplier of the point, and level is the number of preimages + taken to find the point + + OUTPUT: + + If no set of `n+2` points of which all subsets of size `n+1` are linearly + independent can be found, then ``None`` is returned. + + Otherwise, a tuple of the form (``source``, ``corresponding``) is returned. + + - ``source`` -- a conjugation invariant set of `n+2` points of the domain of `f`, + of which no `n+1` are linearly dependent. Used to specify a possible conjugation + from `f` to `g`. + + - ``corresponding`` -- a list of tuples of the form ((multiplier, level), repeat) where the + (multiplier, level) pair is the multiplier of a point in ``source`` and repeat + specifies how many points in source have that (multiplier, level) pair + + EXAMPLES:: + + sage: from sage.dynamics.arithmetic_dynamics.endPN_automorphism_group import greedy_independence_check + sage: P. = ProjectiveSpace(QQ, 1) + sage: repeated_mult = {2: [[P((0, 1)), P((1, 0))]], 1: [[P((1, 1))]]} + sage: point_to_mult = {P((0, 1)): (x, 0), P((1, 0)): (x, 0), P((1, 1)): (x - 2, 0)} + sage: greedy_independence_check(P, repeated_mult, point_to_mult) + ([(1 : 1), (0 : 1), (1 : 0)], [[(x - 2, 0), 1], [(x, 0), 2]]) + """ + n = P.dimension_relative() + source = [] + corresponding = [] + for r in sorted(repeated_mult.keys()): + for point_lst in repeated_mult[r]: + for point in point_lst: + if P.is_linearly_independent(source + [point], n+1): + source.append(point) + mult = point_to_mult[point] + # if another point with this multiplier and level pair is in S + # then the multiplier level pair will be the last element of corresponding + if len(corresponding) != 0: + if corresponding[-1][0] == mult: + corresponding[-1][1] += 1 + else: + corresponding.append([mult, 1]) + else: + corresponding.append([mult, 1]) + if len(source) == n+2: + return source, corresponding + def conjugating_set_helper(f, g, num_cpus, source, possible_targets): r""" Return the set of elements in PGL over the base ring @@ -2048,6 +2104,19 @@ def conjugating_set_helper(f, g, num_cpus, source, possible_targets): OUTPUT: a list of elements of PGL which conjugate ``f`` to ``g``. + + EXAMPLES:: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: f = DynamicalSystem([x^2, y^2]) + sage: source = [P((1, 1)), P((0, 1)), P((1, 0))] + sage: possible_targets = [[[P((1, 1))], 1], [[P((0, 1)), P((1, 0))], 2]] + sage: from sage.dynamics.arithmetic_dynamics.endPN_automorphism_group import conjugating_set_helper + sage: conjugating_set_helper(f, f, 2, source, possible_targets) + [ + [1 0] [0 1] + [0 1], [1 0] + ] """ Conj = [] P = f.domain().ambient_space() @@ -2179,6 +2248,16 @@ def is_conjugate_helper(f, g, num_cpus, source, possible_targets): OUTPUT: a list of elements of PGL which conjugate ``f`` to ``g``. + + EXAMPLES:: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: f = DynamicalSystem([x^2, y^2]) + sage: source = [P((1, 1)), P((0, 1)), P((1, 0))] + sage: possible_targets = [[[P((1, 1))], 1], [[P((0, 1)), P((1, 0))], 2]] + sage: from sage.dynamics.arithmetic_dynamics.endPN_automorphism_group import is_conjugate_helper + sage: is_conjugate_helper(f, f, 2, source, possible_targets) + True """ is_conj = False P = f.domain().ambient_space() diff --git a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py index 93b8742b3e9..fabc4c432b1 100644 --- a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py +++ b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py @@ -6451,8 +6451,10 @@ def conjugating_set(self, other, R=None, num_cpus=1): The optional argument `R` specifies the field of definition of the PGL elements. The set is determined by taking the fixed points of one map and mapping - them to all unique permutations of the fixed points of - the other map. If there are not enough fixed points the + them to permutations of the fixed points of the other map. + As conjugacy preserves the multipliers as a set, fixed points + are only maped to fixed points with the same multiplier. + If there are not enough fixed points the function compares the mapping between rational preimages of fixed points and the rational preimages of the preimages of fixed points until there are enough points; such that there @@ -6490,7 +6492,7 @@ def conjugating_set(self, other, R=None, num_cpus=1): - Original algorithm written by Xander Faber, Michelle Manes, Bianca Viray [FMV2014]_. - - Implemented by Rebecca Lauren Miller, as part of GSOC 2016. + - Implemented by Rebecca Lauren Miller as part of GSOC 2016. - Algorithmic improvement by Alexander Galarraga as part of GSOC 2021. @@ -6506,6 +6508,13 @@ def conjugating_set(self, other, R=None, num_cpus=1): [ 2 1] ] + Increasing ``num_cpus`` can speed up computation:: + + sage: P. = ProjectiveSpace(QQ,3) + sage: f = DynamicalSystem_projective([x^2, y^2, z^2, w^2]) + sage: len(f.conjugating_set(f, num_cpus=2)) + 24 + :: sage: K. = QuadraticField(-1) @@ -6731,19 +6740,28 @@ def is_conjugate(self, other, R=None, num_cpus=1): - Implemented by Rebecca Lauren Miller as part of GSOC 2016. + - Algorithmic improvement by Alexander Galarraga as part of GSOC 2016. + EXAMPLES:: sage: K. = CyclotomicField(3) - sage: P. = ProjectiveSpace(K,1) + sage: P. = ProjectiveSpace(K, 1) sage: D8 = DynamicalSystem_projective([y^2, x^2]) sage: D8.is_conjugate(D8) True + We can speed up computation by increasing ``num_cpus``:: + + sage: P. = ProjectiveSpace(QQ,3) + sage: f = DynamicalSystem_projective([x^2, y^2, z^2, w^2]) + sage: f.is_conjugate(f, num_cpus=2) + True + :: sage: set_verbose(None) - sage: P. = ProjectiveSpace(QQbar,1) - sage: f = DynamicalSystem_projective([x^2 + x*y,y^2]) + sage: P. = ProjectiveSpace(QQbar, 1) + sage: f = DynamicalSystem_projective([x^2 + x*y, y^2]) sage: m = matrix(QQbar, 2, 2, [1, 1, 2, 1]) sage: g = f.conjugate(m) sage: f.is_conjugate(g) @@ -6751,8 +6769,8 @@ def is_conjugate(self, other, R=None, num_cpus=1): :: - sage: P. = ProjectiveSpace(GF(5),1) - sage: f = DynamicalSystem_projective([x^3 + x*y^2,y^3]) + sage: P. = ProjectiveSpace(GF(5), 1) + sage: f = DynamicalSystem_projective([x^3 + x*y^2, y^3]) sage: m = matrix(GF(5), 2, 2, [1, 3, 2, 9]) sage: g = f.conjugate(m) sage: f.is_conjugate(g) @@ -6760,15 +6778,15 @@ def is_conjugate(self, other, R=None, num_cpus=1): :: - sage: P. = ProjectiveSpace(QQ,1) - sage: f = DynamicalSystem_projective([x^2 + x*y,y^2]) + sage: P. = ProjectiveSpace(QQ, 1) + sage: f = DynamicalSystem_projective([x^2 + x*y, y^2]) sage: g = DynamicalSystem_projective([x^3 + x^2*y, y^3]) sage: f.is_conjugate(g) False :: - sage: P. = ProjectiveSpace(QQ,1) + sage: P. = ProjectiveSpace(QQ, 1) sage: f = DynamicalSystem_projective([x^2 + x*y, y^2]) sage: g = DynamicalSystem_projective([x^2 - 2*y^2, y^2]) sage: f.is_conjugate(g) @@ -6810,7 +6828,7 @@ def is_conjugate(self, other, R=None, num_cpus=1): :: - sage: P. = ProjectiveSpace(QQ,2) + sage: P. = ProjectiveSpace(QQ, 2) sage: f = DynamicalSystem_projective([2*x^2 + 12*y*x, 11*y*x+2*y^2, x^2+z^2]) sage: m1 = matrix(QQ, 3, 3, [1,4,1,0,2,1,1,1,1]) sage: g = f.conjugate(m1) From f7f22a8865b94ea499c33c198bc13edc432622d6 Mon Sep 17 00:00:00 2001 From: Alexander Date: Tue, 13 Jul 2021 14:15:55 -0400 Subject: [PATCH 023/359] 31994: added degree check when formal=True --- .../arithmetic_dynamics/projective_ds.py | 35 ++++++++++++++++--- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py index 86890bea165..cb4d77489cc 100644 --- a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py +++ b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py @@ -52,7 +52,7 @@ class initialization directly. # https://www.gnu.org/licenses/ # **************************************************************************** -from sage.arith.misc import is_prime +from sage.arith.misc import is_prime, moebius from sage.calculus.functions import jacobian from sage.categories.fields import Fields from sage.categories.function_fields import FunctionFields @@ -4983,8 +4983,28 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point', sage: N. = NumberField(w^2 + 1) sage: P. = ProjectiveSpace(N, 2) sage: f = DynamicalSystem_projective([x^2, y^2, z^2]) - sage: #f.sigma_invariants(1, chow=True) == f.change_ring(QQ).sigma_invariants(1, chow=True) + sage: f.sigma_invariants(1, chow=True) == f.change_ring(QQ).sigma_invariants(1, chow=True) True + + :: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: f = DynamicalSystem([x^2 + 3*y^2, x*y]) + sage: f.sigma_invariants(1, formal=True, return_polynomial=True) + Traceback (most recent call last): + .. + ValueError: sigma polynomial dropped degree, as multiplicities were not accounted + for correctly. try setting chow=True and/or deform=True + + :: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: f = DynamicalSystem([x^2 + 3*y^2, x*y]) + sage: f.sigma_invariants(1, return_polynomial=True) + Traceback (most recent call last): + .. + ValueError: sigma polynomial dropped degree, as multiplicities were not accounted + for correctly. try setting chow=True and/or deform=True """ n = ZZ(n) if n < 1: @@ -5108,9 +5128,16 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point', sigma_polynomial *= poly if not base_ring.is_field(): sigma_polynomial = ringR(sigma_polynomial) - if check and not formal: + if check: degree_w = sigma_polynomial.degrees()[0] - expected_degree = sum(d**(n*i) for i in range(N+1)) + if formal: + expected_degree = 0 + for D in n.divisors(): + u = moebius(n/D) + inner_sum = sum(d**(D*j) for j in range(N+1)) + expected_degree += u*inner_sum + else: + expected_degree = sum(d**(n*i) for i in range(N+1)) if degree_w != expected_degree: raise ValueError('sigma polynomial dropped degree, as multiplicities were not accounted for correctly.'+ ' try setting chow=True and/or deform=True') From b86822d90266c102b9bf97a24e84f0d5ed0c132d Mon Sep 17 00:00:00 2001 From: Alexander Date: Tue, 13 Jul 2021 16:49:57 -0400 Subject: [PATCH 024/359] fixed comments --- .../endPN_automorphism_group.py | 50 ++++++++++++------- 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/src/sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py b/src/sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py index 9ec7adbaf7e..a6d77e854ac 100644 --- a/src/sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py +++ b/src/sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py @@ -1795,6 +1795,13 @@ def conjugating_set_initializer(f, g): Return a conjugation invariant set together with information to reduce the combinatorics of checking all possible conjugations. + This function constructs the conjugation invariant set (``source``) + necessary for the conjugating set algorithm described in [FMV2014]_. + Additionally, it keeps track of multipliers to reduce the combinatorics. + This information is then passed to ``conjugating_set_helper`` or + ``is_conjugate_helper``, which check all possible conjugations determined + by the conjugation invariant set. + Do not call this function directly, instead use ``f.conjugating_set(g)``. INPUT: @@ -1903,24 +1910,25 @@ def conjugating_set_initializer(f, g): more = False source, corresponding = tup - # we keep 3 dictionaries to allow looping over a dictionary - i_repeated_mult = deepcopy(repeated_mult_L) # loop dictionary - a_repeated_mult = {} # loop dictionary for next iteration of loop (if necessary) - found_no_more = True + else: + # loop_repeated_mult stores the points to find preimages of + loop_repeated_mult = deepcopy(repeated_mult_L) + # next_repeated_mult stores the points to find preimages of on the next loop + next_repeated_mult = {} + found_no_more = True # if we don't find enough points, we go to preimages while more: level += 1 # we calculate preimages, starting with preimages with the best # expected combinatorics - for r in sorted(i_repeated_mult.keys()): - for point_lst_L in i_repeated_mult[r]: + for r in sorted(loop_repeated_mult.keys()): + for point_lst_L in loop_repeated_mult[r]: old_tup_L = point_to_mult_L[point_lst_L[0]] point_lst_K = mult_to_point_K[old_tup_L] mult_L = old_tup_L[0] Tl = [] Tk = [] - # first we calculate preimages for pnt in point_lst_L: for preimage in f.rational_preimages(pnt): @@ -1936,7 +1944,6 @@ def conjugating_set_initializer(f, g): found_no_more = False new_tup_L = (mult_L, level) new_tup_K = (mult_L, level) - # we update dictionaries with the new preimages mult_to_point_L[new_tup_L] = Tl mult_to_point_K[new_tup_K] = Tk @@ -1948,10 +1955,10 @@ def conjugating_set_initializer(f, g): repeated_mult_L[repeated] = [Tl] else: repeated_mult_L[repeated] += [Tl] - if repeated not in a_repeated_mult: - a_repeated_mult[repeated] = [Tl] + if repeated not in next_repeated_mult: + next_repeated_mult[repeated] = [Tl] else: - a_repeated_mult[repeated] += [Tl] + next_repeated_mult[repeated] += [Tl] # we again do a greedy check for a subset of n+2 points, of which no n+1 # are linearly dependent tup = greedy_independence_check(P, repeated_mult_L, point_to_mult_L) @@ -1967,7 +1974,10 @@ def conjugating_set_initializer(f, g): # of size n+2 to see if there is a subset in which no n+1 points # are linearly dependent if found_no_more: + # we construct a list of all the possible sources points all_points = [] + # we order the list by how many repeated multipliers each point has + # in an attempt to reduce the combinatorics of checking conjugations for r in sorted(repeated_mult_L.keys()): for point_lst in repeated_mult_L[r]: all_points += point_lst @@ -1998,8 +2008,8 @@ def conjugating_set_initializer(f, g): # if we need to add more preimages, we update loop dictionaries if more: - i_repeated_mult = deepcopy(a_repeated_mult) - a_repeated_mult = {} + loop_repeated_mult = deepcopy(next_repeated_mult) + next_repeated_mult = {} found_no_more = True # we build a list of iterators in order to loop over the product of those iterators @@ -2082,6 +2092,9 @@ def conjugating_set_helper(f, g, num_cpus, source, possible_targets): Return the set of elements in PGL over the base ring that conjugates ``f`` to ``g``. + This function takes as input the conjugation invariant set + and multiplier data from ``conjugating_set_initializer``. + Do not call this function directly, instead do ``f.conjugate_set(g)``. INPUT: @@ -2226,6 +2239,9 @@ def is_conjugate_helper(f, g, num_cpus, source, possible_targets): r""" Return if ``f`` is conjugate to ``g``. + This function takes as input the conjugation invariant set + and multiplier data from ``conjugating_set_initializer``. + Do not call this function directly, instead do ``f.is_conjugate(g)``. INPUT: @@ -2247,7 +2263,7 @@ def is_conjugate_helper(f, g, num_cpus, source, possible_targets): OUTPUT: - a list of elements of PGL which conjugate ``f`` to ``g``. + ``True`` if ``f`` is conjugate to ``g``, ``False`` otherwise. EXAMPLES:: @@ -2271,8 +2287,7 @@ def is_conjugate_helper(f, g, num_cpus, source, possible_targets): # helper function for parallelization # given a list of tuples which specify indicies of possible target points # in possible_targets, check all arragements of those possible target points - # and if any of them define a conjugation which sends f to g, return - # those conjugations as a list + # and if any of them define a conjugation which sends f to g, return True def find_conjugations_subset(tuples): for tup in tuples: target_set = [] @@ -2299,8 +2314,7 @@ def find_conjugations_subset(tuples): # helper function for parallelization # given a list of tuples which specify indicies of possible target points # in possible_targets, check all possible target points - # and if any of them define a conjugation which sends f to g, return - # those conjugations as a list + # and if any of them define a conjugation which sends f to g, return True def find_conjugations_arrangement(tuples): for tup in tuples: current_target = [] From 063f159f6c1fa82966a3173da2a0558333758fe7 Mon Sep 17 00:00:00 2001 From: Alexander Date: Thu, 15 Jul 2021 11:57:48 -0400 Subject: [PATCH 025/359] 31994: added more documentation --- .../arithmetic_dynamics/projective_ds.py | 41 +++++++++++++++---- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py index 9a723dc7b72..079d37b48ec 100644 --- a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py +++ b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py @@ -4750,20 +4750,24 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point', Computes the values of the elementary symmetric polynomials of the ``n`` multiplier spectra of this dynamical system. + For maps defined over projective space of dimension greater than 1, + the sigma invariants are the symetric polynomials in the characteristic + polynomials of the multipliers. See [Hutz2019]_ for the full definition. + Can specify to instead compute the values corresponding to the elementary symmetric polynomials of the formal ``n`` multiplier - spectra. The map must be defined over projective space of dimension - `1`. The base ring should be a number field, number field order, or + spectra. The base ring should be a number field, number field order, or a finite field or a polynomial ring or function field over a number field, number field order, or finite field. The parameter ``type`` determines if the sigma are computed from the multipliers calculated at one per cycle (with multiplicity) - or one per point (with multiplicity). Note that in the ``cycle`` - case, a map with a cycle which collapses into multiple smaller - cycles, this is still considered one cycle. In other words, if a - 4-cycle collapses into a 2-cycle with multiplicity 2, there is only - one multiplier used for the doubled 2-cycle when computing ``n=4``. + or one per point (with multiplicity). Only implemented + for dimension 1. Note that in the ``cycle`` case, a map with a cycle + which collapses into multiple smaller cycles, this is still + considered one cycle. In other words, if a 4-cycle collapses into + a 2-cycle with multiplicity 2, there is only one multiplier used + for the doubled 2-cycle when computing ``n=4``. ALGORITHM: @@ -4779,7 +4783,28 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point', denominators for `g`. To calculate the full polynomial defining the sigma invariants, - we follow the algorithm outlined in section 4 of [Hutz2019]_. + we follow the algorithm outlined in section 4 of [Hutz2019]_. There + are 4 cases: + + - multipliers and ``n`` periodic points all distinct -- in this case, + we can use Proposition 4.1 of [Hutz2019]_ to compute the sigma invariants. + + - ``n`` periodic points are all distinct, multipliers are repeated -- here we + can use Proposition 4.2 of [Hutz2019]_ to compute the sigma invariants. + This corresponds to ``chow=True``. + + - ``n`` periodic points are repeated, multipliers are all distinct -- to deal + with this case, we deform the map by a formal parameter `k`. The deformation + seperates the ``n`` periodic points, making them distinct, and we can recover + the ``n`` periodic points of the original map by specializing `k` to 0. + This corresponds to ``deform=True``. + + - ``n`` periodic points are repeated, multipliers are repeated -- here we + can use both cases 2 and 3 together. This corresponds to ``deform=True`` + and ``chow=True``. + + As we do not want to check which case we are in beforehand, we throw an error + if the computed polynomial drops in degree. INPUT: From 6186c586af31171f64a1d1c8fb372280a1319ecf Mon Sep 17 00:00:00 2001 From: bhutz Date: Thu, 15 Jul 2021 14:21:32 -0500 Subject: [PATCH 026/359] 31994: updated docs --- src/doc/en/reference/references/index.rst | 3 +- .../arithmetic_dynamics/projective_ds.py | 42 ++++++++++++------- 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/src/doc/en/reference/references/index.rst b/src/doc/en/reference/references/index.rst index f1f79881b62..2b61d75e4fd 100644 --- a/src/doc/en/reference/references/index.rst +++ b/src/doc/en/reference/references/index.rst @@ -3042,7 +3042,8 @@ REFERENCES: for morphisms of PN. Mathematics of Computation, 84:291 (2015), 289-308. .. [Hutz2019] \B. Hutz. Multipliers and invariants of endomorphisms of projective - space in dimension greater than 1, :arxiv:`1908.03184`, 2019. + space in dimension greater than 1, Journal de Théorie des Nombres de + Bordeaux, Tome 32 (2020) no. 2, pp. 439-469. .. [Huy2005] \D. Huybrechts : *Complex Geometry*, Springer (Berlin) (2005). diff --git a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py index 079d37b48ec..0d9f5d2557c 100644 --- a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py +++ b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py @@ -4747,16 +4747,26 @@ def multiplier_spectra(self, n, formal=False, type='point', use_algebraic_closur def sigma_invariants(self, n, formal=False, embedding=None, type='point', return_polynomial=False, chow=False, deform=False, check=True): r""" - Computes the values of the elementary symmetric polynomials of - the ``n`` multiplier spectra of this dynamical system. + Computes the values of the elementary symmetric polynomials evaluated + on the ``n`` multiplier spectra of this dynamical system. - For maps defined over projective space of dimension greater than 1, - the sigma invariants are the symetric polynomials in the characteristic - polynomials of the multipliers. See [Hutz2019]_ for the full definition. + The sigma invariants are the symetric polynomials evaluated on the + characteristic polynomial of the multipliers. See [Hutz2019]_ for + the full definition. Spepcifically, this function returns either + the following polynomial or its coefficients (with signs + appropriately adjusted): - Can specify to instead compute the values corresponding to the - elementary symmetric polynomials of the formal ``n`` multiplier - spectra. The base ring should be a number field, number field order, or + .. MATH:: + + \prod_{P \text{ period n}} ( w - c(P,t)), + + where `c(P,t)` is the charateristic polynomial (variable `t`) of the + multiplier at `P`. Note that in dimension 1, only the coefficients + of the constant term is returned. + + The invariants can be computed for points of period ``n`` or + points of formal period ``n``. The base + ring should be a number field, number field order, or a finite field or a polynomial ring or function field over a number field, number field order, or finite field. @@ -4771,15 +4781,19 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point', ALGORITHM: - We use the Poisson product of the resultant of two polynomials: + In dimension 1, we use the Poisson product of the resultant of + two polynomials: .. MATH:: res(f,g) = \prod_{f(a)=0} g(a). - Letting `f` be the polynomial defining the periodic or formal - periodic points and `g` the polynomial `w - f'` for an auxilarly - variable `w`. Note that if `f` is a rational function, we clear + In higher dimensions, we use elimination theory (Groebner bases) + to compute the equivalent of the Poisson product. Letting `f` be + the polynomial defining the periodic or formal + periodic points and `g` the polynomial `w - F` for an auxilarly + variable `w` and `F` the characteristic polynomial of the Jacobian matrix + of `f`. Note that if `f` is a rational function, we clear denominators for `g`. To calculate the full polynomial defining the sigma invariants, @@ -4803,8 +4817,8 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point', can use both cases 2 and 3 together. This corresponds to ``deform=True`` and ``chow=True``. - As we do not want to check which case we are in beforehand, we throw an error - if the computed polynomial drops in degree. + As we do not want to check which case we are in beforehand, we throw a + ValueError if the computed polynomial does not have the correct degree. INPUT: From b882a6a8bb61edbf92ca95ed76d2337820c4cbaa Mon Sep 17 00:00:00 2001 From: Alexander Date: Tue, 20 Jul 2021 12:42:35 -0400 Subject: [PATCH 027/359] 32199: set default cpus to 2 --- src/sage/dynamics/arithmetic_dynamics/projective_ds.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py index bd9ddef3496..91402c18da3 100644 --- a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py +++ b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py @@ -6472,7 +6472,7 @@ def connected_rational_component(self, P, n=0): return points[0] - def conjugating_set(self, other, R=None, num_cpus=1): + def conjugating_set(self, other, R=None, num_cpus=2): r""" Return the set of elements in PGL over the base ring that conjugates one dynamical system to the other. @@ -6513,7 +6513,7 @@ def conjugating_set(self, other, R=None, num_cpus=1): - ``R`` -- a field or embedding - - ``num_cpus`` -- (default: 1) the number of threads to run in parallel. + - ``num_cpus`` -- (default: 2) the number of threads to run in parallel. Increasing ``num_cpus`` can potentially greatly speed up this function. OUTPUT: @@ -7806,7 +7806,7 @@ def automorphism_group(self, **kwds): The following keywords are used when the dimension of the domain is greater than 1: - - ``num_cpus`` -- (default: 1) the number of threads to use. Setting to a + - ``num_cpus`` -- (default: 2) the number of threads to use. Setting to a larger number can greatly speed up this function. The following keywords are used when the dimension of the domain is 1: @@ -7893,7 +7893,7 @@ def automorphism_group(self, **kwds): absolute = kwds.get('absolute', False) iso_type = kwds.get('iso_type', False) return_functions = kwds.get('return_functions', False) - num_cpus = kwds.get('num_cpus', 1) + num_cpus = kwds.get('num_cpus', 2) if self.domain().dimension_relative() != 1: return self.conjugating_set(self, num_cpus) else: From f073844d8b3878b679d7858c03da999564dfca7a Mon Sep 17 00:00:00 2001 From: Christian Wuthrich Date: Wed, 21 Jul 2021 13:19:19 +0100 Subject: [PATCH 028/359] adjust 2-adic lseries for elliptic curves --- .../schemes/elliptic_curves/padic_lseries.py | 24 +++++++------------ 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/src/sage/schemes/elliptic_curves/padic_lseries.py b/src/sage/schemes/elliptic_curves/padic_lseries.py index 3506a565459..030607b5c72 100644 --- a/src/sage/schemes/elliptic_curves/padic_lseries.py +++ b/src/sage/schemes/elliptic_curves/padic_lseries.py @@ -851,7 +851,7 @@ def series(self, n=2, quadratic_twist=+1, prec=5, eta=0): raise ValueError("Insufficient precision (%s)" % prec) # check if the conditions on quadratic_twist are satisfied - eta = ZZ(eta) % (self._p - 1) + eta = ZZ(eta) % (self._p- 1) if self._p != 2 else ZZ(eta) % 2 D = ZZ(quadratic_twist) if D != 1: if eta != 0: @@ -870,6 +870,7 @@ def series(self, n=2, quadratic_twist=+1, prec=5, eta=0): if valuation(self._E.conductor(), ell) > valuation(D, ell): raise ValueError("cannot twist a curve of conductor (=%s) by the quadratic twist (=%s)."%(self._E.conductor(),D)) p = self._p + si = 1-2*(eta % 2) #verbose("computing L-series for p=%s, n=%s, and prec=%s"%(p,n,prec)) @@ -891,17 +892,9 @@ def series(self, n=2, quadratic_twist=+1, prec=5, eta=0): return L else: # here we need some sums anyway - if eta % 2 == 1: - si = ZZ(-1) - else: - si = ZZ(1) bounds = self._prec_bounds(n,prec,sign=si) padic_prec = 20 else: - if eta % 2 == 1: - si = ZZ(-1) - else: - si = ZZ(1) bounds = self._prec_bounds(n,prec,sign=si) padic_prec = max(bounds[1:]) + 5 @@ -935,7 +928,6 @@ def series(self, n=2, quadratic_twist=+1, prec=5, eta=0): gamma = K(1+ p) p_power = p**(n-1) a_range = p - si = 1-2*(eta % 2) verbose("Now iterating over %s summands"%((p-1)*p_power)) verbose_level = get_verbose() @@ -964,7 +956,9 @@ def series(self, n=2, quadratic_twist=+1, prec=5, eta=0): [aj[j].add_bigoh(bounds[j]) for j in range(1,len(aj))] L = R(aj,res_series_prec ) - L /= self._quotient_of_periods_to_twist(D)*self._E.real_components() + L /= self._quotient_of_periods_to_twist(D) + if si == +1: + L /= self._E.real_components() self._set_series_in_cache(n, res_series_prec, D, eta, L) @@ -1226,9 +1220,7 @@ def series(self, n=3, quadratic_twist=+1, prec=5, eta=0): raise ValueError("cannot twist a curve of conductor (=%s) by the quadratic twist (=%s)." % (self._E.conductor(), D)) p = self._p - eta = ZZ(eta) % (p - 1) - #if p == 2 and self._normalize: - #print('Warning : for p = 2 the normalization might not be correct !') + eta = ZZ(eta) % (p - 1) if p != 2 else ZZ(eta) % 2 if prec == 1: if eta == 0: @@ -1306,7 +1298,9 @@ def series(self, n=3, quadratic_twist=+1, prec=5, eta=0): bj.append( aj[j].add_bigoh(bounds[j]) ) j += 1 L = R(bj, prec) - L /= self._quotient_of_periods_to_twist(D)*self._E.real_components() + L /= self._quotient_of_periods_to_twist(D) + if si == +1 : + L /= self._E.real_components() self._set_series_in_cache(n, prec, quadratic_twist, eta, L) return L From 9005db2ddeaacab075c6f8d44ddd5cf427f7af68 Mon Sep 17 00:00:00 2001 From: Chase Meadors Date: Fri, 23 Jul 2021 00:56:42 -0600 Subject: [PATCH 029/359] Ensure elements of coxeter3 CoxeterGroup are normalized on construction (particularly, after multiplication). --- src/sage/libs/coxeter3/coxeter_group.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/sage/libs/coxeter3/coxeter_group.py b/src/sage/libs/coxeter3/coxeter_group.py index b4118ca9592..9ebb8137ebc 100644 --- a/src/sage/libs/coxeter3/coxeter_group.py +++ b/src/sage/libs/coxeter3/coxeter_group.py @@ -158,7 +158,7 @@ def simple_reflections(self): sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3 sage: s = W.simple_reflections() # optional - coxeter3 sage: s[2]*s[1]*s[2] # optional - coxeter3 - [2, 1, 2] + [1, 2, 1] """ from sage.combinat.family import Family return Family(self.index_set(), lambda i: self.element_class(self, [i])) @@ -422,6 +422,7 @@ def __init__(self, parent, x): """ if not isinstance(x, CoxGroupElement): x = CoxGroupElement(parent._coxgroup, x).reduced() + x = x.normal_form() ElementWrapper.__init__(self, parent, x) def __iter__(self): @@ -446,7 +447,7 @@ def coatoms(self): sage: W = CoxeterGroup(['B', 3], implementation='coxeter3') # optional - coxeter3 sage: w = W([1,2,3]) # optional - coxeter3 sage: w.coatoms() # optional - coxeter3 - [[2, 3], [1, 3], [1, 2]] + [[2, 3], [3, 1], [1, 2]] """ W = self.parent() return [W(w) for w in self.value.coatoms()] @@ -528,6 +529,8 @@ def _mul_(self, y): [] sage: s[1]*s[2]*s[1] # optional - coxeter3 [1, 2, 1] + sage: s[2]*s[1]*s[2] # optional - coxeter3 + [1, 2, 1] """ return self.__class__(self.parent(), self.value * y.value) From dcad52d1d16b8b575a6faee3e6814178cdd367a7 Mon Sep 17 00:00:00 2001 From: Chase Meadors Date: Fri, 23 Jul 2021 00:57:05 -0600 Subject: [PATCH 030/359] Provide direct/efficient implementation of from_reduced_word for coxeter3 CoxeterGroups. --- src/sage/libs/coxeter3/coxeter_group.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/sage/libs/coxeter3/coxeter_group.py b/src/sage/libs/coxeter3/coxeter_group.py index 9ebb8137ebc..d0c13f12a11 100644 --- a/src/sage/libs/coxeter3/coxeter_group.py +++ b/src/sage/libs/coxeter3/coxeter_group.py @@ -165,6 +165,20 @@ def simple_reflections(self): gens = simple_reflections + def from_reduced_word(self, w): + """ + Return an element of ``self`` from its (reduced) word. + + EXAMPLES:: + + sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') + sage: W.from_reduced_word([1, 3]) + [1, 3] + sage: W.from_reduced_word([3, 1]) + [1, 3] + """ + return self.element_class(self, w) + def rank(self): """ Return the rank of this Coxeter group, that is, the number of generators. From edfb6a0a7f3b34363741cd02aab2dde119cbbbc4 Mon Sep 17 00:00:00 2001 From: Kwankyu Lee Date: Wed, 14 Jul 2021 11:13:49 +0900 Subject: [PATCH 031/359] 32200: Add developer manual section on integer return values --- src/doc/en/developer/coding_in_python.rst | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/doc/en/developer/coding_in_python.rst b/src/doc/en/developer/coding_in_python.rst index 1d8b7c1d3bf..f6ee0c9527d 100644 --- a/src/doc/en/developer/coding_in_python.rst +++ b/src/doc/en/developer/coding_in_python.rst @@ -465,6 +465,26 @@ Note that the syntax in ``except`` is to list all the exceptions that are caught as a tuple, followed by an error message. +Integer Return Value +==================== + +Many functions and methods of objects in Sage return an integer, which users +often treat mathematically and may want to explore its number-theoretic +properties such as prime factorization. Hence if a function or method for your +object returns an integer, consider returning Sage integer of type ``Integer`` +rather than Python integer of type ``int``, unless there is a good reason not +to (such as performance or compatibility with Python code). If ``i`` is an +integer of type ``int``, then code for the return statement would be + +.. CODE-BLOCK:: python + + from sage.rings.integer import Integer + return Integer(i) + +Notable definite exceptions to this rule are special methods like ``__hash__``, +``__len__``, and ``__int__``. + + Importing ========= From 5d545019639407e60985c9112ba70685acc1d26c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20Leli=C3=A8vre?= Date: Sat, 24 Jul 2021 17:20:51 +0200 Subject: [PATCH 032/359] 32200: Rephrase section on integer return values --- src/doc/en/developer/coding_in_python.rst | 29 ++++++++++++++--------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/src/doc/en/developer/coding_in_python.rst b/src/doc/en/developer/coding_in_python.rst index f6ee0c9527d..c81d5736eb9 100644 --- a/src/doc/en/developer/coding_in_python.rst +++ b/src/doc/en/developer/coding_in_python.rst @@ -465,24 +465,31 @@ Note that the syntax in ``except`` is to list all the exceptions that are caught as a tuple, followed by an error message. -Integer Return Value -==================== +Integer Return Values +===================== -Many functions and methods of objects in Sage return an integer, which users -often treat mathematically and may want to explore its number-theoretic -properties such as prime factorization. Hence if a function or method for your -object returns an integer, consider returning Sage integer of type ``Integer`` -rather than Python integer of type ``int``, unless there is a good reason not -to (such as performance or compatibility with Python code). If ``i`` is an -integer of type ``int``, then code for the return statement would be +Many functions and methods in Sage return integer values. +Those should usually be returned as Sage integers of class +:class:`Integer ` rather than +as Python integers of class :class:`int`, as users may want +to explore the resulting integers' number-theoretic properties +such as prime factorization. Exceptions should be made when +there are good reasons such as performance or compatibility +with Python code, for instance in methods such as +``__hash__``, ``__len__``, and ``__int__``. + +To return a Python integer ``i`` as a Sage integer, use: .. CODE-BLOCK:: python from sage.rings.integer import Integer return Integer(i) -Notable definite exceptions to this rule are special methods like ``__hash__``, -``__len__``, and ``__int__``. +To return a Sage integer ``i`` as a Python ineger, use: + +.. CODE-BLOCK:: python + + return int(i) Importing From 56202355f5df69bd015014ade3a7a25732138240 Mon Sep 17 00:00:00 2001 From: Christian Wuthrich Date: Sat, 24 Jul 2021 19:26:55 +0100 Subject: [PATCH 033/359] trac 32258: add doctest --- .../schemes/elliptic_curves/padic_lseries.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/sage/schemes/elliptic_curves/padic_lseries.py b/src/sage/schemes/elliptic_curves/padic_lseries.py index 030607b5c72..72250f3ed6b 100644 --- a/src/sage/schemes/elliptic_curves/padic_lseries.py +++ b/src/sage/schemes/elliptic_curves/padic_lseries.py @@ -841,6 +841,20 @@ def series(self, n=2, quadratic_twist=+1, prec=5, eta=0): sage: lp = E.padic_lseries(2) sage: lp.series(6) 2^2 + 2^6 + O(2^7) + (2 + O(2^4))*T + O(2^3)*T^2 + (2^2 + O(2^3))*T^3 + (2 + O(2^2))*T^4 + O(T^5) + + Check that twists by odd Teichmuller charachters are ok (:trac:`32258`):: + + sage: E = EllipticCurve("443c1") + sage: lp = E.padic_lseries(17, implementation="num") + sage: l8 = lp.series(2,eta=8,prec=3) + sage: l8.list()[0] - 1/lp.alpha() + O(17^4) + sage: lp = E.padic_lseries(2, implementation="num") + sage: l1 = lp.series(8,eta=1,prec=3) + sage: l1.list()[0] - 4/lp.alpha()^2 + O(2^9) + + """ n = ZZ(n) if n < 1: @@ -919,7 +933,7 @@ def series(self, n=2, quadratic_twist=+1, prec=5, eta=0): gamma_power = K(1) teich = self.teichmuller(padic_prec) if p == 2: - teich = [0, 1,-1] + teich = [0, 1, -1] gamma = K(5) p_power = 2**(n-2) a_range = 3 From abdade36276e7c5c51fc2a818f599c667f0f1627 Mon Sep 17 00:00:00 2001 From: Alexander Date: Mon, 26 Jul 2021 17:56:57 -0400 Subject: [PATCH 034/359] 31994: return sorted list of preperiodic points --- src/sage/dynamics/arithmetic_dynamics/projective_ds.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py index 0d9f5d2557c..4a8e69a4084 100644 --- a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py +++ b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py @@ -4182,6 +4182,7 @@ def preperiodic_points(self, m, n, **kwds): Z(list(Q)) except TypeError: good_points.append(Q) + good_points.sort() return good_points else: raise NotImplementedError("ring must a number field or finite field") @@ -4526,6 +4527,7 @@ def periodic_points(self, n, minimal=True, formal=False, R=None, algorithm='vari Z(list(Q)) except TypeError: good_points.append(Q) + good_points.sort() return good_points else: raise NotImplementedError("ring must be a number field or finite field") From 79cedf0b33140fe79ec40986b8ba673d1cf8ebfe Mon Sep 17 00:00:00 2001 From: Alexander Date: Tue, 27 Jul 2021 15:48:47 -0400 Subject: [PATCH 035/359] 32199: fixed documentation issues --- .../endPN_automorphism_group.py | 58 +++++++++++-------- .../arithmetic_dynamics/projective_ds.py | 58 ++++++++++++------- 2 files changed, 69 insertions(+), 47 deletions(-) diff --git a/src/sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py b/src/sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py index a6d77e854ac..c6fd4789978 100644 --- a/src/sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py +++ b/src/sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py @@ -1795,12 +1795,19 @@ def conjugating_set_initializer(f, g): Return a conjugation invariant set together with information to reduce the combinatorics of checking all possible conjugations. - This function constructs the conjugation invariant set (``source``) - necessary for the conjugating set algorithm described in [FMV2014]_. - Additionally, it keeps track of multipliers to reduce the combinatorics. + This function constructs the invariant pair (``source``, ``possible_targets``) + necessary for the conjugating set algorithm described in [FMV2014]_. + Let `f` and `g` be dynamical systems on `\mathbb{P}^n`. + An invariant pair is a pair of two sets `U`, `V` such that + `|U| = |V|` and for all `\phi \in PGL` such that `f^\phi = g`, + `\phi(u) \in V` for all `u \in U`. Invariant pairs can be used + to determine all conjugations from `f` to `g`. For details + in the `\mathbb{P}^1` case, see [FMV2014]_. + + Additionally, this function keeps track of multipliers to reduce the combinatorics. This information is then passed to ``conjugating_set_helper`` or ``is_conjugate_helper``, which check all possible conjugations determined - by the conjugation invariant set. + by the invariant pair. Do not call this function directly, instead use ``f.conjugating_set(g)``. @@ -2020,10 +2027,17 @@ def conjugating_set_initializer(f, g): def greedy_independence_check(P, repeated_mult, point_to_mult): r""" - Return a conjugation invariant set together with information + Return an invariant pair together with information to reduce the combinatorics of checking all possible conjugations. - This function may sometimes fail to find the conjugation invariant + Let `f` and `g` be dynamical systems on `\mathbb{P}^n`. + An invariant pair is a pair of two sets `U`, `V` such that + `|U| = |V|` and for all `\phi \in PGL` such that `f^\phi = g`, + `\phi(u) \in V` for all `u \in U`. Invariant pairs can be used + to determine all conjugations from `f` to `g`. For details + in the `\mathbb{P}^1` case, see [FMV2014]_. + + This function may sometimes fail to find the invariant pair set even though one exists. It is useful, however, as it is fast and returns a set which usually minimizes the combinatorics of checking all conjugations. @@ -2049,13 +2063,13 @@ def greedy_independence_check(P, repeated_mult, point_to_mult): Otherwise, a tuple of the form (``source``, ``corresponding``) is returned. - - ``source`` -- a conjugation invariant set of `n+2` points of the domain of `f`, - of which no `n+1` are linearly dependent. Used to specify a possible conjugation - from `f` to `g`. + - ``source`` -- the set `U` of the conjugation invariant pair. A set of `n+2` points + of the domain of `f`, of which no `n+1` are linearly dependent. - ``corresponding`` -- a list of tuples of the form ((multiplier, level), repeat) where the (multiplier, level) pair is the multiplier of a point in ``source`` and repeat - specifies how many points in source have that (multiplier, level) pair + specifies how many points in source have that (multiplier, level) pair. This + information specifies the set `V` of the invariant pair. EXAMPLES:: @@ -2092,18 +2106,17 @@ def conjugating_set_helper(f, g, num_cpus, source, possible_targets): Return the set of elements in PGL over the base ring that conjugates ``f`` to ``g``. - This function takes as input the conjugation invariant set + This function takes as input the invariant pair and multiplier data from ``conjugating_set_initializer``. - Do not call this function directly, instead do ``f.conjugate_set(g)``. + Do not call this function directly, instead use ``f.conjugate_set(g)``. INPUT: - ``f`` -- a rational function of degree at least 2, and the same degree as ``g`` - - ``g`` -- a rational function of the same - degree as ``f`` + - ``g`` -- a rational function of the same degree as ``f`` - ``num_cpus`` -- the number of threads to run in parallel @@ -2114,9 +2127,7 @@ def conjugating_set_helper(f, g, num_cpus, source, possible_targets): is a list of ``points`` which are possible targets for point(s) in ``source``. ``repeated`` specifies how many points in ``source`` have points in ``points`` as their possible target. - OUTPUT: - - a list of elements of PGL which conjugate ``f`` to ``g``. + OUTPUT: a list of elements of PGL which conjugate ``f`` to ``g``. EXAMPLES:: @@ -2239,18 +2250,17 @@ def is_conjugate_helper(f, g, num_cpus, source, possible_targets): r""" Return if ``f`` is conjugate to ``g``. - This function takes as input the conjugation invariant set + This function takes as input the invariant pair and multiplier data from ``conjugating_set_initializer``. - Do not call this function directly, instead do ``f.is_conjugate(g)``. + Do not call this function directly, instead use ``f.is_conjugate(g)``. INPUT: - ``f`` -- a rational function of degree at least 2, and the same degree as ``g`` - - ``g`` -- a rational function of the same - degree as ``f`` + - ``g`` -- a rational function of the same degree as ``f`` - ``num_cpus`` -- the number of threads to run in parallel @@ -2261,9 +2271,7 @@ def is_conjugate_helper(f, g, num_cpus, source, possible_targets): is a list of ``points`` which are possible targets for point(s) in ``source``. ``repeated`` specifies how many points in ``source`` have points in ``points`` as their possible target. - OUTPUT: - - ``True`` if ``f`` is conjugate to ``g``, ``False`` otherwise. + OUTPUT: ``True`` if ``f`` is conjugate to ``g``, ``False`` otherwise. EXAMPLES:: @@ -2375,4 +2383,4 @@ def find_conjugations_arrangement(tuples): break else: is_conj = find_conjugations_subset(product(*subset_iterators)) - return is_conj \ No newline at end of file + return is_conj diff --git a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py index 91402c18da3..96f0f4f4fc8 100644 --- a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py +++ b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py @@ -3250,7 +3250,7 @@ def automorphism_group(self, **kwds): The following keywords are used in most cases: - - ``num_cpus`` -- (default: 1) the number of threads to use. Setting to a + - ``num_cpus`` -- (default: 2) the number of threads to use. Setting to a larger number can greatly speed up this function. The following keywords are used only when the dimension of the domain is 1 and @@ -3285,14 +3285,14 @@ def automorphism_group(self, **kwds): EXAMPLES:: - sage: R. = ProjectiveSpace(QQ,1) + sage: R. = ProjectiveSpace(QQ, 1) sage: f = DynamicalSystem_projective([x^2-y^2, x*y]) sage: f.automorphism_group(return_functions=True) [x, -x] :: - sage: R. = ProjectiveSpace(QQ,1) + sage: R. = ProjectiveSpace(QQ, 1) sage: f = DynamicalSystem_projective([x^2 + 5*x*y + 5*y^2, 5*x^2 + 5*x*y + y^2]) sage: f.automorphism_group() [ @@ -3302,14 +3302,21 @@ def automorphism_group(self, **kwds): :: - sage: R. = ProjectiveSpace(QQ,1) + sage: P. = ProjectiveSpace(QQ, 2) + sage: f = DynamicalSystem([x^3, y^3, z^3]) + sage: len(f.automorphism_group()) + 24 + + :: + + sage: R. = ProjectiveSpace(QQ, 1) sage: f = DynamicalSystem_projective([x^2-2*x*y-2*y^2, -2*x^2-2*x*y+y^2]) sage: f.automorphism_group(return_functions=True) [x, 1/x, -x - 1, -x/(x + 1), (-x - 1)/x, -1/(x + 1)] :: - sage: R. = ProjectiveSpace(QQ,1) + sage: R. = ProjectiveSpace(QQ, 1) sage: f = DynamicalSystem_projective([3*x^2*y - y^3, x^3 - 3*x*y^2]) sage: lst, label = f.automorphism_group(algorithm='CRT', return_functions=True, iso_type=True) sage: sorted(lst), label @@ -3318,7 +3325,7 @@ def automorphism_group(self, **kwds): :: - sage: A. = AffineSpace(QQ,1) + sage: A. = AffineSpace(QQ, 1) sage: f = DynamicalSystem_affine([1/z^3]) sage: F = f.homogenize(1) sage: F.automorphism_group() @@ -3329,7 +3336,7 @@ def automorphism_group(self, **kwds): :: - sage: P. = ProjectiveSpace(QQ,2) + sage: P. = ProjectiveSpace(QQ, 2) sage: f = DynamicalSystem_projective([x**2 + x*z, y**2, z**2]) sage: f.automorphism_group() [ @@ -3353,7 +3360,7 @@ def automorphism_group(self, **kwds): p = kwds.get('starting_prime', 5) return_functions = kwds.get('return_functions', False) iso_type = kwds.get('iso_type', False) - num_cpus = kwds.get('num_cpus', 1) + num_cpus = kwds.get('num_cpus', 2) if self.domain().dimension_relative() != 1: return self.conjugating_set(self, num_cpus) if self.base_ring() != QQ and self.base_ring() != ZZ: @@ -6531,7 +6538,7 @@ def conjugating_set(self, other, R=None, num_cpus=2): EXAMPLES:: - sage: P. = ProjectiveSpace(QQ,1) + sage: P. = ProjectiveSpace(QQ, 1) sage: f = DynamicalSystem_projective([x^2 - 2*y^2, y^2]) sage: m = matrix(QQbar, 2, 2, [-1, 3, 2, 1]) sage: g = f.conjugate(m) @@ -6543,15 +6550,15 @@ def conjugating_set(self, other, R=None, num_cpus=2): Increasing ``num_cpus`` can speed up computation:: - sage: P. = ProjectiveSpace(QQ,3) + sage: P. = ProjectiveSpace(QQ, 3) sage: f = DynamicalSystem_projective([x^2, y^2, z^2, w^2]) - sage: len(f.conjugating_set(f, num_cpus=2)) + sage: len(f.conjugating_set(f, num_cpus=3)) 24 :: sage: K. = QuadraticField(-1) - sage: P. = ProjectiveSpace(K,1) + sage: P. = ProjectiveSpace(K, 1) sage: f = DynamicalSystem_projective([x^2 + y^2, x*y]) sage: m = matrix(K, 2, 2, [1, 1, 2, 1]) sage: g = f.conjugate(m) @@ -6564,7 +6571,7 @@ def conjugating_set(self, other, R=None, num_cpus=2): :: sage: K. = QuadraticField(-1) - sage: P. = ProjectiveSpace(K,1) + sage: P. = ProjectiveSpace(K, 1) sage: D8 = DynamicalSystem_projective([y^3, x^3]) sage: sorted(D8.conjugating_set(D8)) [ @@ -6574,7 +6581,7 @@ def conjugating_set(self, other, R=None, num_cpus=2): :: - sage: P. = ProjectiveSpace(QQ,1) + sage: P. = ProjectiveSpace(QQ, 1) sage: D8 = DynamicalSystem_projective([y^2, x^2]) sage: D8.conjugating_set(D8) Traceback (most recent call last): @@ -6583,7 +6590,7 @@ def conjugating_set(self, other, R=None, num_cpus=2): :: - sage: P. = ProjectiveSpace(GF(7),1) + sage: P. = ProjectiveSpace(GF(7), 1) sage: D6 = DynamicalSystem_projective([y^2, x^2]) sage: D6.conjugating_set(D6) [ @@ -6593,7 +6600,7 @@ def conjugating_set(self, other, R=None, num_cpus=2): :: - sage: P. = ProjectiveSpace(QQ,2) + sage: P. = ProjectiveSpace(QQ, 2) sage: f = DynamicalSystem_projective([x^2 + x*z, y^2, z^2]) sage: f.conjugating_set(f) [ @@ -6623,7 +6630,7 @@ def conjugating_set(self, other, R=None, num_cpus=2): note that only one possible conjugation is returned:: - sage: P. = ProjectiveSpace(GF(11),2) + sage: P. = ProjectiveSpace(GF(11), 2) sage: f = DynamicalSystem_projective([2*x + 12*y, 11*y+2*z, x+z]) sage: m1 = matrix(GF(11), 3, 3, [1,4,1,0,2,1,1,1,1]) sage: g = f.conjugate(m1) @@ -6650,7 +6657,7 @@ def conjugating_set(self, other, R=None, num_cpus=2): Make sure the caching problem is fixed, see #28070 :: sage: K. = QuadraticField(-1) - sage: P. = ProjectiveSpace(QQ,1) + sage: P. = ProjectiveSpace(QQ, 1) sage: f = DynamicalSystem_projective([x^2 - 2*y^2, y^2]) sage: m = matrix(QQ, 2, 2, [-1, 3, 2, 1]) sage: g = f.conjugate(m) @@ -6724,7 +6731,7 @@ def conjugating_set(self, other, R=None, num_cpus=2): if f.conjugate(m_emb) == g: return [m_emb] else: #finite field case - #always comes from prime field so an coerce + #always comes from prime field so can coerce m = matrix(base, M, M, [base(u.as_finite_field_element()[1]) for t in list(m) for u in t]) return [m] #not similar @@ -6740,7 +6747,7 @@ def conjugating_set(self, other, R=None, num_cpus=2): source, possible_targets = tup return conjugating_set_helper(f, g, num_cpus, source, possible_targets) - def is_conjugate(self, other, R=None, num_cpus=1): + def is_conjugate(self, other, R=None, num_cpus=2): r""" Return whether two dynamical systems are conjugate over their base ring (by default) or over the ring `R` entered as an @@ -6761,7 +6768,7 @@ def is_conjugate(self, other, R=None, num_cpus=1): - ``R`` -- a field or embedding - - ``num_cpus`` -- (default: 1) the number of threads to run in parallel. + - ``num_cpus`` -- (default: 2) the number of threads to run in parallel. Increasing ``num_cpus`` can potentially greatly speed up this function. OUTPUT: boolean @@ -6773,7 +6780,7 @@ def is_conjugate(self, other, R=None, num_cpus=1): - Implemented by Rebecca Lauren Miller as part of GSOC 2016. - - Algorithmic improvement by Alexander Galarraga as part of GSOC 2016. + - Algorithmic improvement by Alexander Galarraga as part of GSOC 2021. EXAMPLES:: @@ -7889,6 +7896,13 @@ def automorphism_group(self, **kwds): [1 0] [0 1] ]] + + :: + + sage: R. = ProjectiveSpace(GF(5), 2) + sage: f = DynamicalSystem_projective([x^3 + x*z^2, y^3 + y*z^2, z^3]) + sage: all([f.conjugate(m) == f for m in f.automorphism_group()]) + True """ absolute = kwds.get('absolute', False) iso_type = kwds.get('iso_type', False) From 6e4139efa630e66aabf5fcf8301032b573d61a36 Mon Sep 17 00:00:00 2001 From: Alexander Date: Thu, 29 Jul 2021 10:59:07 -0400 Subject: [PATCH 036/359] 32199: fixed call to is_linearly_independent --- .../arithmetic_dynamics/endPN_automorphism_group.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py b/src/sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py index c6fd4789978..a089419754b 100644 --- a/src/sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py +++ b/src/sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py @@ -2086,7 +2086,11 @@ def greedy_independence_check(P, repeated_mult, point_to_mult): for r in sorted(repeated_mult.keys()): for point_lst in repeated_mult[r]: for point in point_lst: - if P.is_linearly_independent(source + [point], n+1): + if len(source) == n+1: + independent = P.is_linearly_independent(source + [point], n+1) + else: + independent = P.is_linearly_independent(source + [point]) + if independent: source.append(point) mult = point_to_mult[point] # if another point with this multiplier and level pair is in S From 231862dc186b620cf0f00f7397cf0141b455d682 Mon Sep 17 00:00:00 2001 From: Lorenz Panny Date: Fri, 30 Jul 2021 22:53:49 +0800 Subject: [PATCH 037/359] make gcd() work on generators --- src/sage/arith/misc.py | 2 +- src/sage/rings/integer.pyx | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/sage/arith/misc.py b/src/sage/arith/misc.py index 83f3a957d17..e80488dcb93 100644 --- a/src/sage/arith/misc.py +++ b/src/sage/arith/misc.py @@ -1785,7 +1785,7 @@ def gcd(a, b=None, **kwargs): from sage.structure.sequence import Sequence seq = Sequence(py_scalar_to_element(el) for el in a) if seq.universe() is ZZ: - return GCD_list(a) + return GCD_list(seq) else: return __GCD_sequence(seq, **kwargs) diff --git a/src/sage/rings/integer.pyx b/src/sage/rings/integer.pyx index 14eec0c8c3b..80228f53d92 100644 --- a/src/sage/rings/integer.pyx +++ b/src/sage/rings/integer.pyx @@ -7148,13 +7148,14 @@ def GCD_list(v): sage: GCD_list([]) 0 """ + if not isinstance(v, list): + v = list(v) + cdef int i, n = len(v) cdef Integer z = PY_NEW(Integer) for i from 0 <= i < n: if not isinstance(v[i], Integer): - if not isinstance(v, list): - v = list(v) v[i] = Integer(v[i]) if n == 0: From 13de775ac290b351d1f5dfb934a45833a1c05ed1 Mon Sep 17 00:00:00 2001 From: EnderWannabe Date: Mon, 2 Aug 2021 19:41:10 -0400 Subject: [PATCH 038/359] 32328: initial commit --- .../arithmetic_dynamics/projective_ds.py | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py index 7b53546f1ee..85f9c2b09c0 100644 --- a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py +++ b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py @@ -5419,6 +5419,53 @@ def _is_preperiodic(self, P, err=0.1, return_period=False): else: return False + def post_critical_set(self): + r""" + Return the post critical set of this dynamical system. + + Raises an error if this dynamical system is not post-critically finite. + + Note that the orbit of all critical points is found, even if the + critical points are defined in an extension of the base ring of + this dynamical system. + + OUTPUT: The combined orbits of the critical points, as a set + + EXAMPLES:: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: f = DynamicalSystem([x^3 - 3/2* x*y^2, y^3]) + sage: f.post_critical_set() + [(-1/2*a : 1), (1/2*a : 1), (1 : 0)] + + :: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: f = DynamicalSystem([3*x^3 - 9/2* x^2*y+y^3, y^3]) + sage: f.post_critical_set() + [(0 : 1), (1 : 1), (-1/2 : 1), (1 : 0)] + + :: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: f = DynamicalSystem([-4*y^2, 9*x^2 - 12*x*y]) + sage: f.post_critical_set() + [(2/3 : 1), (1 : 1), (4/3 : 1), (1 : 0), (0 : 1)] + """ + if not is_ProjectiveSpace(self.domain()): + raise ValueError('must not be a dynamical system on a subscheme') + if self.domain().dimension_relative() != 1: + raise ValueError('must be defined on projective space of dimension 1') + f = self.change_ring(self.field_of_definition_critical()) + critical_points = f.critical_points() + post_critical_list = [] + for point in critical_points: + next_point = point + while not(next_point in post_critical_list): + post_critical_list.append(next_point) + next_point = f(next_point) + return post_critical_list + class DynamicalSystem_projective_field(DynamicalSystem_projective, SchemeMorphism_polynomial_projective_space_field): From f8e7d19ec2ae40d2cd46ea51aef18b17c12f6d15 Mon Sep 17 00:00:00 2001 From: bhutz Date: Tue, 3 Aug 2021 07:53:56 -0500 Subject: [PATCH 039/359] 32155: remove unused import --- src/sage/schemes/projective/projective_space.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/sage/schemes/projective/projective_space.py b/src/sage/schemes/projective/projective_space.py index 1d43737a98d..2d6f327c4ca 100644 --- a/src/sage/schemes/projective/projective_space.py +++ b/src/sage/schemes/projective/projective_space.py @@ -79,7 +79,6 @@ # http://www.gnu.org/licenses/ # **************************************************************************** -from typing import Type from sage.arith.all import gcd, binomial, srange from sage.rings.all import (PolynomialRing, Integer, From 2e320b59aa963bd76d3e03f484fbb4aa235c890f Mon Sep 17 00:00:00 2001 From: EnderWannabe Date: Tue, 3 Aug 2021 12:47:02 -0400 Subject: [PATCH 040/359] 32328: added examples and fixed errors --- .../arithmetic_dynamics/projective_ds.py | 63 ++++++++++++++----- 1 file changed, 49 insertions(+), 14 deletions(-) diff --git a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py index 85f9c2b09c0..f5da0eabb30 100644 --- a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py +++ b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py @@ -5419,48 +5419,83 @@ def _is_preperiodic(self, P, err=0.1, return_period=False): else: return False - def post_critical_set(self): + def postcritical_set(self, check=True): r""" - Return the post critical set of this dynamical system. + Return the postcritical set of this dynamical system. - Raises an error if this dynamical system is not post-critically finite. + Raises an error if this dynamical system is not postcritically finite. + + The postcritical set is union of points which are in the forward orbits + of the critical points. In other words, the set of points `Q` such that + `f^n(P) = Q` for some positive integer `n` and critical point `P`, where + `f` is this map. Note that the orbit of all critical points is found, even if the critical points are defined in an extension of the base ring of - this dynamical system. + this dynamical system. We extend to the field defined by + ``f.field_of_definition_critical()``, where ``f`` is this map. + + INPUT: - OUTPUT: The combined orbits of the critical points, as a set + - ``check`` -- (default: ``True``) boolean; whether to check + if this dynamical system is postcritically finite or not. + + OUTPUT: The set of postcritical points. EXAMPLES:: sage: P. = ProjectiveSpace(QQ, 1) sage: f = DynamicalSystem([x^3 - 3/2* x*y^2, y^3]) - sage: f.post_critical_set() - [(-1/2*a : 1), (1/2*a : 1), (1 : 0)] + sage: f.postcritical_set() + [(1/2*a : 1), (-1/2*a : 1), (1 : 0)] :: sage: P. = ProjectiveSpace(QQ, 1) sage: f = DynamicalSystem([3*x^3 - 9/2* x^2*y+y^3, y^3]) - sage: f.post_critical_set() - [(0 : 1), (1 : 1), (-1/2 : 1), (1 : 0)] + sage: f.postcritical_set(check=False) + [(1 : 1), (-1/2 : 1), (1 : 0)] :: sage: P. = ProjectiveSpace(QQ, 1) sage: f = DynamicalSystem([-4*y^2, 9*x^2 - 12*x*y]) - sage: f.post_critical_set() - [(2/3 : 1), (1 : 1), (4/3 : 1), (1 : 0), (0 : 1)] + sage: f.postcritical_set() + [(1 : 1), (4/3 : 1), (1 : 0), (0 : 1)] + + :: + + sage: K. = QuadraticField(2) + sage: P. = ProjectiveSpace(K,1) + sage: f = DynamicalSystem([x^2 + (-2)*y^2, y^2]) + sage: m = matrix(K, 2, 2, [v, 1, 0, 1]) + sage: g = f.conjugate(m) + sage: g.postcritical_set() + [(-3/2*a : 1), (1/2*a : 1), (1 : 0)] + + :: + + sage: F. = FiniteField(9) + sage: P. = ProjectiveSpace(F, 1) + sage: f = DynamicalSystem([x^2 + (-2)*y^2, y^2]) + sage: m = matrix(F, 2, 2, [z, 1, 0, 1]) + sage: g = f.conjugate(m) + sage: g.postcritical_set() + [(1 : 0), (0 : 1), (a + 2 : 1)] """ if not is_ProjectiveSpace(self.domain()): - raise ValueError('must not be a dynamical system on a subscheme') + raise ValueError('must be a dynamical system on projective space') if self.domain().dimension_relative() != 1: raise ValueError('must be defined on projective space of dimension 1') - f = self.change_ring(self.field_of_definition_critical()) + if check: + if not self.is_postcritically_finite(): + raise ValueError('map must be postcritically finite') + new_base_ring = self.field_of_definition_critical(return_embedding=True)[1] + f = self.change_ring(new_base_ring) critical_points = f.critical_points() post_critical_list = [] for point in critical_points: - next_point = point + next_point = f(point) while not(next_point in post_critical_list): post_critical_list.append(next_point) next_point = f(next_point) From eb218c1ee74abe7aeafaba8b6077246c33d85ca1 Mon Sep 17 00:00:00 2001 From: EnderWannabe Date: Wed, 4 Aug 2021 12:10:21 -0700 Subject: [PATCH 041/359] 32199: removed unused imports attempted fix for example --- src/sage/dynamics/arithmetic_dynamics/projective_ds.py | 3 --- src/sage/schemes/projective/projective_space.py | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py index f39c31b98f2..8fcc4e9f0d4 100644 --- a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py +++ b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py @@ -104,9 +104,6 @@ class initialization directly. from sage.parallel.ncpus import ncpus from sage.parallel.use_fork import p_iter_fork from sage.dynamics.arithmetic_dynamics.projective_ds_helper import (_fast_possible_periods,_all_periodic_points) -from sage.sets.set import Set -from sage.combinat.permutation import Arrangements -from sage.combinat.subset import Subsets from sage.symbolic.ring import SR from itertools import count, product from .endPN_automorphism_group import ( diff --git a/src/sage/schemes/projective/projective_space.py b/src/sage/schemes/projective/projective_space.py index 2d6f327c4ca..95a4cfcb058 100644 --- a/src/sage/schemes/projective/projective_space.py +++ b/src/sage/schemes/projective/projective_space.py @@ -1728,7 +1728,7 @@ def is_linearly_independent(self, points, n=None): EXAMPLES:: - sage: P. = ProjectiveSpace(ZZ, 2) + sage: P. = ProjectiveSpace(QQ, 2) sage: points = [P((1, 0, 1)), P((1, 2, 1)), P((1, 3, 4))] sage: P.is_linearly_independent(points) True From 0f73fcd3009b174d88c6dc67a7a4e55afeaa6adb Mon Sep 17 00:00:00 2001 From: EnderWannabe Date: Thu, 5 Aug 2021 10:58:44 -0700 Subject: [PATCH 042/359] 32199: changed check in examples --- .../endPN_automorphism_group.py | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py b/src/sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py index a089419754b..e5ef59acf59 100644 --- a/src/sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py +++ b/src/sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py @@ -1831,17 +1831,21 @@ def conjugating_set_initializer(f, g): is a list of ``points`` which are possible targets for point(s) in ``source``. ``repeated`` specifies how many points in ``source`` have points in ``points`` as their possible target. - EXAMPLES:: + EXAMPLES: + + We check that ``source`` has no `n+1` linearly dependent points, and that + ``possible_targets`` tracks multiplier information:: sage: P. = ProjectiveSpace(QQ, 2) sage: f = DynamicalSystem([(8*x^7 - 35*x^4*y^3 - 35*x^4*z^3 - 7*x*y^6 - 140*x*y^3*z^3 \ - 7*x*z^6), (-7*x^6*y - 35*x^3*y^4 - 140*x^3*y*z^3 + 8*y^7 - 35*y^4*z^3 \ - 7*y*z^6), -7*x^6*z - 140*x^3*y^3*z - 35*x^3*z^4 - 7*y^6*z - 35*y^3*z^4 + 8*z^7]) sage: from sage.dynamics.arithmetic_dynamics.endPN_automorphism_group import conjugating_set_initializer - sage: conjugating_set_initializer(f, f) - ([(-1 : 0 : 1), (0 : -1 : 1), (0 : 1 : 0), (1 : 0 : 0)], - [[[(-1 : 0 : 1), (0 : -1 : 1), (-1 : 1 : 0)], 2], - [[(0 : 1 : 0), (1 : 0 : 0), (1 : 1 : 1), (0 : 0 : 1)], 2]]) + sage: source, possible_targets = conjugating_set_initializer(f, f) + sage: P.is_linearly_independent(source, 3) + True + sage: f.multiplier(possible_targets[0][0][0], 1) == f.multiplier(source[0], 1) + True """ n = f.domain().dimension_relative() @@ -2140,10 +2144,10 @@ def conjugating_set_helper(f, g, num_cpus, source, possible_targets): sage: source = [P((1, 1)), P((0, 1)), P((1, 0))] sage: possible_targets = [[[P((1, 1))], 1], [[P((0, 1)), P((1, 0))], 2]] sage: from sage.dynamics.arithmetic_dynamics.endPN_automorphism_group import conjugating_set_helper - sage: conjugating_set_helper(f, f, 2, source, possible_targets) + sage: sorted(conjugating_set_helper(f, f, 2, source, possible_targets)) [ - [1 0] [0 1] - [0 1], [1 0] + [0 1] [1 0] + [1 0], [0 1] ] """ Conj = [] From e6a3c5dfeca8e37ce61efe25dbb3473475ba912c Mon Sep 17 00:00:00 2001 From: Lorenz Panny Date: Fri, 6 Aug 2021 19:54:07 +0800 Subject: [PATCH 043/359] undo earlier list cast in GCD_list --- src/sage/rings/integer.pyx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/sage/rings/integer.pyx b/src/sage/rings/integer.pyx index 80228f53d92..14eec0c8c3b 100644 --- a/src/sage/rings/integer.pyx +++ b/src/sage/rings/integer.pyx @@ -7148,14 +7148,13 @@ def GCD_list(v): sage: GCD_list([]) 0 """ - if not isinstance(v, list): - v = list(v) - cdef int i, n = len(v) cdef Integer z = PY_NEW(Integer) for i from 0 <= i < n: if not isinstance(v[i], Integer): + if not isinstance(v, list): + v = list(v) v[i] = Integer(v[i]) if n == 0: From 05cfb4ef31bfe7542027498ffd1f6a76ba5f22ba Mon Sep 17 00:00:00 2001 From: Chase Meadors Date: Tue, 13 Jul 2021 01:15:46 -0600 Subject: [PATCH 044/359] Draft implementation of fast Cp basis for IwahoriHeckeAlgebra --- src/sage/algebras/iwahori_hecke_algebra.py | 106 +++++++++++++++++++++ 1 file changed, 106 insertions(+) diff --git a/src/sage/algebras/iwahori_hecke_algebra.py b/src/sage/algebras/iwahori_hecke_algebra.py index ae50b39a3e0..ab86c1d56a1 100644 --- a/src/sage/algebras/iwahori_hecke_algebra.py +++ b/src/sage/algebras/iwahori_hecke_algebra.py @@ -32,6 +32,8 @@ from sage.combinat.root_system.coxeter_group import CoxeterGroup from sage.combinat.family import Family from sage.combinat.free_module import CombinatorialFreeModule +from sage.algebras.free_algebra import FreeAlgebra +from sage.libs.coxeter3.coxeter_group import CoxeterGroup as Coxeter3Group def normalized_laurent_polynomial(R, p): @@ -1948,6 +1950,110 @@ def hash_involution_on_basis(self, w): C_prime = Cp + class Cp_native(_Basis): + _basis_name = 'Cp_native' + + def __init__(self, algebra, prefix='Cp'): + if not isinstance(algebra._W, Coxeter3Group): + raise ValueError('Algebra must be initialized with a coxeter3-implemented Coxeter group to use the Cp_native basis.') + + super(IwahoriHeckeAlgebra.Cp_native, self).__init__(algebra, prefix) + + self._W = algebra._W + self.gen_algebra = FreeAlgebra(algebra.base_ring(), ['g' + str(i) for i in self.index_set()]) + self.delta = algebra.q1() - algebra.q2() + + def _product_with_generator_on_basis(self, side, s, w): + # C_s * C_w = (v + 1/v) * C_w if s is a left descent, otherwise: + # Left: C_s * C_w = C_{sw} + \sum_{sx < x < w} mu(x, w) C_x + # Right: C_w * C_s = C_{ws} + \sum_{xs < x < w} mu(x, w) C_x + + if w.has_descent(s, side=side): + return self.delta * self.monomial(w) + else: + element = self(0) + between = self._W.bruhat_interval([], w) + for x in between: + x_elt = self._W(x) + if x_elt.has_descent(s, side=side): + element += x.mu_coefficient(w) * self.monomial(x_elt) + + # Doing self._W([s]) * w may not ensure that the word is is normal form + # Since W's element constructor does ensure that, use this method. + longer_word = self._W([s] + list(w) if side == 'left' else list(w) + [s]) + return self.monomial(longer_word) + element + + def _product_with_generator(self, side, s, x): + return self.linear_combination((self._product_with_generator_on_basis(side, s, w), coeff) for (w, coeff) in x) + + def _decompose_into_generators(self, w): + r""" + Returns an element of self.gen_algebra, a free algebra over {g_1, ..., g_n} + describing how to write 'word' in terms of the generators + """ + gs = self.gen_algebra.gens() + if len(w) == 0: + return self.gen_algebra(1) + if len(w) == 1: + return gs[w[0]] + + s = w[0] + w1 = w[1:] + + # We have C_w = C_s * C_{w1} + # Use the reverse of the left-multiplication by generator rule: + # We know s is not a left descent, so + # C_w = C_s * C_{w1} - \sum_{sy < y < w1} C_y + + # The sum from the above + rest = self(0) + between = self._W.bruhat_interval([], w1) + for x in between: + x_elt = self._W(x) + if x_elt.has_left_descent(s): + rest += self.base_ring()(x.mu_coefficient(w1)) * self.monomial(x_elt) + + # In the expression above, we need to recurse and decompose C_{w1} into generators, + # and then go through the terms of the sum 'rest' and decompose those C_y's into generators + alg_element = gs[s] * self._decompose_into_generators(w1) + for (v, coeff) in rest: + # We're subtracting 'rest' + alg_element -= coeff * self._decompose_into_generators(v) + + return alg_element + + def product_on_basis(self, w1, w2): + # Otherwise, decompose the first word into generators + # (as expressed as an element of the FreeAlgebra over 'generator' variables g1, ..., gn) + if len(w1) <= len(w2): + side = 'left' + gens = self._decompose_into_generators(w1) + other_element = self.monomial(w2) + else: + side = 'right' + gens = self._decompose_into_generators(w2) + other_element = self.monomial(w1) + + # Now, build everything back up, continually multiplying on the left by a single generator + # Multiply gens by other_element, doing "manual distribution" + + result = self(0) + for (p, coeff) in gens: + # p is a product of generators, i.e. 2*g1*g2*g1; multiply it by other_element + # Build summand multiplicatively, going through variables and thier powers in p + # If gens are on the right, we need to start at the left end of p, and vice versa. + summand = coeff * other_element + p_list = list(p) if side == 'right' else list(p)[::-1] + for (g, power) in p_list: + s = self.gen_algebra.gens().index(g) + # Multiply this_element on the apppropriate side by the generator this variable g corresponds to + for i in range(power): + summand = self._product_with_generator(side, s, summand) + + result += summand + + return result + class C(_KLHeckeBasis): r""" The Kazhdan-Lusztig `C`-basis of Iwahori-Hecke algebra. From 37333ba11ace9c857242f2e9d079d1031d01c506 Mon Sep 17 00:00:00 2001 From: Tianyuan Xu Date: Mon, 19 Jul 2021 18:40:58 -0600 Subject: [PATCH 045/359] first doc change for Cp_Coxeter3 class --- src/sage/algebras/iwahori_hecke_algebra.py | 131 +++++++++++++++++++-- 1 file changed, 124 insertions(+), 7 deletions(-) diff --git a/src/sage/algebras/iwahori_hecke_algebra.py b/src/sage/algebras/iwahori_hecke_algebra.py index ab86c1d56a1..16b14181cc4 100644 --- a/src/sage/algebras/iwahori_hecke_algebra.py +++ b/src/sage/algebras/iwahori_hecke_algebra.py @@ -8,6 +8,11 @@ - Brant Jones, Travis Scrimshaw, Andrew Mathas (2013): Moved into the category framework and implemented the Kazhdan-Lusztig `C` and `C^{\prime}` bases + +- Chase Meadors, Tianyuan Xu (2021): + Implemented direct computation of products in the + `C^{\prime}` basis using du Cloux's Coxeter3 package + """ # **************************************************************************** # Copyright (C) 2013 Brant Jones @@ -1950,23 +1955,120 @@ def hash_involution_on_basis(self, w): C_prime = Cp - class Cp_native(_Basis): - _basis_name = 'Cp_native' + class Cp_Coxeter3(_Basis): + r""" + Directly compute products in the `C^{\prime}`-basis by using du Cloux's Coxeter3 package. + + [State assumptions] normalization/coxeter3 implementation + + Expanding products of the form `C^{\prime}_x \cdot C^{\prime}_y` in the `C^{\prime}`-basis is useful for + computing Kazhdan-Lusztig cells of Coxeter systems and the corresponding cell modules of Iwahori-Hecke + algebras. Such expansion is controlled by the following formula (and the analogous formula for + `C^{\prime}_s \cdot C^{\prime}_w`) under both the "standard" and the "normalized" presentations of the + Iwahori-Hecke algebra, where the quadratic relation is `(T_s-q^2)(T_s+1)=0` and `(T_s-q)(T_s+q^-1)=0` for + each generator `s`, respectively. + + .. MATH:: + C^{\prime}_s \cdot C^{\prime}_w = + \begin{cases} + (q+q^-1)C^{\prime}_{w}, & \text{if } \ell(sw) = \ell(w)-1,\\ + C^{\prime}_{sw}+\sum_{v\leq w, sv \leq v} \mu(v,w)C^{\prime}_v, & \text{if } \ell(sw) = \ell(w)+1. + \end{cases} + + where `\leq` is the Bruhat order on the underlying Coxeter group and `\mu(v,w)` is the "leading coefficient + of Kazhdan-Lusztig polynomials"; see [KL1979]_ and [Lus2014]_ for more details. + + The emphasis of this class is to compute products in the `C^{\prime}`-basis directly, by using the above + formula and calling the necessary `\mu`-coefficients from Sage's implementation of Fokko du Cloux's + Coxeter3 package. This methods computes the products faster than the _Basis.product_on_basis method on Line + 1298, which needs to convert the `C^{\prime}`-basis to the `T`-basis, calculate the product in the + `T`-basis, and convert the results back to the `C^{\prime}`-basis. For example, the product + `C^{\prime}_{32345} * C^{\prime}_{23}` in the Hecke algebra of type 'B_9' takes more than 30 seconds with + the latter method but is instant using this class. + + .. TODO:: + Use the analog of the displayed formula to implement `C^{\prime}`-products in the multi-parameter + Iwahori-Hecke algebra; see Section 6 of [Lus2013]_. + + EXAMPLES:: + + sage: R = LaurentPolynomialRing(QQ, 'q') + [A3 examples with warnings caused by wrong presentation or implementation...] + + Create the Hecke algebra of type 'A3' and label the `C^{\prime}`-basis by `B`: + + sage: H = IwahoriHeckeAlgebra('A3',implementation = 'coxeter3') + sage: B = H.Cp_Coxeter3() [careful about printing: B or Cp] + + Product of the form `B_s \cdot B_y` where `s` is a generator are computed by the earlier formula:: + + sage: B[1] * B[1] + (q^-1+q) * B[1] + sage: B[1] * B[2] + B[1,2] + sage: B[1] * B[2,1] + B[1,2,1] + B[1] + sage: B[1] * B[2,1,3] + B[1,2,3,1] + B[3,1] + sage: B[2] * B[1,3,2,1,3] + B[1,2,3,1,2,1] + Cp[2,3,2,1] + Cp[1,2,3,1] + + + More generally, we can compute products of the form 'B_x \cdot B_y` for general `x, y`:: + + sage: B[1,2,1] * B[3,1] + (q^-1+q)*B[1,2,3,1] + sage: B[1,2,1] * B[3,1,2] (q^-1+q)*B[1,2,3,1,2] + (q^-1+q)*B[1,2,1] + + [More examples: B9 examples; showcase labelling, compare speed with the indirect method ] + + + .. NOTE:: + + The products `B_x \cdot B_y` are computed as follows: if `\ell(x) \leq \ell(y)`, then we first + decompose `B_x` into a linear combination of products of generators `B_s (s\in S)`, then multiplies + that linear combination onto `B_y`; otherwise we decompose `B_y` and multiply the result onto + `B_x`. For example, in the computation of `B[1,2,1] * B[3,1,2]` in type `A3`, the left term + `B[1,2,1]` is first (essentially) decomposed into the linear combination `B[1]*B[2]*B[1] - B[1]` + behind the scenes. The decomposition is achieved via the [_decompose_into_generators function], + which in turn uses an auxiliary free algebra with generators corresponding to the Coxeter + generators. + + .. SEEALSO:: + + :ref: [KL1979]_, [Lus2013]_ + :meth:`sage.somewhere.other_useful_method`, + [coxeter3?] + + TESTS:: + + [show our direct method yields the same results as the indirect method?] + + """ + _basis_name = 'Cp_Coxeter3' def __init__(self, algebra, prefix='Cp'): if not isinstance(algebra._W, Coxeter3Group): - raise ValueError('Algebra must be initialized with a coxeter3-implemented Coxeter group to use the Cp_native basis.') + raise ValueError('Algebra must be initialized with a coxeter3-implemented Coxeter group to use the + Cp_Coxeter3 basis.') super(IwahoriHeckeAlgebra.Cp_native, self).__init__(algebra, prefix) self._W = algebra._W + self.delta = q + q^{-1} #[better way to write this, maybe q as R.gen(0)?] + + #[can we move the following to _decompose_into_generators and avoid it in the manual distribution part + # of product_on_basis? Not a big deal; we could also use the comment below.] + + # the auxiliary free algebra mentioned in ..NOTE:: self.gen_algebra = FreeAlgebra(algebra.base_ring(), ['g' + str(i) for i in self.index_set()]) - self.delta = algebra.q1() - algebra.q2() def _product_with_generator_on_basis(self, side, s, w): - # C_s * C_w = (v + 1/v) * C_w if s is a left descent, otherwise: - # Left: C_s * C_w = C_{sw} + \sum_{sx < x < w} mu(x, w) C_x - # Right: C_w * C_s = C_{ws} + \sum_{xs < x < w} mu(x, w) C_x + r""" + Compute the product of `C^{\prime}_s` and `C^{\prime}_w`, putting `C^{\prime}_s` on the given ``side``. + + [recycle the examples from the class' documentation, or not?] + """ if w.has_descent(s, side=side): return self.delta * self.monomial(w) @@ -1984,13 +2086,20 @@ def _product_with_generator_on_basis(self, side, s, w): return self.monomial(longer_word) + element def _product_with_generator(self, side, s, x): + r""" + Compute the product of `C^{\prime}_s` with any linear combination of `C^{\prime}`-basis elemens. + """ return self.linear_combination((self._product_with_generator_on_basis(side, s, w), coeff) for (w, coeff) in x) def _decompose_into_generators(self, w): r""" Returns an element of self.gen_algebra, a free algebra over {g_1, ..., g_n} describing how to write 'word' in terms of the generators + + [need a good running example or several examples, maybe including how C_121=C_1*C_2*C_1-C_1 in type A; + decomposing from one side is probably enough in the example(s)] """ + gs = self.gen_algebra.gens() if len(w) == 0: return self.gen_algebra(1) @@ -2023,6 +2132,11 @@ def _decompose_into_generators(self, w): return alg_element def product_on_basis(self, w1, w2): + r""" + Return the expansion of `C^{\prime}_{w_1} \cdot C^{\prime}_{w_2}` in the `C^{\prime}`-basis. + + [recycle example from class' doc?] + """ # Otherwise, decompose the first word into generators # (as expressed as an element of the FreeAlgebra over 'generator' variables g1, ..., gn) if len(w1) <= len(w2): @@ -2034,6 +2148,9 @@ def product_on_basis(self, w1, w2): gens = self._decompose_into_generators(w2) other_element = self.monomial(w1) + # [I'm a little confused by 'powers' below; also, should we write a helper function earlier for the 'manual + # distribution'?] + # Now, build everything back up, continually multiplying on the left by a single generator # Multiply gens by other_element, doing "manual distribution" From a5e4808962183a02deaf600cb59dd38232912513 Mon Sep 17 00:00:00 2001 From: Chase Meadors Date: Tue, 20 Jul 2021 16:35:34 -0600 Subject: [PATCH 046/359] Tweak to compile; change error message to python convention --- src/sage/algebras/iwahori_hecke_algebra.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/sage/algebras/iwahori_hecke_algebra.py b/src/sage/algebras/iwahori_hecke_algebra.py index 16b14181cc4..5a6a187bb19 100644 --- a/src/sage/algebras/iwahori_hecke_algebra.py +++ b/src/sage/algebras/iwahori_hecke_algebra.py @@ -2049,13 +2049,12 @@ class Cp_Coxeter3(_Basis): def __init__(self, algebra, prefix='Cp'): if not isinstance(algebra._W, Coxeter3Group): - raise ValueError('Algebra must be initialized with a coxeter3-implemented Coxeter group to use the - Cp_Coxeter3 basis.') + raise ValueError('algebra must be initialized with a coxeter3-implemented Coxeter group to use the Cp_Coxeter3 basis') - super(IwahoriHeckeAlgebra.Cp_native, self).__init__(algebra, prefix) + super(IwahoriHeckeAlgebra.Cp_Coxeter3, self).__init__(algebra, prefix) self._W = algebra._W - self.delta = q + q^{-1} #[better way to write this, maybe q as R.gen(0)?] + self.delta = algebra.q1() + ~algebra.q1() #[better way to write this, maybe q as R.gen(0)?] #[can we move the following to _decompose_into_generators and avoid it in the manual distribution part # of product_on_basis? Not a big deal; we could also use the comment below.] From e137d1c8af7f678bd93dcd0189b2fc1e8e2e02dd Mon Sep 17 00:00:00 2001 From: Chase Meadors Date: Tue, 20 Jul 2021 16:37:22 -0600 Subject: [PATCH 047/359] Implement coercions between Cp_Coxeter3 and the other bases --- src/sage/algebras/iwahori_hecke_algebra.py | 49 ++++++++++++++++++++-- 1 file changed, 45 insertions(+), 4 deletions(-) diff --git a/src/sage/algebras/iwahori_hecke_algebra.py b/src/sage/algebras/iwahori_hecke_algebra.py index 5a6a187bb19..70ca468ddd9 100644 --- a/src/sage/algebras/iwahori_hecke_algebra.py +++ b/src/sage/algebras/iwahori_hecke_algebra.py @@ -1581,6 +1581,11 @@ def to_Cp_basis(self, w): generic_T = H._generic_iwahori_hecke_algebra.T() return generic_T.to_Cp_basis(w).specialize_to(H) + def to_Cp_Coxeter3_basis(self, w): + H = self.realization_of() + generic_T = H._generic_iwahori_hecke_algebra.T() + return generic_T.to_Cp_Coxeter3_basis(w).specialize_to(H) + def bar_on_basis(self, w): """ Return the bar involution of `T_w`, which is `T^{-1}_{w^-1}`. @@ -1932,6 +1937,11 @@ class Cp(_KLHeckeBasis): """ _basis_name = 'Cp' # this is used, for example, by specialize_to and is the default prefix + def to_Cp_Coxeter3_basis(self, w): + A = self.realization_of() + Cp = A.Cp_Coxeter3() + return Cp.monomial(w) + def hash_involution_on_basis(self, w): r""" Return the effect of applying the hash involution to the basis @@ -1955,7 +1965,7 @@ def hash_involution_on_basis(self, w): C_prime = Cp - class Cp_Coxeter3(_Basis): + class Cp_Coxeter3(_KLHeckeBasis): r""" Directly compute products in the `C^{\prime}`-basis by using du Cloux's Coxeter3 package. @@ -2062,6 +2072,19 @@ def __init__(self, algebra, prefix='Cp'): # the auxiliary free algebra mentioned in ..NOTE:: self.gen_algebra = FreeAlgebra(algebra.base_ring(), ['g' + str(i) for i in self.index_set()]) + # Define conversion to the other Cp basis + self.module_morphism(self.to_Cp_basis, codomain=algebra.Cp(), category=self.category() + ).register_as_coercion() + + # ...and from the other Cp basis to the Cp_Coxeter3 basis + Cp = algebra.Cp() + Cp.module_morphism(Cp.to_Cp_Coxeter3_basis, codomain=self, category=self.category()).register_as_coercion() + + def to_Cp_basis(self, w): + A = self.realization_of() + Cp = A.Cp() + return Cp.monomial(w) + def _product_with_generator_on_basis(self, side, s, w): r""" Compute the product of `C^{\prime}_s` and `C^{\prime}_w`, putting `C^{\prime}_s` on the given ``side``. @@ -2739,9 +2762,9 @@ class T(IwahoriHeckeAlgebra.T): r""" The `T`-basis for the generic Iwahori-Hecke algebra. """ - @cached_method - def to_Cp_basis(self, w): + def _to_Cp_basis(self, w, Cp): r""" + TODO: Change this documentation and the two below Return `T_w` as a linear combination of `C^{\prime}`-basis elements. @@ -2765,7 +2788,7 @@ def to_Cp_basis(self, w): + (u^-2*v^5)*Cp[1] + (u^-2*v^5)*Cp[2] + (-u^-3*v^6) """ A = self.realization_of() - Cp = A.Cp() + # Cp = A.Cp() if not use_Cp_Coxeter3 else A.Cp_Coxeter3() if w == A._W.one(): # the identity element of the Coxeter group return Cp.one() @@ -2780,6 +2803,16 @@ def to_Cp_basis(self, w): return result + @cached_method + def to_Cp_basis(self, w): + A = self.realization_of() + return self._to_Cp_basis(w, A.Cp()) + + @cached_method + def to_Cp_Coxeter3_basis(self, w): + A = self.realization_of() + return self._to_Cp_basis(w, A.Cp_Coxeter3()) + @cached_method def to_C_basis(self, w): r""" @@ -2891,6 +2924,14 @@ def key_func(x): C_prime = Cp + class Cp_Coxeter3(IwahoriHeckeAlgebra.Cp_Coxeter3): + @cached_method + def to_T_basis(self, w): + A = self.realization_of() + Cp = A.Cp() + T = A.T() + return T(Cp.monomial(w)) + class C(IwahoriHeckeAlgebra.C): r""" The Kazhdan-Lusztig `C`-basis for the generic Iwahori-Hecke algebra. From d2a237b7d71cee6df1d6397f8cb1103027762354 Mon Sep 17 00:00:00 2001 From: Chase Meadors Date: Tue, 20 Jul 2021 17:47:28 -0600 Subject: [PATCH 048/359] Draft of some better naming/commenting and some documentation --- src/sage/algebras/iwahori_hecke_algebra.py | 51 ++++++++++++++-------- 1 file changed, 33 insertions(+), 18 deletions(-) diff --git a/src/sage/algebras/iwahori_hecke_algebra.py b/src/sage/algebras/iwahori_hecke_algebra.py index 70ca468ddd9..232cca63496 100644 --- a/src/sage/algebras/iwahori_hecke_algebra.py +++ b/src/sage/algebras/iwahori_hecke_algebra.py @@ -2040,9 +2040,9 @@ class Cp_Coxeter3(_KLHeckeBasis): that linear combination onto `B_y`; otherwise we decompose `B_y` and multiply the result onto `B_x`. For example, in the computation of `B[1,2,1] * B[3,1,2]` in type `A3`, the left term `B[1,2,1]` is first (essentially) decomposed into the linear combination `B[1]*B[2]*B[1] - B[1]` - behind the scenes. The decomposition is achieved via the [_decompose_into_generators function], - which in turn uses an auxiliary free algebra with generators corresponding to the Coxeter - generators. + behind the scenes. The decomposition is achieved via the [_decompose_into_generators function], which + takes an element `B_w` and gives an element of the free algebra over \{ B_s \; : \; s \in S \}, whose + image under the canonical homomorphism from the free algebra is precisely `B_w`. .. SEEALSO:: @@ -2065,11 +2065,8 @@ def __init__(self, algebra, prefix='Cp'): self._W = algebra._W self.delta = algebra.q1() + ~algebra.q1() #[better way to write this, maybe q as R.gen(0)?] - - #[can we move the following to _decompose_into_generators and avoid it in the manual distribution part - # of product_on_basis? Not a big deal; we could also use the comment below.] - # the auxiliary free algebra mentioned in ..NOTE:: + # The free algebra over our algebra generators, used in _decompose_into_generators self.gen_algebra = FreeAlgebra(algebra.base_ring(), ['g' + str(i) for i in self.index_set()]) # Define conversion to the other Cp basis @@ -2087,19 +2084,27 @@ def to_Cp_basis(self, w): def _product_with_generator_on_basis(self, side, s, w): r""" - Compute the product of `C^{\prime}_s` and `C^{\prime}_w`, putting `C^{\prime}_s` on the given ``side``. + Compute the product of `C^{\prime}_s` and `C^{\prime}_w`, putting + `C^{\prime}_s` on the given ``side``. + + TODO: Repeat the explanation in Cp_Coxeter3's docstring about + C_s * C_w = { cases ... }? [recycle the examples from the class' documentation, or not?] """ if w.has_descent(s, side=side): + # Descent case, return (q + q^-1) C'_w return self.delta * self.monomial(w) else: + # Additively build the sum \sum_{v \leq w; sv < v} mu(v, w) C'_v element = self(0) between = self._W.bruhat_interval([], w) for x in between: + # Get (coxeter3-implemented) group element corresponding to x x_elt = self._W(x) if x_elt.has_descent(s, side=side): + # Compute mu-coefficient via coxeter3 element += x.mu_coefficient(w) * self.monomial(x_elt) # Doing self._W([s]) * w may not ensure that the word is is normal form @@ -2110,6 +2115,9 @@ def _product_with_generator_on_basis(self, side, s, w): def _product_with_generator(self, side, s, x): r""" Compute the product of `C^{\prime}_s` with any linear combination of `C^{\prime}`-basis elemens. + + TODO: Say more here; maybe that this just does distribution? I think + the one line is fairly self-explanatory. """ return self.linear_combination((self._product_with_generator_on_basis(side, s, w), coeff) for (w, coeff) in x) @@ -2135,20 +2143,23 @@ def _decompose_into_generators(self, w): # Use the reverse of the left-multiplication by generator rule: # We know s is not a left descent, so # C_w = C_s * C_{w1} - \sum_{sy < y < w1} C_y + # TODO: Explain this ^ in the docstring? - # The sum from the above - rest = self(0) + # Additively build the sum just mentioned above + sum_term = self(0) between = self._W.bruhat_interval([], w1) for x in between: + # Get (coxeter3-implemented) group element corresponding to x x_elt = self._W(x) if x_elt.has_left_descent(s): - rest += self.base_ring()(x.mu_coefficient(w1)) * self.monomial(x_elt) + # Compute mu-coefficient via coxeter3 + sum_term += self.base_ring()(x.mu_coefficient(w1)) * self.monomial(x_elt) # In the expression above, we need to recurse and decompose C_{w1} into generators, # and then go through the terms of the sum 'rest' and decompose those C_y's into generators alg_element = gs[s] * self._decompose_into_generators(w1) - for (v, coeff) in rest: - # We're subtracting 'rest' + for (v, coeff) in sum_term: + # We're subtracting 'sum_term' alg_element -= coeff * self._decompose_into_generators(v) return alg_element @@ -2173,20 +2184,24 @@ def product_on_basis(self, w1, w2): # [I'm a little confused by 'powers' below; also, should we write a helper function earlier for the 'manual # distribution'?] - # Now, build everything back up, continually multiplying on the left by a single generator - # Multiply gens by other_element, doing "manual distribution" + # gens is a linear combination of products of the C' generators + # Now, build everything back up, continually multiplying on the left by a single generator at a time result = self(0) + # Iterate through the sum of terms for (p, coeff) in gens: # p is a product of generators, i.e. 2*g1*g2*g1; multiply it by other_element # Build summand multiplicatively, going through variables and thier powers in p # If gens are on the right, we need to start at the left end of p, and vice versa. summand = coeff * other_element p_list = list(p) if side == 'right' else list(p)[::-1] - for (g, power) in p_list: + # Iterate through the product of generators + for (g, exponent) in p_list: s = self.gen_algebra.gens().index(g) - # Multiply this_element on the apppropriate side by the generator this variable g corresponds to - for i in range(power): + # Multiply this_element on the apppropriate side by the generator this variable g corresponds to, + # however many times it is represented in the product (according to the exponent) + for i in range(exponent): + # Perform C'_s * (summand) summand = self._product_with_generator(side, s, summand) result += summand From a000d6cf5fed22b41ab7de8b927c3f6427c3b743 Mon Sep 17 00:00:00 2001 From: Tianyuan Xu Date: Wed, 21 Jul 2021 16:51:27 -0600 Subject: [PATCH 049/359] more docstrings for methods in Cp_Coxeter3 --- src/sage/algebras/iwahori_hecke_algebra.py | 98 +++++++++++++++------- 1 file changed, 66 insertions(+), 32 deletions(-) diff --git a/src/sage/algebras/iwahori_hecke_algebra.py b/src/sage/algebras/iwahori_hecke_algebra.py index 232cca63496..d5c65b9d2b4 100644 --- a/src/sage/algebras/iwahori_hecke_algebra.py +++ b/src/sage/algebras/iwahori_hecke_algebra.py @@ -2036,18 +2036,18 @@ class Cp_Coxeter3(_KLHeckeBasis): .. NOTE:: The products `B_x \cdot B_y` are computed as follows: if `\ell(x) \leq \ell(y)`, then we first - decompose `B_x` into a linear combination of products of generators `B_s (s\in S)`, then multiplies - that linear combination onto `B_y`; otherwise we decompose `B_y` and multiply the result onto - `B_x`. For example, in the computation of `B[1,2,1] * B[3,1,2]` in type `A3`, the left term - `B[1,2,1]` is first (essentially) decomposed into the linear combination `B[1]*B[2]*B[1] - B[1]` - behind the scenes. The decomposition is achieved via the [_decompose_into_generators function], which - takes an element `B_w` and gives an element of the free algebra over \{ B_s \; : \; s \in S \}, whose - image under the canonical homomorphism from the free algebra is precisely `B_w`. + decompose `B_x` into a polynomial in the generators `B_s (s\in S)`, then multiplies that linear + combination onto `B_y`; otherwise we decompose `B_y` and multiply the result onto `B_x`. For + example, in the computation of `B[1,2,1] * B[3,1,2]` in type `A3`, the left term `B[1,2,1]` is + first (essentially) decomposed into the linear combination `B[1]*B[2]*B[1] - B[1]` behind the + scenes. The decomposition is achieved via the [_decompose_into_generators function], which takes an + element `B_w` and gives an element of the free algebra over \{ B_s \; : \; s \in S \}, whose image + under the canonical homomorphism from the free algebra is precisely `B_w`. .. SEEALSO:: :ref: [KL1979]_, [Lus2013]_ - :meth:`sage.somewhere.other_useful_method`, + :meth:`sage.somewhere.other_useful_method`, cell stuff [coxeter3?] TESTS:: @@ -2064,10 +2064,11 @@ def __init__(self, algebra, prefix='Cp'): super(IwahoriHeckeAlgebra.Cp_Coxeter3, self).__init__(algebra, prefix) self._W = algebra._W - self.delta = algebra.q1() + ~algebra.q1() #[better way to write this, maybe q as R.gen(0)?] - - # The free algebra over our algebra generators, used in _decompose_into_generators + self.delta = q + ~q # need the normalizations q_1=q^2, q_2=-1 or q_1=q,q_2=-q^-1 + + # The free algebra over our algebra generators, used to create monomials in these generators in _decompose_into_generators self.gen_algebra = FreeAlgebra(algebra.base_ring(), ['g' + str(i) for i in self.index_set()]) + # Define conversion to the other Cp basis self.module_morphism(self.to_Cp_basis, codomain=algebra.Cp(), category=self.category() @@ -2087,8 +2088,23 @@ def _product_with_generator_on_basis(self, side, s, w): Compute the product of `C^{\prime}_s` and `C^{\prime}_w`, putting `C^{\prime}_s` on the given ``side``. - TODO: Repeat the explanation in Cp_Coxeter3's docstring about - C_s * C_w = { cases ... }? + For each generator `s` and element `x`, the products `C^{\prime}_s \cdot C^{\prime}_w` + is given by the following formulas: + + .. MATH:: + C^{\prime}_s \cdot C^{\prime}_w = + \begin{cases} + (q+q^-1)C^{\prime}_{w}, & \text{if } \ell(sw) = \ell(w)-1,\\ + C^{\prime}_{sw}+\sum_{v\leq w, sv \leq v} \mu(v,w)C^{\prime}_v, & \text{if } \ell(sw) = \ell(w)+1. + \end{cases} + + C^{\prime}_w \cdot C^{\prime}_s = + \begin{cases} + (q+q^-1)C^{\prime}_{w}, & \text{if } \ell(ws) = \ell(w)-1,\\ + C^{\prime}_{ws}+\sum_{v\leq w, vs \leq v} \mu(v,w)C^{\prime}_v, & \text{if } \ell(ws) = \ell(w)+1. + \end{cases} + + where `\leq` is the Bruhat order and the numbers `\mu(v,w)` are the `mu`-coefficients of [Lus2014]_. [recycle the examples from the class' documentation, or not?] """ @@ -2114,21 +2130,47 @@ def _product_with_generator_on_basis(self, side, s, w): def _product_with_generator(self, side, s, x): r""" - Compute the product of `C^{\prime}_s` with any linear combination of `C^{\prime}`-basis elemens. + Compute the product of `C^{\prime}_s` with any linear combination of `C^{\prime}`-basis elements. - TODO: Say more here; maybe that this just does distribution? I think - the one line is fairly self-explanatory. + EXAMPLE:: + + [one example is enough] """ return self.linear_combination((self._product_with_generator_on_basis(side, s, w), coeff) for (w, coeff) in x) def _decompose_into_generators(self, w): r""" - Returns an element of self.gen_algebra, a free algebra over {g_1, ..., g_n} - describing how to write 'word' in terms of the generators + Decompose `C^{\prime}_s` into a polynomial in the KL generators `C^{\prime}_s`. + + The decomposition is obtained recursively, by induction on `\ell(w)`. If `ell(w) < 2` the decomposition + is trivial (see Examples). If `\ell(w) \geq 2`, write `w=su` where `s` is a left descent of `w` so that + `\ell(w) = \ell(u) + 1`, then use the formula that - [need a good running example or several examples, maybe including how C_121=C_1*C_2*C_1-C_1 in type A; - decomposing from one side is probably enough in the example(s)] - """ + .. MATH:: + C^{\prime}_s \cdot C^{\prime}_u = + C^{\prime}_{su}+\sum_{v\leq u, sv \leq v} \mu(v,u)C^{\prime}_v + + to conclude that + + .. MATH:: + C^{\prime}_{w}= C^{\prime}_s \cdot C^{\prime}_u - \sum_{v\leq u, sv \leq v} \mu(v,u)C^{\prime}_v. + + The element `u` and the elements `v` on the right side all have smaller length than `w`, so they can be + obtained by induction. + + + EXAMPLES:: + # A3 + sage: _decompose_into_generators((1,2)) + {[1,2]: 1} # C_{12}=C_1C_2 + sage: _decompose_into_generators((1,2,1)) + {[1,2,1]: 1, [1]:-1} # C_{121}=C_1C_2C_1-C_1=m_121-m_1 + sage: _decompose_into_generators((1,2,3,1,2)) + the suitable dictionary # use "monomial" somehow to get the result natively? + + """ + # Returns an element of self.gen_algebra, a free algebra over {g_1, ..., g_n} + # describing how to write 'word' in terms of the generators gs = self.gen_algebra.gens() if len(w) == 0: @@ -2139,12 +2181,7 @@ def _decompose_into_generators(self, w): s = w[0] w1 = w[1:] - # We have C_w = C_s * C_{w1} - # Use the reverse of the left-multiplication by generator rule: - # We know s is not a left descent, so - # C_w = C_s * C_{w1} - \sum_{sy < y < w1} C_y - # TODO: Explain this ^ in the docstring? - + # Additively build the sum just mentioned above sum_term = self(0) between = self._W.bruhat_interval([], w1) @@ -2156,7 +2193,7 @@ def _decompose_into_generators(self, w): sum_term += self.base_ring()(x.mu_coefficient(w1)) * self.monomial(x_elt) # In the expression above, we need to recurse and decompose C_{w1} into generators, - # and then go through the terms of the sum 'rest' and decompose those C_y's into generators + # and then go through the terms of the sum_term (lower order terms) and decompose those C_y's into generators alg_element = gs[s] * self._decompose_into_generators(w1) for (v, coeff) in sum_term: # We're subtracting 'sum_term' @@ -2181,10 +2218,7 @@ def product_on_basis(self, w1, w2): gens = self._decompose_into_generators(w2) other_element = self.monomial(w1) - # [I'm a little confused by 'powers' below; also, should we write a helper function earlier for the 'manual - # distribution'?] - - # gens is a linear combination of products of the C' generators + # gens is a linear combination of products of the C' generators # Now, build everything back up, continually multiplying on the left by a single generator at a time result = self(0) From 2e9f6d6616c11c5e0f5b0a3c9896f5e105630a97 Mon Sep 17 00:00:00 2001 From: Chase Meadors Date: Thu, 22 Jul 2021 11:54:48 -0600 Subject: [PATCH 050/359] Only allow the standard normalizations for the Cp_Coxeter3 basis. --- src/sage/algebras/iwahori_hecke_algebra.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/sage/algebras/iwahori_hecke_algebra.py b/src/sage/algebras/iwahori_hecke_algebra.py index d5c65b9d2b4..583db458673 100644 --- a/src/sage/algebras/iwahori_hecke_algebra.py +++ b/src/sage/algebras/iwahori_hecke_algebra.py @@ -2064,11 +2064,15 @@ def __init__(self, algebra, prefix='Cp'): super(IwahoriHeckeAlgebra.Cp_Coxeter3, self).__init__(algebra, prefix) self._W = algebra._W - self.delta = q + ~q # need the normalizations q_1=q^2, q_2=-1 or q_1=q,q_2=-q^-1 - # The free algebra over our algebra generators, used to create monomials in these generators in _decompose_into_generators - self.gen_algebra = FreeAlgebra(algebra.base_ring(), ['g' + str(i) for i in self.index_set()]) - + v = algebra.base_ring().gen(0) + if ((algebra.q1() == v**2 and algebra.q2() == -1) or (algebra.q1() == v and algebra.q2() == -1/v)): + self.delta = v + ~v + else: + if not algebra._is_generic: + # If this algebra is generic, it's only being used to coerce to the T basis, not perform computations + raise ValueError('the Cp_Coxeter3 basis is only supported in a Hecke algebra with standard normalizations (explain)') + # Define conversion to the other Cp basis self.module_morphism(self.to_Cp_basis, codomain=algebra.Cp(), category=self.category() From 787be9175f69b71da58035fd4bb96a462782b826 Mon Sep 17 00:00:00 2001 From: Chase Meadors Date: Thu, 22 Jul 2021 11:56:16 -0600 Subject: [PATCH 051/359] Tweak _decompose_into_generators and related free algebra stuff for clarity and readability. --- src/sage/algebras/iwahori_hecke_algebra.py | 52 ++++++++++++---------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/src/sage/algebras/iwahori_hecke_algebra.py b/src/sage/algebras/iwahori_hecke_algebra.py index 583db458673..129fe26a7e0 100644 --- a/src/sage/algebras/iwahori_hecke_algebra.py +++ b/src/sage/algebras/iwahori_hecke_algebra.py @@ -2073,6 +2073,11 @@ def __init__(self, algebra, prefix='Cp'): # If this algebra is generic, it's only being used to coerce to the T basis, not perform computations raise ValueError('the Cp_Coxeter3 basis is only supported in a Hecke algebra with standard normalizations (explain)') + # Construct a free algebra over generators representing the C' generators: { Cp_s : s in S } + self._generator_algebra = FreeAlgebra(algebra.base_ring(), ['Cp{}'.format(s) for s in self.index_set()]) + # The correspondence between indices and generators of the generator algebra + self._generators = { s: self._generator_algebra('Cp{}'.format(s)) for s in self.index_set() } + self._index_of_generator = { v: k for (k, v) in self._generators.items() } # Define conversion to the other Cp basis self.module_morphism(self.to_Cp_basis, codomain=algebra.Cp(), category=self.category() @@ -2144,7 +2149,8 @@ def _product_with_generator(self, side, s, x): def _decompose_into_generators(self, w): r""" - Decompose `C^{\prime}_s` into a polynomial in the KL generators `C^{\prime}_s`. + Decompose `C^{\prime}_w` into a polynomial in the KL generators `C^{\prime}_s` (an element of the + free algebra `self.generator_algebra`) The decomposition is obtained recursively, by induction on `\ell(w)`. If `ell(w) < 2` the decomposition is trivial (see Examples). If `\ell(w) \geq 2`, write `w=su` where `s` is a left descent of `w` so that @@ -2166,27 +2172,23 @@ def _decompose_into_generators(self, w): EXAMPLES:: # A3 sage: _decompose_into_generators((1,2)) - {[1,2]: 1} # C_{12}=C_1C_2 + Cp1*Cp2 # C_{12} = C_1C_2 sage: _decompose_into_generators((1,2,1)) - {[1,2,1]: 1, [1]:-1} # C_{121}=C_1C_2C_1-C_1=m_121-m_1 + Cp1*Cp2*Cp1 - Cp1 # C_{121} = C_1C_2C_1 - C_1 sage: _decompose_into_generators((1,2,3,1,2)) the suitable dictionary # use "monomial" somehow to get the result natively? - """ - # Returns an element of self.gen_algebra, a free algebra over {g_1, ..., g_n} - # describing how to write 'word' in terms of the generators - - gs = self.gen_algebra.gens() + """ if len(w) == 0: - return self.gen_algebra(1) + return self.generator_algebra(1) if len(w) == 1: - return gs[w[0]] + return self._generators[w[0]] s = w[0] w1 = w[1:] - # Additively build the sum just mentioned above + # Additively build the sum term (lower order terms) sum_term = self(0) between = self._W.bruhat_interval([], w1) for x in between: @@ -2197,8 +2199,8 @@ def _decompose_into_generators(self, w): sum_term += self.base_ring()(x.mu_coefficient(w1)) * self.monomial(x_elt) # In the expression above, we need to recurse and decompose C_{w1} into generators, - # and then go through the terms of the sum_term (lower order terms) and decompose those C_y's into generators - alg_element = gs[s] * self._decompose_into_generators(w1) + # and then go through the terms of sum_term (lower order terms) and decompose those C_y's into generators + alg_element = self._generators[s] * self._decompose_into_generators(w1) for (v, coeff) in sum_term: # We're subtracting 'sum_term' alg_element -= coeff * self._decompose_into_generators(v) @@ -2215,31 +2217,33 @@ def product_on_basis(self, w1, w2): # (as expressed as an element of the FreeAlgebra over 'generator' variables g1, ..., gn) if len(w1) <= len(w2): side = 'left' - gens = self._decompose_into_generators(w1) + gen_expression = self._decompose_into_generators(w1) other_element = self.monomial(w2) else: side = 'right' - gens = self._decompose_into_generators(w2) + gen_expression = self._decompose_into_generators(w2) other_element = self.monomial(w1) - # gens is a linear combination of products of the C' generators + # gen_expression is a linear combination of products of the C' generators # Now, build everything back up, continually multiplying on the left by a single generator at a time result = self(0) # Iterate through the sum of terms - for (p, coeff) in gens: + for (p, coeff) in gen_expression: # p is a product of generators, i.e. 2*g1*g2*g1; multiply it by other_element - # Build summand multiplicatively, going through variables and thier powers in p - # If gens are on the right, we need to start at the left end of p, and vice versa. + # Build summand multiplicatively, going through variables (and their exponents) in p + # If gen_expression is being multiplied on the right, we need to start at the left + # end of p, and vice versa. summand = coeff * other_element p_list = list(p) if side == 'right' else list(p)[::-1] # Iterate through the product of generators - for (g, exponent) in p_list: - s = self.gen_algebra.gens().index(g) - # Multiply this_element on the apppropriate side by the generator this variable g corresponds to, - # however many times it is represented in the product (according to the exponent) + for (gen, exponent) in p_list: + s = self._index_of_generator[self._generator_algebra(gen)] + # gen is in the underlying monoid of _generator_algebra, so coercion is required for i in range(exponent): - # Perform C'_s * (summand) + # Perform C'_s * summand (on the appropriate side), + # however many times C'_s is represented in the product + # according to the exponent. summand = self._product_with_generator(side, s, summand) result += summand From 56707178f43e3b821020a2dc6cfe4cbf63dd2166 Mon Sep 17 00:00:00 2001 From: Chase Meadors Date: Thu, 22 Jul 2021 18:25:51 -0600 Subject: [PATCH 052/359] Some TODO's and documentation tweaks; make docstrings functional through "to_Cp_basis" --- src/sage/algebras/iwahori_hecke_algebra.py | 159 +++++++++++++++------ 1 file changed, 114 insertions(+), 45 deletions(-) diff --git a/src/sage/algebras/iwahori_hecke_algebra.py b/src/sage/algebras/iwahori_hecke_algebra.py index 129fe26a7e0..f7da859c508 100644 --- a/src/sage/algebras/iwahori_hecke_algebra.py +++ b/src/sage/algebras/iwahori_hecke_algebra.py @@ -1969,7 +1969,7 @@ class Cp_Coxeter3(_KLHeckeBasis): r""" Directly compute products in the `C^{\prime}`-basis by using du Cloux's Coxeter3 package. - [State assumptions] normalization/coxeter3 implementation + TODO: [State assumptions] normalization/coxeter3 implementation Expanding products of the form `C^{\prime}_x \cdot C^{\prime}_y` in the `C^{\prime}`-basis is useful for computing Kazhdan-Lusztig cells of Coxeter systems and the corresponding cell modules of Iwahori-Hecke @@ -2000,49 +2000,86 @@ class Cp_Coxeter3(_KLHeckeBasis): Use the analog of the displayed formula to implement `C^{\prime}`-products in the multi-parameter Iwahori-Hecke algebra; see Section 6 of [Lus2013]_. - EXAMPLES:: - - sage: R = LaurentPolynomialRing(QQ, 'q') - [A3 examples with warnings caused by wrong presentation or implementation...] - - Create the Hecke algebra of type 'A3' and label the `C^{\prime}`-basis by `B`: - - sage: H = IwahoriHeckeAlgebra('A3',implementation = 'coxeter3') - sage: B = H.Cp_Coxeter3() [careful about printing: B or Cp] - - Product of the form `B_s \cdot B_y` where `s` is a generator are computed by the earlier formula:: + EXAMPLES: - sage: B[1] * B[1] - (q^-1+q) * B[1] - sage: B[1] * B[2] - B[1,2] - sage: B[1] * B[2,1] - B[1,2,1] + B[1] - sage: B[1] * B[2,1,3] - B[1,2,3,1] + B[3,1] - sage: B[2] * B[1,3,2,1,3] - B[1,2,3,1,2,1] + Cp[2,3,2,1] + Cp[1,2,3,1] + Basic usage:: + sage: R. = LaurentPolynomialRing(ZZ) + sage: A3 = CoxeterGroup('A3', implementation='coxeter3') + sage: s1, s2, s3 = A3.simple_reflections() + sage: H = IwahoriHeckeAlgebra(A3, v**2) + sage: Cp = H.Cp_Coxeter3() + sage: Cp(s1*s2*s1) + Cp[1,2,1] + sage: Cp(s1)**2 + (v^-1+v)*Cp[1] + sage: Cp(s1)*Cp(s2)*Cp(s1) + Cp[1,2,1] + Cp[1] + sage: Cp[1]*Cp[2]*Cp[3]*Cp[1]*Cp[2] + Cp[1,2,1,3,2] + Cp[1,2,1] + Cp[1,3,2] - More generally, we can compute products of the form 'B_x \cdot B_y` for general `x, y`:: - - sage: B[1,2,1] * B[3,1] - (q^-1+q)*B[1,2,3,1] - sage: B[1,2,1] * B[3,1,2] (q^-1+q)*B[1,2,3,1,2] + (q^-1+q)*B[1,2,1] - - [More examples: B9 examples; showcase labelling, compare speed with the indirect method ] - + The IwahoriHeckeAlgebra must be initialized with a ``CoxeterGroup`` + implemented with coxeter3 and the Hecke parameters must be v^2, -1 or + v, -1/v:: - .. NOTE:: + sage: H = IwahoriHeckeAlgebra('A3', v**2) + sage: H.Cp_Coxeter3() + Traceback (most recent call last): + ... + ValueError: algebra must be initialized with a coxeter3-implemented Coxeter group to use the Cp_Coxeter3 basis + sage: A3 = CoxeterGroup('A3', implementation='coxeter3') + sage: H = IwahoriHeckeAlgebra(A3, QQ(1)) + sage: H.Cp_Coxeter3() + Traceback (most recent call last): + ... + ValueError: the Cp_Coxeter3 basis is only supported in a Hecke algebra with standard normalizations (explain) + + Products of the form `Cp_s \cdot Cp_y` where `s` is a generator are computed by the earlier formula:: - The products `B_x \cdot B_y` are computed as follows: if `\ell(x) \leq \ell(y)`, then we first - decompose `B_x` into a polynomial in the generators `B_s (s\in S)`, then multiplies that linear - combination onto `B_y`; otherwise we decompose `B_y` and multiply the result onto `B_x`. For - example, in the computation of `B[1,2,1] * B[3,1,2]` in type `A3`, the left term `B[1,2,1]` is - first (essentially) decomposed into the linear combination `B[1]*B[2]*B[1] - B[1]` behind the - scenes. The decomposition is achieved via the [_decompose_into_generators function], which takes an - element `B_w` and gives an element of the free algebra over \{ B_s \; : \; s \in S \}, whose image - under the canonical homomorphism from the free algebra is precisely `B_w`. + sage: A3 = CoxeterGroup('A3', implementation='coxeter3') + sage: H = IwahoriHeckeAlgebra(A3, v**2) + sage: Cp = H.Cp_Coxeter3() + sage: Cp[1] * Cp[1] + (v^-1+v)*Cp[1] + sage: Cp[1] * Cp[2] + Cp[1,2] + sage: Cp[1] * Cp[2,1] + Cp[1,2,1] + Cp[1] + sage: Cp[1] * Cp[2,1,3] + Cp[1,2,1,3] + Cp[1,3] + sage: Cp[2] * Cp[1,3,2,1,3] + Cp[1,2,1,3,2,1] + Cp[1,2,1,3] + Cp[2,3,2,1] + + More generally, we can compute products of the form `C^{\prime}_x \cdot C^{\prime}_y` for + general `x, y`:: + + sage: Cp[1,2,1] * Cp[3,1] + (v^-1+v)*Cp[1,2,1,3] + sage: Cp[1,2,1] * Cp[3,1,2] + (v^-1+v)*Cp[1,2,1,3,2] + (v^-1+v)*Cp[1,2,1] + (v^-1+v)*Cp[1,3,2] - (v^-1+v)*Cp[3,1,2] + + We can compute complex products in in type `B9`, while relabelling the + generators so that the long braid is between the first two generators:: + + sage: B9 = CoxeterGroup(CoxeterType(['B', 9]).relabel({ i: 9-i+1 for i in range(1, 10) }), implementation='coxeter3') + sage: H = IwahoriHeckeAlgebra(B9, v, -1/v) + sage: Cp = H.Cp_Coxeter3() + sage: Cp[1,2,1,2] + Cp[1,2,1,2] + sage: Cp[3,2,3,4,5] * Cp[2,3] + (v^-1+v)*Cp[2,3,2,4,3,5] + (v^-1+v)*Cp[2,3,2,5] + + + .. NOTE:: + + The products `B_x \cdot B_y` are computed as follows: if `\ell(x) \leq \ell(y)`, then we first + decompose `B_x` into a polynomial in the generators `B_s (s\in S)`, then multiplies that linear + combination onto `B_y`; otherwise we decompose `B_y` and multiply the result onto `B_x`. For + example, in the computation of `B[1,2,1] * B[3,1,2]` in type `A3`, the left term `B[1,2,1]` is + first (essentially) decomposed into the linear combination `B[1]*B[2]*B[1] - B[1]` behind the + scenes. The decomposition is achieved via the [_decompose_into_generators function], which takes an + element `B_w` and gives an element of the free algebra over \{ B_s \; : \; s \in S \}, whose image + under the canonical homomorphism from the free algebra is precisely `B_w`. .. SEEALSO:: @@ -2050,14 +2087,27 @@ class Cp_Coxeter3(_KLHeckeBasis): :meth:`sage.somewhere.other_useful_method`, cell stuff [coxeter3?] - TESTS:: - - [show our direct method yields the same results as the indirect method?] - """ _basis_name = 'Cp_Coxeter3' def __init__(self, algebra, prefix='Cp'): + r""" + Initialize the Cp_Coxeter3 Kazdahn-Luzstig basis of the + Iwahori-Hecke algebra ``algebra''. + + EXAMPLES:: + + sage: R. = LaurentPolynomialRing(ZZ, 'v') + sage: A3 = CoxeterGroup('A3', implementation='coxeter3') + sage: H = IwahoriHeckeAlgebra(A3, v**2) + sage: Cp = H.Cp_Coxeter3() + + sage: H = IwahoriHeckeAlgebra('A3', v**2) + sage: Cp = H.Cp_Coxeter3() + Traceback (most recent call last): + ... + ValueError: algebra must be initialized with a coxeter3-implemented Coxeter group to use the Cp_Coxeter3 basis + """ if not isinstance(algebra._W, Coxeter3Group): raise ValueError('algebra must be initialized with a coxeter3-implemented Coxeter group to use the Cp_Coxeter3 basis') @@ -2066,16 +2116,19 @@ def __init__(self, algebra, prefix='Cp'): self._W = algebra._W v = algebra.base_ring().gen(0) - if ((algebra.q1() == v**2 and algebra.q2() == -1) or (algebra.q1() == v and algebra.q2() == -1/v)): + + # TODO: rewrite this horribly ugly condition: + if v != algebra.base_ring().one() and ((algebra.q1() == v**2 and algebra.q2() == -1) or (algebra.q1() == v and algebra.q2() == -1/v)): self.delta = v + ~v else: if not algebra._is_generic: # If this algebra is generic, it's only being used to coerce to the T basis, not perform computations + # TODO: Better error message raise ValueError('the Cp_Coxeter3 basis is only supported in a Hecke algebra with standard normalizations (explain)') # Construct a free algebra over generators representing the C' generators: { Cp_s : s in S } self._generator_algebra = FreeAlgebra(algebra.base_ring(), ['Cp{}'.format(s) for s in self.index_set()]) - # The correspondence between indices and generators of the generator algebra + # The correspondence between indices and formal generators of the generator algebra self._generators = { s: self._generator_algebra('Cp{}'.format(s)) for s in self.index_set() } self._index_of_generator = { v: k for (k, v) in self._generators.items() } @@ -2088,6 +2141,22 @@ def __init__(self, algebra, prefix='Cp'): Cp.module_morphism(Cp.to_Cp_Coxeter3_basis, codomain=self, category=self.category()).register_as_coercion() def to_Cp_basis(self, w): + r""" + Return the element ``self[w]`` as a linear combination of + ``Cp``-basis elements. This transformation is trivial as both + bases are implementations of the `C^{\prime}` basis. + + EXAMPLES:: + + sage: R. = LaurentPolynomialRing(ZZ, 'v') + sage: A3 = CoxeterGroup('A3', implementation='coxeter3') + sage: H = IwahoriHeckeAlgebra(A3, v**2); Cp=H.Cp(); CpC=H.Cp_Coxeter3() + sage: s1, s2, s3 = A3.simple_reflections() + sage: CpC.to_Cp_basis(s1*s2) + Cp[1,2] + sage: CpC.to_Cp_basis(s1*s2*s1) + Cp[1,2,1] + """ A = self.realization_of() Cp = A.Cp() return Cp.monomial(w) From 9510a6813b0d65973c4b9e1c62e595943d2c52e4 Mon Sep 17 00:00:00 2001 From: Chase Meadors Date: Fri, 23 Jul 2021 01:21:39 -0600 Subject: [PATCH 053/359] Finish getting docstrings drafted and examples functional for all added methods --- src/sage/algebras/iwahori_hecke_algebra.py | 328 +++++++++++++++------ 1 file changed, 241 insertions(+), 87 deletions(-) diff --git a/src/sage/algebras/iwahori_hecke_algebra.py b/src/sage/algebras/iwahori_hecke_algebra.py index f7da859c508..128fce56ccf 100644 --- a/src/sage/algebras/iwahori_hecke_algebra.py +++ b/src/sage/algebras/iwahori_hecke_algebra.py @@ -1582,6 +1582,25 @@ def to_Cp_basis(self, w): return generic_T.to_Cp_basis(w).specialize_to(H) def to_Cp_Coxeter3_basis(self, w): + r""" + Return `T-w` as a linear combination of `C^{\prime}`-basis elements, + using the ``Cp_Coxeter3`` basis. + + EXAMPLES:: + + sage: R. = LaurentPolynomialRing(ZZ, 'v') + sage: A3 = CoxeterGroup('A3', implementation='coxeter3') + sage: H = IwahoriHeckeAlgebra(A3, v**2); T=H.T(); Cp=H.Cp_Coxeter3() + sage: s1,s2,s3 = A3.simple_reflections() + sage: T.to_Cp_Coxeter3_basis(s1) + v*Cp[1] - 1 + sage: Cp(T(s1)) + v*Cp[1] - 1 + sage: Cp(T[1] + 1) + v*Cp[1] + sage: Cp(T[1,2] + T[1] + T[2] + 1) + v^2*Cp[1,2] + """ H = self.realization_of() generic_T = H._generic_iwahori_hecke_algebra.T() return generic_T.to_Cp_Coxeter3_basis(w).specialize_to(H) @@ -1938,6 +1957,21 @@ class Cp(_KLHeckeBasis): _basis_name = 'Cp' # this is used, for example, by specialize_to and is the default prefix def to_Cp_Coxeter3_basis(self, w): + r""" + Return ``self[w]`` as an element of the ``Cp_Coxeter3`` basis. This + transformation is trivial since both bases are implementations of + the `C^{\prime}` basis. + + EXAMPLES:: + + sage: R. = LaurentPolynomialRing(ZZ, 'v') + sage: A3 = CoxeterGroup('A3', implementation='coxeter3') + sage: H = IwahoriHeckeAlgebra(A3, v**2); Cp = H.Cp(); CpC=H.Cp_Coxeter3() + sage: Cp.to_Cp_Coxeter3_basis(A3([1,2])) + Cp[1,2] + sage: CpC(Cp[1,2]) + Cp[1,2] + """ A = self.realization_of() Cp = A.Cp_Coxeter3() return Cp.monomial(w) @@ -1967,38 +2001,46 @@ def hash_involution_on_basis(self, w): class Cp_Coxeter3(_KLHeckeBasis): r""" - Directly compute products in the `C^{\prime}`-basis by using du Cloux's Coxeter3 package. + Directly compute products in the `C^{\prime}`-basis by using du Cloux's + Coxeter3 package. TODO: [State assumptions] normalization/coxeter3 implementation - Expanding products of the form `C^{\prime}_x \cdot C^{\prime}_y` in the `C^{\prime}`-basis is useful for - computing Kazhdan-Lusztig cells of Coxeter systems and the corresponding cell modules of Iwahori-Hecke - algebras. Such expansion is controlled by the following formula (and the analogous formula for - `C^{\prime}_s \cdot C^{\prime}_w`) under both the "standard" and the "normalized" presentations of the - Iwahori-Hecke algebra, where the quadratic relation is `(T_s-q^2)(T_s+1)=0` and `(T_s-q)(T_s+q^-1)=0` for - each generator `s`, respectively. + Expanding products of the form `C^{\prime}_x \cdot C^{\prime}_y` in the + `C^{\prime}`-basis is useful for computing Kazhdan-Lusztig cells of + Coxeter systems and the corresponding cell modules of Iwahori-Hecke + algebras. Such expansion is controlled by the following formula (and + the analogous formula for `C^{\prime}_s \cdot C^{\prime}_w`) under both + the "standard" and the "normalized" presentations of the Iwahori-Hecke + algebra, where the quadratic relation is `(T_s-q^2)(T_s+1)=0` and + `(T_s-q)(T_s+q^-1)=0` for each generator `s`, respectively. + + .. MATH:: C^{\prime}_s \cdot C^{\prime}_w = \begin{cases} + (q+q^-1)C^{\prime}_{w}, & + \text{if } \ell(sw) = \ell(w)-1,\\ + C^{\prime}_{sw}+\sum_{v\leq w, sv \leq v} \mu(v,w)C^{\prime}_v, & + \text{if } \ell(sw) = \ell(w)+1. \end{cases} + + where `\leq` is the Bruhat order on the underlying Coxeter group and + `\mu(v,w)` is the "leading coefficient of Kazhdan-Lusztig polynomials"; + see [KL1979]_ and [Lus2014]_ for more details. + + The emphasis of this class is to compute products in the + `C^{\prime}`-basis directly, by using the above formula and calling the + necessary `\mu`-coefficients from Sage's implementation of Fokko du + Cloux's Coxeter3 package. This methods computes the products faster than + the _Basis.product_on_basis method on Line 1298, which needs to convert + the `C^{\prime}`-basis to the `T`-basis, calculate the product in the + `T`-basis, and convert the results back to the `C^{\prime}`-basis. For + example, the product `C^{\prime}_{32345} * C^{\prime}_{23}` in the Hecke + algebra of type 'B_9' takes more than 30 seconds with the latter method + but is instant using this class. - .. MATH:: - C^{\prime}_s \cdot C^{\prime}_w = - \begin{cases} - (q+q^-1)C^{\prime}_{w}, & \text{if } \ell(sw) = \ell(w)-1,\\ - C^{\prime}_{sw}+\sum_{v\leq w, sv \leq v} \mu(v,w)C^{\prime}_v, & \text{if } \ell(sw) = \ell(w)+1. - \end{cases} - - where `\leq` is the Bruhat order on the underlying Coxeter group and `\mu(v,w)` is the "leading coefficient - of Kazhdan-Lusztig polynomials"; see [KL1979]_ and [Lus2014]_ for more details. - - The emphasis of this class is to compute products in the `C^{\prime}`-basis directly, by using the above - formula and calling the necessary `\mu`-coefficients from Sage's implementation of Fokko du Cloux's - Coxeter3 package. This methods computes the products faster than the _Basis.product_on_basis method on Line - 1298, which needs to convert the `C^{\prime}`-basis to the `T`-basis, calculate the product in the - `T`-basis, and convert the results back to the `C^{\prime}`-basis. For example, the product - `C^{\prime}_{32345} * C^{\prime}_{23}` in the Hecke algebra of type 'B_9' takes more than 30 seconds with - the latter method but is instant using this class. - .. TODO:: - Use the analog of the displayed formula to implement `C^{\prime}`-products in the multi-parameter - Iwahori-Hecke algebra; see Section 6 of [Lus2013]_. + + Use the analog of the displayed formula to implement + `C^{\prime}`-products in the multi-parameter Iwahori-Hecke algebra; + see Section 6 of [Lus2013]_. EXAMPLES: @@ -2019,8 +2061,8 @@ class Cp_Coxeter3(_KLHeckeBasis): Cp[1,2,1,3,2] + Cp[1,2,1] + Cp[1,3,2] The IwahoriHeckeAlgebra must be initialized with a ``CoxeterGroup`` - implemented with coxeter3 and the Hecke parameters must be v^2, -1 or - v, -1/v:: + implemented with coxeter3 and the Hecke parameters must be v^2, -1 or v, + -1/v:: sage: H = IwahoriHeckeAlgebra('A3', v**2) sage: H.Cp_Coxeter3() @@ -2033,8 +2075,9 @@ class Cp_Coxeter3(_KLHeckeBasis): Traceback (most recent call last): ... ValueError: the Cp_Coxeter3 basis is only supported in a Hecke algebra with standard normalizations (explain) - - Products of the form `Cp_s \cdot Cp_y` where `s` is a generator are computed by the earlier formula:: + + Products of the form `Cp_s \cdot Cp_y` where `s` is a generator are + computed by the earlier formula:: sage: A3 = CoxeterGroup('A3', implementation='coxeter3') sage: H = IwahoriHeckeAlgebra(A3, v**2) @@ -2050,13 +2093,13 @@ class Cp_Coxeter3(_KLHeckeBasis): sage: Cp[2] * Cp[1,3,2,1,3] Cp[1,2,1,3,2,1] + Cp[1,2,1,3] + Cp[2,3,2,1] - More generally, we can compute products of the form `C^{\prime}_x \cdot C^{\prime}_y` for - general `x, y`:: + More generally, we can compute products of the form `C^{\prime}_x \cdot + C^{\prime}_y` for general `x, y`:: sage: Cp[1,2,1] * Cp[3,1] (v^-1+v)*Cp[1,2,1,3] sage: Cp[1,2,1] * Cp[3,1,2] - (v^-1+v)*Cp[1,2,1,3,2] + (v^-1+v)*Cp[1,2,1] + (v^-1+v)*Cp[1,3,2] - (v^-1+v)*Cp[3,1,2] + (v^-1+v)*Cp[1,2,1,3,2] + (v^-1+v)*Cp[1,2,1] We can compute complex products in in type `B9`, while relabelling the generators so that the long braid is between the first two generators:: @@ -2071,15 +2114,19 @@ class Cp_Coxeter3(_KLHeckeBasis): .. NOTE:: - - The products `B_x \cdot B_y` are computed as follows: if `\ell(x) \leq \ell(y)`, then we first - decompose `B_x` into a polynomial in the generators `B_s (s\in S)`, then multiplies that linear - combination onto `B_y`; otherwise we decompose `B_y` and multiply the result onto `B_x`. For - example, in the computation of `B[1,2,1] * B[3,1,2]` in type `A3`, the left term `B[1,2,1]` is - first (essentially) decomposed into the linear combination `B[1]*B[2]*B[1] - B[1]` behind the - scenes. The decomposition is achieved via the [_decompose_into_generators function], which takes an - element `B_w` and gives an element of the free algebra over \{ B_s \; : \; s \in S \}, whose image - under the canonical homomorphism from the free algebra is precisely `B_w`. + + The products `B_x \cdot B_y` are computed as follows: if + `\ell(x) \leq \ell(y)`, then we first decompose `B_x` into a + polynomial in the generators `B_s (s\in S)`, then multiplies that + linear combination onto `B_y`; otherwise we decompose `B_y` and + multiply the result onto `B_x`. For example, in the computation of + `B[1,2,1] * B[3,1,2]` in type `A3`, the left term `B[1,2,1]` is + first (essentially) decomposed into the linear combination + `B[1]*B[2]*B[1] - B[1]` behind the scenes. The decomposition is + achieved via the [_decompose_into_generators function], which takes + an element `B_w` and gives an element of the free algebra over \{ + B_s \; : \; s \in S \}, whose image under the canonical homomorphism + from the free algebra is precisely `B_w`. .. SEEALSO:: @@ -2092,7 +2139,7 @@ class Cp_Coxeter3(_KLHeckeBasis): def __init__(self, algebra, prefix='Cp'): r""" - Initialize the Cp_Coxeter3 Kazdahn-Luzstig basis of the + Initialize the Cp_Coxeter3 Kazdahn-Luzstig basis of the Iwahori-Hecke algebra ``algebra''. EXAMPLES:: @@ -2142,9 +2189,9 @@ def __init__(self, algebra, prefix='Cp'): def to_Cp_basis(self, w): r""" - Return the element ``self[w]`` as a linear combination of - ``Cp``-basis elements. This transformation is trivial as both - bases are implementations of the `C^{\prime}` basis. + Return the element ``self[w]`` in the ``Cp``-basis. This + transformation is trivial as both bases are implementations of the + `C^{\prime}` basis. EXAMPLES:: @@ -2166,10 +2213,11 @@ def _product_with_generator_on_basis(self, side, s, w): Compute the product of `C^{\prime}_s` and `C^{\prime}_w`, putting `C^{\prime}_s` on the given ``side``. - For each generator `s` and element `x`, the products `C^{\prime}_s \cdot C^{\prime}_w` - is given by the following formulas: + For each generator `s` and element `x`, the products `C^{\prime}_s + \cdot C^{\prime}_w` is given by the following formulas: .. MATH:: + C^{\prime}_s \cdot C^{\prime}_w = \begin{cases} (q+q^-1)C^{\prime}_{w}, & \text{if } \ell(sw) = \ell(w)-1,\\ @@ -2184,10 +2232,27 @@ def _product_with_generator_on_basis(self, side, s, w): where `\leq` is the Bruhat order and the numbers `\mu(v,w)` are the `mu`-coefficients of [Lus2014]_. - [recycle the examples from the class' documentation, or not?] + INPUT: + + - ``side`` -- string; 'left' or 'right' + + - ``s`` -- integer in self.index_set() + + - ``w`` -- a word in self.coxeter_group() + + EXAMPLES:: + + sage: R. = LaurentPolynomialRing(ZZ, 'v') + sage: A3 = CoxeterGroup('A3', implementation='coxeter3') + sage: H = IwahoriHeckeAlgebra(A3, v**2); Cp=H.Cp_Coxeter3() + sage: Cp._product_with_generator_on_basis('left', 1, A3([2,1])) + Cp[1,2,1] + Cp[1] + sage: Cp._product_with_generator_on_basis('right', 2, A3([1,3,2,1,3])) + Cp[1,2,1,3,2,1] + Cp[1,2,3,2] + Cp[1,3,2,1] """ if w.has_descent(s, side=side): + # TODO: notation? # Descent case, return (q + q^-1) C'_w return self.delta * self.monomial(w) else: @@ -2208,22 +2273,40 @@ def _product_with_generator_on_basis(self, side, s, w): def _product_with_generator(self, side, s, x): r""" - Compute the product of `C^{\prime}_s` with any linear combination of `C^{\prime}`-basis elements. + Compute the product of `C^{\prime}_s` with any linear combination of + `C^{\prime}`-basis elements. + + INPUT: + + - ``side`` -- string; 'left' or 'right' - EXAMPLE:: + - ``s`` -- integer in self.index_set() - [one example is enough] + - ``w`` -- any element of self + + EXAMPLES:: + + sage: R. = LaurentPolynomialRing(ZZ, 'v') + sage: A3 = CoxeterGroup('A3', implementation='coxeter3') + sage: H = IwahoriHeckeAlgebra(A3, v**2); Cp=H.Cp_Coxeter3() + sage: Cp._product_with_generator('left', 1, Cp[1]+Cp[2]) + Cp[1,2] + (v^-1+v)*Cp[1] + sage: Cp._product_with_generator('right', 1, Cp[1]+Cp[2]) + Cp[2,1] + (v^-1+v)*Cp[1] """ return self.linear_combination((self._product_with_generator_on_basis(side, s, w), coeff) for (w, coeff) in x) def _decompose_into_generators(self, w): r""" - Decompose `C^{\prime}_w` into a polynomial in the KL generators `C^{\prime}_s` (an element of the - free algebra `self.generator_algebra`) - - The decomposition is obtained recursively, by induction on `\ell(w)`. If `ell(w) < 2` the decomposition - is trivial (see Examples). If `\ell(w) \geq 2`, write `w=su` where `s` is a left descent of `w` so that - `\ell(w) = \ell(u) + 1`, then use the formula that + Decompose `C^{\prime}_w` into a polynomial in the KL generators + `C^{\prime}_s` (an element of the free algebra + `self.generator_algebra`) + + The decomposition is obtained recursively, by induction on + `\ell(w)`. If `ell(w) < 2` the decomposition is trivial (see + Examples). If `\ell(w) \geq 2`, write `w=su` where `s` is a left + descent of `w` so that `\ell(w) = \ell(u) + 1`, then use the formula + that .. MATH:: C^{\prime}_s \cdot C^{\prime}_u = @@ -2234,19 +2317,29 @@ def _decompose_into_generators(self, w): .. MATH:: C^{\prime}_{w}= C^{\prime}_s \cdot C^{\prime}_u - \sum_{v\leq u, sv \leq v} \mu(v,u)C^{\prime}_v. - The element `u` and the elements `v` on the right side all have smaller length than `w`, so they can be - obtained by induction. + The element `u` and the elements `v` on the right side all have + smaller length than `w`, so they can be obtained by induction. + + INPUT: + + - ``w`` -- word in self.coxeter_group() + OUTPUT: + + An element of ``self._generator_algebra`` describing how to express + `C^{\prime}_w` in terms of the generators `C^{\prime}_s`. EXAMPLES:: - # A3 - sage: _decompose_into_generators((1,2)) - Cp1*Cp2 # C_{12} = C_1C_2 - sage: _decompose_into_generators((1,2,1)) - Cp1*Cp2*Cp1 - Cp1 # C_{121} = C_1C_2C_1 - C_1 - sage: _decompose_into_generators((1,2,3,1,2)) - the suitable dictionary # use "monomial" somehow to get the result natively? + sage: R. = LaurentPolynomialRing(ZZ, 'v') + sage: A3 = CoxeterGroup('A3', implementation='coxeter3') + sage: H = IwahoriHeckeAlgebra(A3, v**2); Cp=H.Cp_Coxeter3() + sage: Cp._decompose_into_generators(A3([1,2])) # C_{12} = C_1C_2 + Cp1*Cp2 + sage: Cp._decompose_into_generators(A3([1,2,1])) # C_{121} = C_1C_2C_1 - C_1 + -Cp1 + Cp1*Cp2*Cp1 + sage: Cp._decompose_into_generators(A3([1,2,3,1,2])) + Cp1 - Cp1*Cp2*Cp1 - Cp1*Cp3*Cp2 + Cp1*Cp2*Cp1*Cp3*Cp2 """ if len(w) == 0: return self.generator_algebra(1) @@ -2278,9 +2371,22 @@ def _decompose_into_generators(self, w): def product_on_basis(self, w1, w2): r""" - Return the expansion of `C^{\prime}_{w_1} \cdot C^{\prime}_{w_2}` in the `C^{\prime}`-basis. - - [recycle example from class' doc?] + Return the expansion of `C^{\prime}_{w_1} \cdot C^{\prime}_{w_2}` in + the `C^{\prime}`-basis. + + TODO: Describe our decision to decompose the smaller word...? Or is + class docs enough here. I lean towards describing the algorithm once + in the class docs. + + EXAMPLES:: + + sage: R. = LaurentPolynomialRing(ZZ, 'v') + sage: A3 = CoxeterGroup('A3', implementation='coxeter3') + sage: H = IwahoriHeckeAlgebra(A3, v**2); Cp=H.Cp_Coxeter3() + sage: Cp.product_on_basis(A3([1,2,1]), A3([3,1])) + (v^-1+v)*Cp[1,2,1,3] + sage: Cp.product_on_basis(A3([1,2,1]), A3([3,1,2])) + (v^-1+v)*Cp[1,2,1,3,2] + (v^-1+v)*Cp[1,2,1] """ # Otherwise, decompose the first word into generators # (as expressed as an element of the FreeAlgebra over 'generator' variables g1, ..., gn) @@ -2890,28 +2996,30 @@ class T(IwahoriHeckeAlgebra.T): """ def _to_Cp_basis(self, w, Cp): r""" - TODO: Change this documentation and the two below - Return `T_w` as a linear combination of `C^{\prime}`-basis - elements. + Return `T_w` as a linear combination of `C^{\prime}`-basis elements, + using either the ``Cp`` basis or the ``Cp_Coxeter3`` implementation. + + INPUT: + + - ``w`` -- a word in self.coxeter_group() + + - ``Cp`` -- the target `C^{\prime}` basis to use; either ``Cp`` or + ``Cp_Coxeter3`` EXAMPLES:: - sage: H = sage.algebras.iwahori_hecke_algebra.IwahoriHeckeAlgebra_nonstandard("A2") - sage: s1,s2 = H.coxeter_group().simple_reflections() - sage: T = H.T() - sage: Cp = H.Cp() - sage: T.to_Cp_basis(s1) + sage: A3 = CoxeterGroup('A3', implementation='coxeter3') + sage: H = sage.algebras.iwahori_hecke_algebra.IwahoriHeckeAlgebra_nonstandard(A3) + sage: s1,s2,s3 = A3.simple_reflections() + sage: T = H.T(); Cp = H.Cp(); CpC = H.Cp_Coxeter3() + sage: T._to_Cp_basis(s1, Cp) v*Cp[1] + (-u^-1*v^2) sage: Cp(T(s1)) v*Cp[1] + (-u^-1*v^2) - sage: Cp(T(s1)+1) - v*Cp[1] + (-u^-1*v^2+1) - sage: Cp(T(s1*s2)+T(s1)+T(s2)+1) - v^2*Cp[1,2] + (-u^-1*v^3+v)*Cp[1] + (-u^-1*v^3+v)*Cp[2] - + (u^-2*v^4-2*u^-1*v^2+1) - sage: Cp(T(s1*s2*s1)) - v^3*Cp[1,2,1] + (-u^-1*v^4)*Cp[2,1] + (-u^-1*v^4)*Cp[1,2] - + (u^-2*v^5)*Cp[1] + (u^-2*v^5)*Cp[2] + (-u^-3*v^6) + sage: T._to_Cp_basis(s1, CpC) + v*Cp[1] + (-u^-1*v^2) + sage: CpC(T(s1)) + v*Cp[1] + (-u^-1*v^2) """ A = self.realization_of() # Cp = A.Cp() if not use_Cp_Coxeter3 else A.Cp_Coxeter3() @@ -2931,11 +3039,57 @@ def _to_Cp_basis(self, w, Cp): @cached_method def to_Cp_basis(self, w): + r""" + Return `T_w` as a linear combination of `C^{\prime}`-basis elements + + EXAMPLES:: + + sage: H = sage.algebras.iwahori_hecke_algebra.IwahoriHeckeAlgebra_nonstandard("A2") + sage: s1,s2 = H.coxeter_group().simple_reflections() + sage: T = H.T() + sage: Cp = H.Cp() + sage: T.to_Cp_basis(s1) + v*Cp[1] + (-u^-1*v^2) + sage: Cp(T(s1)) + v*Cp[1] + (-u^-1*v^2) + sage: Cp(T(s1)+1) + v*Cp[1] + (-u^-1*v^2+1) + sage: Cp(T(s1*s2)+T(s1)+T(s2)+1) + v^2*Cp[1,2] + (-u^-1*v^3+v)*Cp[1] + (-u^-1*v^3+v)*Cp[2] + + (u^-2*v^4-2*u^-1*v^2+1) + sage: Cp(T(s1*s2*s1)) + v^3*Cp[1,2,1] + (-u^-1*v^4)*Cp[2,1] + (-u^-1*v^4)*Cp[1,2] + + (u^-2*v^5)*Cp[1] + (u^-2*v^5)*Cp[2] + (-u^-3*v^6) + """ A = self.realization_of() return self._to_Cp_basis(w, A.Cp()) @cached_method def to_Cp_Coxeter3_basis(self, w): + r""" + Return `T_w` as a linear combination of `C^{\prime}`-basis elements, + using the ``Cp_Coxeter3`` implementation. + + EXAMPLES:: + + sage: A2 = CoxeterGroup('A2', implementation='coxeter3') + sage: H = sage.algebras.iwahori_hecke_algebra.IwahoriHeckeAlgebra_nonstandard(A2) + sage: s1,s2 = H.coxeter_group().simple_reflections() + sage: T = H.T() + sage: Cp = H.Cp_Coxeter3() + sage: T.to_Cp_Coxeter3_basis(s1) + v*Cp[1] + (-u^-1*v^2) + sage: Cp(T(s1)) + v*Cp[1] + (-u^-1*v^2) + sage: Cp(T(s1)+1) + v*Cp[1] + (-u^-1*v^2+1) + sage: Cp(T(s1*s2)+T(s1)+T(s2)+1) + v^2*Cp[1,2] + (-u^-1*v^3+v)*Cp[1] + (-u^-1*v^3+v)*Cp[2] + + (u^-2*v^4-2*u^-1*v^2+1) + sage: Cp(T(s1*s2*s1)) + v^3*Cp[1,2,1] + (-u^-1*v^4)*Cp[1,2] + (-u^-1*v^4)*Cp[2,1] + + (u^-2*v^5)*Cp[1] + (u^-2*v^5)*Cp[2] + (-u^-3*v^6) + """ A = self.realization_of() return self._to_Cp_basis(w, A.Cp_Coxeter3()) From 236b8b324fc3a6c4ecc409ba8fbb1af6bda35bd8 Mon Sep 17 00:00:00 2001 From: Chase Meadors Date: Fri, 23 Jul 2021 15:37:45 -0600 Subject: [PATCH 054/359] Improve commenting on generator decomposition stuff --- src/sage/algebras/iwahori_hecke_algebra.py | 29 ++++++++++++---------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/sage/algebras/iwahori_hecke_algebra.py b/src/sage/algebras/iwahori_hecke_algebra.py index 128fce56ccf..e3c3bdd4fa9 100644 --- a/src/sage/algebras/iwahori_hecke_algebra.py +++ b/src/sage/algebras/iwahori_hecke_algebra.py @@ -2173,7 +2173,9 @@ def __init__(self, algebra, prefix='Cp'): # TODO: Better error message raise ValueError('the Cp_Coxeter3 basis is only supported in a Hecke algebra with standard normalizations (explain)') - # Construct a free algebra over generators representing the C' generators: { Cp_s : s in S } + # Construct a free algebra over generators representing the Cp generators: { Cp_s : s in S } + # We use this to represent polynomials in the Cp generators. e.g., we represent the element + # Cp_{121} as Cp1*Cp2*Cp1 - Cp1 self._generator_algebra = FreeAlgebra(algebra.base_ring(), ['Cp{}'.format(s) for s in self.index_set()]) # The correspondence between indices and formal generators of the generator algebra self._generators = { s: self._generator_algebra('Cp{}'.format(s)) for s in self.index_set() } @@ -2399,26 +2401,27 @@ class docs enough here. I lean towards describing the algorithm once gen_expression = self._decompose_into_generators(w2) other_element = self.monomial(w1) - # gen_expression is a linear combination of products of the C' generators - # Now, build everything back up, continually multiplying on the left by a single generator at a time + # gen_expression is a linear combination of products of the Cp + # generators. e.g., gen_expression = 2*Cp1*Cp2*Cp1 - Cp1 We now + # perform (2*Cp1*Cp2*Cp1 - Cp1) * other_element by proceeding one + # generator at a time. result = self(0) - # Iterate through the sum of terms + # Proceed through the terms, multiplying each term onto other_element + # and adding that summand onto result. for (p, coeff) in gen_expression: - # p is a product of generators, i.e. 2*g1*g2*g1; multiply it by other_element - # Build summand multiplicatively, going through variables (and their exponents) in p - # If gen_expression is being multiplied on the right, we need to start at the left - # end of p, and vice versa. + # is a term, e.g. p = Cp1*Cp2*Cp1 and coeff = 2 summand = coeff * other_element p_list = list(p) if side == 'right' else list(p)[::-1] - # Iterate through the product of generators + # Iterate through the generators in the term, multiplying each generator + # onto other_element and multiplying the result onto summand. for (gen, exponent) in p_list: + # gen is some formal generator Cp{s} (it is in the + # underlying monoid of self._generator_algebra so coercion + # is required). e.g. gen = Cp1 and exponent = 1. s = self._index_of_generator[self._generator_algebra(gen)] - # gen is in the underlying monoid of _generator_algebra, so coercion is required for i in range(exponent): - # Perform C'_s * summand (on the appropriate side), - # however many times C'_s is represented in the product - # according to the exponent. + # Perform the product C'_s * summand, exponent-many times. summand = self._product_with_generator(side, s, summand) result += summand From b4d7c9e45d46b06cd804d34d45af9bf9f354ad59 Mon Sep 17 00:00:00 2001 From: Chase Meadors Date: Fri, 23 Jul 2021 15:37:54 -0600 Subject: [PATCH 055/359] Remove long-form descriptions from private method docs. --- src/sage/algebras/iwahori_hecke_algebra.py | 49 +--------------------- 1 file changed, 1 insertion(+), 48 deletions(-) diff --git a/src/sage/algebras/iwahori_hecke_algebra.py b/src/sage/algebras/iwahori_hecke_algebra.py index e3c3bdd4fa9..2c74443c0a8 100644 --- a/src/sage/algebras/iwahori_hecke_algebra.py +++ b/src/sage/algebras/iwahori_hecke_algebra.py @@ -2215,25 +2215,6 @@ def _product_with_generator_on_basis(self, side, s, w): Compute the product of `C^{\prime}_s` and `C^{\prime}_w`, putting `C^{\prime}_s` on the given ``side``. - For each generator `s` and element `x`, the products `C^{\prime}_s - \cdot C^{\prime}_w` is given by the following formulas: - - .. MATH:: - - C^{\prime}_s \cdot C^{\prime}_w = - \begin{cases} - (q+q^-1)C^{\prime}_{w}, & \text{if } \ell(sw) = \ell(w)-1,\\ - C^{\prime}_{sw}+\sum_{v\leq w, sv \leq v} \mu(v,w)C^{\prime}_v, & \text{if } \ell(sw) = \ell(w)+1. - \end{cases} - - C^{\prime}_w \cdot C^{\prime}_s = - \begin{cases} - (q+q^-1)C^{\prime}_{w}, & \text{if } \ell(ws) = \ell(w)-1,\\ - C^{\prime}_{ws}+\sum_{v\leq w, vs \leq v} \mu(v,w)C^{\prime}_v, & \text{if } \ell(ws) = \ell(w)+1. - \end{cases} - - where `\leq` is the Bruhat order and the numbers `\mu(v,w)` are the `mu`-coefficients of [Lus2014]_. - INPUT: - ``side`` -- string; 'left' or 'right' @@ -2301,35 +2282,7 @@ def _product_with_generator(self, side, s, x): def _decompose_into_generators(self, w): r""" Decompose `C^{\prime}_w` into a polynomial in the KL generators - `C^{\prime}_s` (an element of the free algebra - `self.generator_algebra`) - - The decomposition is obtained recursively, by induction on - `\ell(w)`. If `ell(w) < 2` the decomposition is trivial (see - Examples). If `\ell(w) \geq 2`, write `w=su` where `s` is a left - descent of `w` so that `\ell(w) = \ell(u) + 1`, then use the formula - that - - .. MATH:: - C^{\prime}_s \cdot C^{\prime}_u = - C^{\prime}_{su}+\sum_{v\leq u, sv \leq v} \mu(v,u)C^{\prime}_v - - to conclude that - - .. MATH:: - C^{\prime}_{w}= C^{\prime}_s \cdot C^{\prime}_u - \sum_{v\leq u, sv \leq v} \mu(v,u)C^{\prime}_v. - - The element `u` and the elements `v` on the right side all have - smaller length than `w`, so they can be obtained by induction. - - INPUT: - - - ``w`` -- word in self.coxeter_group() - - OUTPUT: - - An element of ``self._generator_algebra`` describing how to express - `C^{\prime}_w` in terms of the generators `C^{\prime}_s`. + `C^{\prime}_s`. EXAMPLES:: From 89c8ee33b913e143bae9404cfdab2c62195b896a Mon Sep 17 00:00:00 2001 From: Tianyuan Xu Date: Wed, 28 Jul 2021 15:57:37 -0600 Subject: [PATCH 056/359] more docstring edits --- build/pkgs/sage_sws2rst/src | 1 - src/sage/algebras/iwahori_hecke_algebra.py | 311 +++++++++++++-------- 2 files changed, 191 insertions(+), 121 deletions(-) delete mode 120000 build/pkgs/sage_sws2rst/src diff --git a/build/pkgs/sage_sws2rst/src b/build/pkgs/sage_sws2rst/src deleted file mode 120000 index 2de26d80e1e..00000000000 --- a/build/pkgs/sage_sws2rst/src +++ /dev/null @@ -1 +0,0 @@ -../../../pkgs/sage-sws2rst \ No newline at end of file diff --git a/src/sage/algebras/iwahori_hecke_algebra.py b/src/sage/algebras/iwahori_hecke_algebra.py index 2c74443c0a8..40d60fd1835 100644 --- a/src/sage/algebras/iwahori_hecke_algebra.py +++ b/src/sage/algebras/iwahori_hecke_algebra.py @@ -2004,136 +2004,152 @@ class Cp_Coxeter3(_KLHeckeBasis): Directly compute products in the `C^{\prime}`-basis by using du Cloux's Coxeter3 package. - TODO: [State assumptions] normalization/coxeter3 implementation + To use this class, the Hecke algebra needs to be created in the + "standard" presentation where `\{q_1,q_2\} = \{v^2,1\}` as sets or the + "normalized" presentations where `\{q_1,q_2\} = \{v,-v^-1\}` as sets. + The Hecke algebra also needs to be created from a Coxeter group defined + using the 'coxeter3' implementation; see the examples to follow. Expanding products of the form `C^{\prime}_x \cdot C^{\prime}_y` in the `C^{\prime}`-basis is useful for computing Kazhdan-Lusztig cells of Coxeter systems and the corresponding cell modules of Iwahori-Hecke - algebras. Such expansion is controlled by the following formula (and - the analogous formula for `C^{\prime}_s \cdot C^{\prime}_w`) under both - the "standard" and the "normalized" presentations of the Iwahori-Hecke - algebra, where the quadratic relation is `(T_s-q^2)(T_s+1)=0` and - `(T_s-q)(T_s+q^-1)=0` for each generator `s`, respectively. - - .. MATH:: C^{\prime}_s \cdot C^{\prime}_w = \begin{cases} - (q+q^-1)C^{\prime}_{w}, & - \text{if } \ell(sw) = \ell(w)-1,\\ - C^{\prime}_{sw}+\sum_{v\leq w, sv \leq v} \mu(v,w)C^{\prime}_v, & - \text{if } \ell(sw) = \ell(w)+1. \end{cases} - - where `\leq` is the Bruhat order on the underlying Coxeter group and + algebras. The emphasis of this class is to compute such products more + directly in the `C^{\prime}`-basis, as opposed to converting the + `C^{\prime}`-basis to the `T`-basis, calculating the product in the + `T`-basis, and converting the results back to the `C^{\prime}`-basis + (see Line 1303). The latter approach is used in the + _Basis.product_on_basis method on Line 1298. The direct + method significantly speeds up the product computations. + + The following formulas for products of the forms `C^{\prime}_s \cdot + C^{\prime}_w` and `C^{\prime}_w \cdot C^{\prime}_s`, where `s` is a + generator of the Coxeter group and `w` an arbitrary element, are key to + this class. The formulas are valid for both the standard and normalized + presentation of the Hecke algebra, and they control the products of the + `C^{\prime}_x \cdot C^{\prime}_y` for arbitrary `x,y`. + + .. MATH:: + C^{\prime}_s \cdot C^{\prime}_w = + \begin{cases} + (q+q^-1)C^{\prime}_{w}, & \text{if } \ell(sw) = \ell(w)-1,\\ + C^{\prime}_{sw}+\sum_{v\leq w, sv \leq v} \mu(v,w)C^{\prime}_v, + & \text{if } \ell(sw) = \ell(w)+1. + \end{cases} + + C^{\prime}_w \cdot C^{\prime}_s = + \begin{cases} + (q+q^-1)C^{\prime}_{w}, & \text{if } \ell(ws) = \ell(w)-1,\\ + C^{\prime}_{ws}+\sum_{v\leq w, vs \leq v} \mu(v,w)C^{\prime}_v, + & \text{if } \ell(ws) = \ell(w)+1. + \end{cases} + + In the above, `\leq` is the Bruhat order on the Coxeter group and `\mu(v,w)` is the "leading coefficient of Kazhdan-Lusztig polynomials"; - see [KL1979]_ and [Lus2014]_ for more details. - - The emphasis of this class is to compute products in the - `C^{\prime}`-basis directly, by using the above formula and calling the - necessary `\mu`-coefficients from Sage's implementation of Fokko du - Cloux's Coxeter3 package. This methods computes the products faster than - the _Basis.product_on_basis method on Line 1298, which needs to convert - the `C^{\prime}`-basis to the `T`-basis, calculate the product in the - `T`-basis, and convert the results back to the `C^{\prime}`-basis. For - example, the product `C^{\prime}_{32345} * C^{\prime}_{23}` in the Hecke - algebra of type 'B_9' takes more than 30 seconds with the latter method - but is instant using this class. - - .. TODO:: - - Use the analog of the displayed formula to implement - `C^{\prime}`-products in the multi-parameter Iwahori-Hecke algebra; - see Section 6 of [Lus2013]_. - + see [KL1979]_ and [Lus2014]_ for more details. The method designates + the computation of the `\mu`-coefficients to Fokko du Cloux's + 'coxeter3' package (wrapped in Sage), which is why the method requires + the creation of the Coxeter group in the 'coxeter3' implementation. + EXAMPLES: Basic usage:: + + # To create the basis, define the Coxeter group with 'coxeter3' and + # the Hecke algebra with the standard or normalized presentation. sage: R. = LaurentPolynomialRing(ZZ) sage: A3 = CoxeterGroup('A3', implementation='coxeter3') - sage: s1, s2, s3 = A3.simple_reflections() - sage: H = IwahoriHeckeAlgebra(A3, v**2) + sage: H = IwahoriHeckeAlgebra(A3, v**2) # standard presentation sage: Cp = H.Cp_Coxeter3() + + # TODO: 1. avoid Cp, maybe CpC or CpC3? 2. show that CpC3 IS Cp (more reason for 1) + + sage: s1, s2, s3 = A3.simple_reflections() sage: Cp(s1*s2*s1) Cp[1,2,1] sage: Cp(s1)**2 (v^-1+v)*Cp[1] sage: Cp(s1)*Cp(s2)*Cp(s1) Cp[1,2,1] + Cp[1] - sage: Cp[1]*Cp[2]*Cp[3]*Cp[1]*Cp[2] + + The following computation take a long time in the + _Basis.product_on_basis method as mentioned on Line 1941, but it is + instant in the current method :: + + sage: Cp[1]*Cp[2]*Cp[3]*Cp[1]*Cp[2] Cp[1,2,1,3,2] + Cp[1,2,1] + Cp[1,3,2] - The IwahoriHeckeAlgebra must be initialized with a ``CoxeterGroup`` - implemented with coxeter3 and the Hecke parameters must be v^2, -1 or v, - -1/v:: + Another example, with the Hecke algebra of type `B9` in the normalized + presentation :: + + sage: B9 = CoxeterGroup(CoxeterType(['B', 9]).relabel({ i: 9-i+1 for i in range(1, 10) }), implementation='coxeter3') + # the (optional) relabeling above ensures `m(1,2)=4`, i.e., that + # the generators 1, 2 form the strong bond in the Dynkin diagram. + + sage: H = IwahoriHeckeAlgebra(B9, v, -1/v) + sage: Cp = H.Cp_Coxeter3() + sage: Cp[1,2,1,2] + Cp[1,2,1,2] + + The following computation also takes a long time in + _Basis.product_on_basis, but it is instant here :: + + sage: Cp[3,2,3,4,5] * Cp[2,3] + (v^-1+v)*Cp[2,3,2,4,3,5] + (v^-1+v)*Cp[2,3,2,5] + + Directly creating a Hecke algebra from its Coxeter type does not work + currently. Instead, a Coxeter group implemented with 'coxeter3' must be + created first :: sage: H = IwahoriHeckeAlgebra('A3', v**2) sage: H.Cp_Coxeter3() Traceback (most recent call last): ... ValueError: algebra must be initialized with a coxeter3-implemented Coxeter group to use the Cp_Coxeter3 basis + + With the Coxeter group created first, the Hecke algebra must be defined + with the standard or normalized presentation mentioned before :: + sage: A3 = CoxeterGroup('A3', implementation='coxeter3') - sage: H = IwahoriHeckeAlgebra(A3, QQ(1)) + sage: H = IwahoriHeckeAlgebra(A3, QQ(1)) sage: H.Cp_Coxeter3() Traceback (most recent call last): ... - ValueError: the Cp_Coxeter3 basis is only supported in a Hecke algebra with standard normalizations (explain) - - Products of the form `Cp_s \cdot Cp_y` where `s` is a generator are - computed by the earlier formula:: + ValueError: the Cp_Coxeter3 basis is only supported in a Hecke + algebra with the standard or normalized presentations (i.e., need + `\{q_1,q_2\} = \{v^2,1\}` or `\{q_1,q_2\} = \{v,-v^-1\}` as sets) + sage: H.Cp_Coxeter3() + - sage: A3 = CoxeterGroup('A3', implementation='coxeter3') - sage: H = IwahoriHeckeAlgebra(A3, v**2) - sage: Cp = H.Cp_Coxeter3() - sage: Cp[1] * Cp[1] - (v^-1+v)*Cp[1] - sage: Cp[1] * Cp[2] - Cp[1,2] - sage: Cp[1] * Cp[2,1] - Cp[1,2,1] + Cp[1] - sage: Cp[1] * Cp[2,1,3] - Cp[1,2,1,3] + Cp[1,3] - sage: Cp[2] * Cp[1,3,2,1,3] - Cp[1,2,1,3,2,1] + Cp[1,2,1,3] + Cp[2,3,2,1] - More generally, we can compute products of the form `C^{\prime}_x \cdot - C^{\prime}_y` for general `x, y`:: + ALGORITHM : + Write `b` for `C^{\prime}`. This class computes each product `b_x + \cdot b_y` as follows. - sage: Cp[1,2,1] * Cp[3,1] - (v^-1+v)*Cp[1,2,1,3] - sage: Cp[1,2,1] * Cp[3,1,2] - (v^-1+v)*Cp[1,2,1,3,2] + (v^-1+v)*Cp[1,2,1] + If `\ell(x) \leq \ell(y)`, then we first decompose `b_x` into a + polynomial in the generators `b_s (s\in S)` and then multiply that + polynomial with `b_y`. Both steps are carried out by repeated + application of the formula for `b_s * b_w` mentioned before. For + example, in the computation of the product `b[1,2,1] * b[3,1,2]` in + type `A3`, the left term `b_{121}` is first decomposed into the + linear combination `b_1*b_2*b_1 - b_1` behind the scenes. - We can compute complex products in in type `B9`, while relabelling the - generators so that the long braid is between the first two generators:: - - sage: B9 = CoxeterGroup(CoxeterType(['B', 9]).relabel({ i: 9-i+1 for i in range(1, 10) }), implementation='coxeter3') - sage: H = IwahoriHeckeAlgebra(B9, v, -1/v) - sage: Cp = H.Cp_Coxeter3() - sage: Cp[1,2,1,2] - Cp[1,2,1,2] - sage: Cp[3,2,3,4,5] * Cp[2,3] - (v^-1+v)*Cp[2,3,2,4,3,5] + (v^-1+v)*Cp[2,3,2,5] - - - .. NOTE:: - - The products `B_x \cdot B_y` are computed as follows: if - `\ell(x) \leq \ell(y)`, then we first decompose `B_x` into a - polynomial in the generators `B_s (s\in S)`, then multiplies that - linear combination onto `B_y`; otherwise we decompose `B_y` and - multiply the result onto `B_x`. For example, in the computation of - `B[1,2,1] * B[3,1,2]` in type `A3`, the left term `B[1,2,1]` is - first (essentially) decomposed into the linear combination - `B[1]*B[2]*B[1] - B[1]` behind the scenes. The decomposition is - achieved via the [_decompose_into_generators function], which takes - an element `B_w` and gives an element of the free algebra over \{ - B_s \; : \; s \in S \}, whose image under the canonical homomorphism - from the free algebra is precisely `B_w`. + If `\ell(x) > \ell(y)`, we decompose `b_y` into a polynomial in + `b_s (s\in S)` and multiply that polynomial with `b_x`. .. SEEALSO:: + # TODO: edit the following + :ref: [KL1979]_, [Lus2013]_ - :meth:`sage.somewhere.other_useful_method`, cell stuff - [coxeter3?] + :meth: _Basis.product_on_basis, cell stuff + :package?[coxeter3?] + .. TODO:: + + Use the analog of the displayed formulas to implement + `C^{\prime}`-products in the multi-parameter Iwahori-Hecke algebra; + see Section 6 of [Lus2013]_. """ _basis_name = 'Cp_Coxeter3' @@ -2144,6 +2160,8 @@ def __init__(self, algebra, prefix='Cp'): EXAMPLES:: + TODO: Do we still need all these here? Space after (to + separate good and bad) sage: R. = LaurentPolynomialRing(ZZ, 'v') sage: A3 = CoxeterGroup('A3', implementation='coxeter3') sage: H = IwahoriHeckeAlgebra(A3, v**2) @@ -2170,12 +2188,24 @@ def __init__(self, algebra, prefix='Cp'): else: if not algebra._is_generic: # If this algebra is generic, it's only being used to coerce to the T basis, not perform computations - # TODO: Better error message - raise ValueError('the Cp_Coxeter3 basis is only supported in a Hecke algebra with standard normalizations (explain)') + # TODO: Better error message (TX made some changes) + raise ValueError('the Cp_Coxeter3 basis is only supported in a Hecke algebra with the standard or normalized presentations (i.e., need `\{q_1,q_2\} = \{v^2,1\}` or `\{q_1,q_2\} = \{v,-v^-1\}` as sets)') + + # TODO: change the name systematically, bad to use Cp. (sorry I + # went back to g) + + # Construct a free algebra over generators {g_s:s in S} + # The free algebra is merely a formal device to encode polynomials + # in the `C^{prime}`-basis. For example, we mentioned in + # "ALGORITHM" how it is useful to decompose `b_{121}` to the + # polynomial `b_1*b_2* b_1 - b_1` where `b` stands for + # `C^{\prime}`. The polynomial will be encoded as `g_1*g_2*g_1 - + # g_1`. While this formal construction may seem unnecessary, it + # appears to be the most convenient way to encode the polynomials + # mentioned above, and we are not able to remove it at the moment. + + # TODO: better explain the last sentence, maybe with an example? - # Construct a free algebra over generators representing the Cp generators: { Cp_s : s in S } - # We use this to represent polynomials in the Cp generators. e.g., we represent the element - # Cp_{121} as Cp1*Cp2*Cp1 - Cp1 self._generator_algebra = FreeAlgebra(algebra.base_ring(), ['Cp{}'.format(s) for s in self.index_set()]) # The correspondence between indices and formal generators of the generator algebra self._generators = { s: self._generator_algebra('Cp{}'.format(s)) for s in self.index_set() } @@ -2215,6 +2245,9 @@ def _product_with_generator_on_basis(self, side, s, w): Compute the product of `C^{\prime}_s` and `C^{\prime}_w`, putting `C^{\prime}_s` on the given ``side``. + # TODO: again, 'Cp' might be bad; put left as default side (since s + # comes before w in the input tuple)? + INPUT: - ``side`` -- string; 'left' or 'right' @@ -2230,16 +2263,21 @@ def _product_with_generator_on_basis(self, side, s, w): sage: H = IwahoriHeckeAlgebra(A3, v**2); Cp=H.Cp_Coxeter3() sage: Cp._product_with_generator_on_basis('left', 1, A3([2,1])) Cp[1,2,1] + Cp[1] + sage: Cp._product_with_generator_on_basis('right', 1, A3([2,1])) + (v+v^-1) * Cp[1] sage: Cp._product_with_generator_on_basis('right', 2, A3([1,3,2,1,3])) Cp[1,2,1,3,2,1] + Cp[1,2,3,2] + Cp[1,3,2,1] """ - + + # TODO: consistency in our docstring: ticks or not + other things. + + # If `s` is a descent of `w` on the `side`, the product is (v + v^-1) C'_w: if w.has_descent(s, side=side): - # TODO: notation? - # Descent case, return (q + q^-1) C'_w return self.delta * self.monomial(w) + # Otherwise the product is \sum_{v \leq w; sv < v} mu(v, w) C'_v + # if `side` is left and \sum_{v \leq w; vs < v} mu(v, w) C'_s if + # `side` is right, as mentioned before. else: - # Additively build the sum \sum_{v \leq w; sv < v} mu(v, w) C'_v element = self(0) between = self._W.bruhat_interval([], w) for x in between: @@ -2249,15 +2287,17 @@ def _product_with_generator_on_basis(self, side, s, w): # Compute mu-coefficient via coxeter3 element += x.mu_coefficient(w) * self.monomial(x_elt) - # Doing self._W([s]) * w may not ensure that the word is is normal form - # Since W's element constructor does ensure that, use this method. - longer_word = self._W([s] + list(w) if side == 'left' else list(w) + [s]) - return self.monomial(longer_word) + element + # Doing self._W([s]) * w may not ensure that the word is + # normal form Since W's element constructor does ensure that, + # use the constructor. + # TODO: change the above for better reader friendliness. + longer_word = self._W([s] + list(w) if side == 'left' else + list(w) + [s]) return self.monomial(longer_word) + + element - def _product_with_generator(self, side, s, x): - r""" - Compute the product of `C^{\prime}_s` with any linear combination of - `C^{\prime}`-basis elements. + def _product_with_generator(self, side, s, x): + r""" + Compute the product of `C^{\prime}_s` with any linear combination of `C^{\prime}`-basis elements. INPUT: @@ -2284,27 +2324,60 @@ def _decompose_into_generators(self, w): Decompose `C^{\prime}_w` into a polynomial in the KL generators `C^{\prime}_s`. + For every element `y\in W` with length `\ell(w)>1` and every left descent `s` of + `y`, write `y=sw` (so `x=sw`) and note that + + .. MATH:: + C^{\prime}_y = C^{\prime}_s * C^{\prime}_{w} - \sum_{v\le w; sv< + v} \mu(v,w) C^{\prime}_v + + by the formula for `C^{\prime}_s * C^{\prime}_w`. All `v`'s in the + sum on the right side are lower than `w` in the Bruhat order and + hence shorter than `w`, so the above formula allows us to decompose + `C^{\prime}_y` into the generators `C^{\prime}_s` by induction on + `\ell(y)`, with the base case being `\ell(y)=1` where `y` is itself + a Coxeter generator. (For the group identity `e` we have `C_e=1` in + the Hecke algebra.) + EXAMPLES:: + + # TODO: fix notation sage: R. = LaurentPolynomialRing(ZZ, 'v') sage: A3 = CoxeterGroup('A3', implementation='coxeter3') sage: H = IwahoriHeckeAlgebra(A3, v**2); Cp=H.Cp_Coxeter3() - sage: Cp._decompose_into_generators(A3([1,2])) # C_{12} = C_1C_2 - Cp1*Cp2 + + When `y` is itself a generator `s`, the decomposition is trivial :: + + sage: Cp._decompose_into_generators(A3([1])) + Cp[1] + + Another example, where it happens that `C^{\prime}_y = C^{\prime}_s * C^{\prime}_{w}` exactly :: + + sage: Cp._decompose_into_generators(A3([2,1])) # C_{21} = C_2C_1 + Cp[2]*Cp[1] + + In more general situations the sum is a linear combination because + of the lower order terms `v`'s that can appear in each intermediate + step; for example, we have C_121=C_1*C_21 - C_1= C_1*C_2*C_1-C_1 :: + sage: Cp._decompose_into_generators(A3([1,2,1])) # C_{121} = C_1C_2C_1 - C_1 -Cp1 + Cp1*Cp2*Cp1 sage: Cp._decompose_into_generators(A3([1,2,3,1,2])) Cp1 - Cp1*Cp2*Cp1 - Cp1*Cp3*Cp2 + Cp1*Cp2*Cp1*Cp3*Cp2 """ + # \ell(y) < 1 if len(w) == 0: return self.generator_algebra(1) if len(w) == 1: return self._generators[w[0]] - + # \ell(y) > 1, we use the induction on `\ell(y)` and recursively + # find the decomposition s = w[0] w1 = w[1:] - + # TODO: remove some doc strings below. We've explained the ideas in enough detail. + # Additively build the sum term (lower order terms) sum_term = self(0) between = self._W.bruhat_interval([], w1) @@ -2329,9 +2402,12 @@ def product_on_basis(self, w1, w2): Return the expansion of `C^{\prime}_{w_1} \cdot C^{\prime}_{w_2}` in the `C^{\prime}`-basis. + The product is computed in the two steps as described in "ALGORITHM". + + # When `w` is the identity, `C_w` is the identity of the algebra. TODO: Describe our decision to decompose the smaller word...? Or is class docs enough here. I lean towards describing the algorithm once - in the class docs. + in the class docs. AGREED! EXAMPLES:: @@ -2343,8 +2419,8 @@ class docs enough here. I lean towards describing the algorithm once sage: Cp.product_on_basis(A3([1,2,1]), A3([3,1,2])) (v^-1+v)*Cp[1,2,1,3,2] + (v^-1+v)*Cp[1,2,1] """ - # Otherwise, decompose the first word into generators - # (as expressed as an element of the FreeAlgebra over 'generator' variables g1, ..., gn) + # Decompose one of `C_{w_1}` and `C_{w_2}` into a polynomial in the + # generators, then multiply the remaining one with the polynomial. if len(w1) <= len(w2): side = 'left' gen_expression = self._decompose_into_generators(w1) @@ -2354,11 +2430,6 @@ class docs enough here. I lean towards describing the algorithm once gen_expression = self._decompose_into_generators(w2) other_element = self.monomial(w1) - # gen_expression is a linear combination of products of the Cp - # generators. e.g., gen_expression = 2*Cp1*Cp2*Cp1 - Cp1 We now - # perform (2*Cp1*Cp2*Cp1 - Cp1) * other_element by proceeding one - # generator at a time. - result = self(0) # Proceed through the terms, multiplying each term onto other_element # and adding that summand onto result. From ce7d2edb0a45a72ae6c34cb10ea93740464be9bb Mon Sep 17 00:00:00 2001 From: Tianyuan Xu Date: Wed, 28 Jul 2021 17:58:33 -0600 Subject: [PATCH 057/359] edit ALGORITHM and doc string for the decomposition step --- src/sage/algebras/iwahori_hecke_algebra.py | 105 ++++++++++----------- 1 file changed, 52 insertions(+), 53 deletions(-) diff --git a/src/sage/algebras/iwahori_hecke_algebra.py b/src/sage/algebras/iwahori_hecke_algebra.py index 40d60fd1835..cc43dee34a2 100644 --- a/src/sage/algebras/iwahori_hecke_algebra.py +++ b/src/sage/algebras/iwahori_hecke_algebra.py @@ -2079,15 +2079,15 @@ class Cp_Coxeter3(_KLHeckeBasis): sage: Cp[1]*Cp[2]*Cp[3]*Cp[1]*Cp[2] Cp[1,2,1,3,2] + Cp[1,2,1] + Cp[1,3,2] - Another example, with the Hecke algebra of type `B9` in the normalized - presentation :: + Below is another example, with the Hecke algebra of type `B9` in the normalized + presentation. The (optional) relabeling command ensures that `m(1,2)=4`, i.e., that + the generators 1, 2 form the strong bond in the Dynkin diagram. :: sage: B9 = CoxeterGroup(CoxeterType(['B', 9]).relabel({ i: 9-i+1 for i in range(1, 10) }), implementation='coxeter3') - # the (optional) relabeling above ensures `m(1,2)=4`, i.e., that - # the generators 1, 2 form the strong bond in the Dynkin diagram. - sage: H = IwahoriHeckeAlgebra(B9, v, -1/v) - sage: Cp = H.Cp_Coxeter3() + sage: Cp = H.Cp_Coxeter3() + + # TODO: create s1 to s9 sage: Cp[1,2,1,2] Cp[1,2,1,2] @@ -2118,25 +2118,44 @@ class Cp_Coxeter3(_KLHeckeBasis): ValueError: the Cp_Coxeter3 basis is only supported in a Hecke algebra with the standard or normalized presentations (i.e., need `\{q_1,q_2\} = \{v^2,1\}` or `\{q_1,q_2\} = \{v,-v^-1\}` as sets) - sage: H.Cp_Coxeter3() - ALGORITHM : Write `b` for `C^{\prime}`. This class computes each product `b_x - \cdot b_y` as follows. + \cdot b_y` in two steps as follows. If `\ell(x) \leq \ell(y)`, then we first decompose `b_x` into a polynomial in the generators `b_s (s\in S)` and then multiply that - polynomial with `b_y`. Both steps are carried out by repeated - application of the formula for `b_s * b_w` mentioned before. For - example, in the computation of the product `b[1,2,1] * b[3,1,2]` in - type `A3`, the left term `b_{121}` is first decomposed into the - linear combination `b_1*b_2*b_1 - b_1` behind the scenes. + polynomial with `b_y`. If `\ell(x) > \ell(y)`, we decompose `b_y` + into a polynomial in `b_s (s\in S)` and multiply that polynomial + with `b_x`. The second step (multiplication) is done by repeatedly + applying the key formulas displayed earlier directly. The first + step (decomposition) is done by induction on the Bruhat order as + follows: for every element `u\in W` with length `\ell(u)>1` and + every left descent `s` of `u`, write `u=sw` (so `w=su`) and note + that - If `\ell(x) > \ell(y)`, we decompose `b_y` into a polynomial in - `b_s (s\in S)` and multiply that polynomial with `b_x`. + .. MATH:: + C^{\prime}_u = C^{\prime}_s * C^{\prime}_{w} - \sum_{v\le u; sv< + v} \mu(v,w) C^{\prime}_v + by the key formulas, where the element `w` and all elements `v`'s + on the right side are lower than `u` in the Bruhat order; this + allows us to finish the computation by decomposing the lower order + terms `b_w` and each `b_v`. For example, for `u=121, s=1, w=21` in + type `A3` we have + + .. MATH:: + b_{121} = b_1*b_{21} - b_1, + + where the lower order term `b_{21}` further decomposes into + `b_2*b_1`, therefore `b_{121}=b_1*b_2 b_1 -b1`. We note that the + the base cases `\ell(x)=1` or `\ell(x)=0` of the above induction + occur when `x` is itself a Coxeter generator `s` or the group + identity, respectively. The decomposition is trivial in these cases + (we have `C_x=C_s` or `C_x=1`, the unit of the Hecke algebra). + + .. SEEALSO:: # TODO: edit the following @@ -2147,6 +2166,9 @@ class Cp_Coxeter3(_KLHeckeBasis): .. TODO:: + Accommodate generic presentations of the Hecke algebra other than + the standard and normalized ones. + Use the analog of the displayed formulas to implement `C^{\prime}`-products in the multi-parameter Iwahori-Hecke algebra; see Section 6 of [Lus2013]_. @@ -2167,6 +2189,7 @@ def __init__(self, algebra, prefix='Cp'): sage: H = IwahoriHeckeAlgebra(A3, v**2) sage: Cp = H.Cp_Coxeter3() + sage: H = IwahoriHeckeAlgebra('A3', v**2) sage: Cp = H.Cp_Coxeter3() Traceback (most recent call last): @@ -2184,7 +2207,7 @@ def __init__(self, algebra, prefix='Cp'): # TODO: rewrite this horribly ugly condition: if v != algebra.base_ring().one() and ((algebra.q1() == v**2 and algebra.q2() == -1) or (algebra.q1() == v and algebra.q2() == -1/v)): - self.delta = v + ~v + self.delta = v + ~v # TODO: this is why we need the two normalizations else: if not algebra._is_generic: # If this algebra is generic, it's only being used to coerce to the T basis, not perform computations @@ -2245,8 +2268,7 @@ def _product_with_generator_on_basis(self, side, s, w): Compute the product of `C^{\prime}_s` and `C^{\prime}_w`, putting `C^{\prime}_s` on the given ``side``. - # TODO: again, 'Cp' might be bad; put left as default side (since s - # comes before w in the input tuple)? + # TODO: again, 'Cp' might be bad; INPUT: @@ -2286,14 +2308,12 @@ def _product_with_generator_on_basis(self, side, s, w): if x_elt.has_descent(s, side=side): # Compute mu-coefficient via coxeter3 element += x.mu_coefficient(w) * self.monomial(x_elt) - + # TODO: do something about the following; there's the bug fix now # Doing self._W([s]) * w may not ensure that the word is # normal form Since W's element constructor does ensure that, # use the constructor. - # TODO: change the above for better reader friendliness. - longer_word = self._W([s] + list(w) if side == 'left' else - list(w) + [s]) return self.monomial(longer_word) + - element + longer_word = self._W([s] + list(w) if side == 'left' else list(w) + [s]) + return self.monomial(longer_word) + element def _product_with_generator(self, side, s, x): r""" @@ -2319,25 +2339,11 @@ def _product_with_generator(self, side, s, x): """ return self.linear_combination((self._product_with_generator_on_basis(side, s, w), coeff) for (w, coeff) in x) - def _decompose_into_generators(self, w): + def _decompose_into_generators(self, w): r""" Decompose `C^{\prime}_w` into a polynomial in the KL generators - `C^{\prime}_s`. - - For every element `y\in W` with length `\ell(w)>1` and every left descent `s` of - `y`, write `y=sw` (so `x=sw`) and note that - - .. MATH:: - C^{\prime}_y = C^{\prime}_s * C^{\prime}_{w} - \sum_{v\le w; sv< - v} \mu(v,w) C^{\prime}_v + `C^{\prime}_s`; see "ALGORITHM". - by the formula for `C^{\prime}_s * C^{\prime}_w`. All `v`'s in the - sum on the right side are lower than `w` in the Bruhat order and - hence shorter than `w`, so the above formula allows us to decompose - `C^{\prime}_y` into the generators `C^{\prime}_s` by induction on - `\ell(y)`, with the base case being `\ell(y)=1` where `y` is itself - a Coxeter generator. (For the group identity `e` we have `C_e=1` in - the Hecke algebra.) EXAMPLES:: @@ -2348,25 +2354,23 @@ def _decompose_into_generators(self, w): sage: H = IwahoriHeckeAlgebra(A3, v**2); Cp=H.Cp_Coxeter3() When `y` is itself a generator `s`, the decomposition is trivial :: - - sage: Cp._decompose_into_generators(A3([1])) + sage: w= A3([1]) + sage: Cp._decompose_into_generators(w) Cp[1] - Another example, where it happens that `C^{\prime}_y = C^{\prime}_s * C^{\prime}_{w}` exactly :: + Another example, where `C^{\prime}_y` happens to be a monomial :: sage: Cp._decompose_into_generators(A3([2,1])) # C_{21} = C_2C_1 Cp[2]*Cp[1] - In more general situations the sum is a linear combination because - of the lower order terms `v`'s that can appear in each intermediate - step; for example, we have C_121=C_1*C_21 - C_1= C_1*C_2*C_1-C_1 :: + In more general situations the sum is a polynomial :: sage: Cp._decompose_into_generators(A3([1,2,1])) # C_{121} = C_1C_2C_1 - C_1 -Cp1 + Cp1*Cp2*Cp1 sage: Cp._decompose_into_generators(A3([1,2,3,1,2])) Cp1 - Cp1*Cp2*Cp1 - Cp1*Cp3*Cp2 + Cp1*Cp2*Cp1*Cp3*Cp2 """ - # \ell(y) < 1 + # \ell(y) \leq 1 if len(w) == 0: return self.generator_algebra(1) if len(w) == 1: @@ -2404,11 +2408,6 @@ def product_on_basis(self, w1, w2): The product is computed in the two steps as described in "ALGORITHM". - # When `w` is the identity, `C_w` is the identity of the algebra. - TODO: Describe our decision to decompose the smaller word...? Or is - class docs enough here. I lean towards describing the algorithm once - in the class docs. AGREED! - EXAMPLES:: sage: R. = LaurentPolynomialRing(ZZ, 'v') @@ -2429,7 +2428,6 @@ class docs enough here. I lean towards describing the algorithm once side = 'right' gen_expression = self._decompose_into_generators(w2) other_element = self.monomial(w1) - result = self(0) # Proceed through the terms, multiplying each term onto other_element # and adding that summand onto result. @@ -2451,6 +2449,7 @@ class docs enough here. I lean towards describing the algorithm once result += summand return result + class C(_KLHeckeBasis): r""" From 235b4f9305cf03ab1664f375e5135af6de1474ab Mon Sep 17 00:00:00 2001 From: Chase Meadors Date: Wed, 28 Jul 2021 18:41:56 -0600 Subject: [PATCH 058/359] Fix documentation formatting --- src/sage/algebras/iwahori_hecke_algebra.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/algebras/iwahori_hecke_algebra.py b/src/sage/algebras/iwahori_hecke_algebra.py index cc43dee34a2..b95be14a75d 100644 --- a/src/sage/algebras/iwahori_hecke_algebra.py +++ b/src/sage/algebras/iwahori_hecke_algebra.py @@ -2316,8 +2316,8 @@ def _product_with_generator_on_basis(self, side, s, w): return self.monomial(longer_word) + element def _product_with_generator(self, side, s, x): - r""" - Compute the product of `C^{\prime}_s` with any linear combination of `C^{\prime}`-basis elements. + r""" + Compute the product of `C^{\prime}_s` with any linear combination of `C^{\prime}`-basis elements. INPUT: From a1c8da901e2e45aa81310414a75beabbc898a070 Mon Sep 17 00:00:00 2001 From: Chase Meadors Date: Wed, 28 Jul 2021 18:57:52 -0600 Subject: [PATCH 059/359] Remove the free algebra in _decompose_into_generators; use dictionaries --- src/sage/algebras/iwahori_hecke_algebra.py | 96 ++++++++-------------- 1 file changed, 35 insertions(+), 61 deletions(-) diff --git a/src/sage/algebras/iwahori_hecke_algebra.py b/src/sage/algebras/iwahori_hecke_algebra.py index b95be14a75d..4737788cc10 100644 --- a/src/sage/algebras/iwahori_hecke_algebra.py +++ b/src/sage/algebras/iwahori_hecke_algebra.py @@ -2214,26 +2214,6 @@ def __init__(self, algebra, prefix='Cp'): # TODO: Better error message (TX made some changes) raise ValueError('the Cp_Coxeter3 basis is only supported in a Hecke algebra with the standard or normalized presentations (i.e., need `\{q_1,q_2\} = \{v^2,1\}` or `\{q_1,q_2\} = \{v,-v^-1\}` as sets)') - # TODO: change the name systematically, bad to use Cp. (sorry I - # went back to g) - - # Construct a free algebra over generators {g_s:s in S} - # The free algebra is merely a formal device to encode polynomials - # in the `C^{prime}`-basis. For example, we mentioned in - # "ALGORITHM" how it is useful to decompose `b_{121}` to the - # polynomial `b_1*b_2* b_1 - b_1` where `b` stands for - # `C^{\prime}`. The polynomial will be encoded as `g_1*g_2*g_1 - - # g_1`. While this formal construction may seem unnecessary, it - # appears to be the most convenient way to encode the polynomials - # mentioned above, and we are not able to remove it at the moment. - - # TODO: better explain the last sentence, maybe with an example? - - self._generator_algebra = FreeAlgebra(algebra.base_ring(), ['Cp{}'.format(s) for s in self.index_set()]) - # The correspondence between indices and formal generators of the generator algebra - self._generators = { s: self._generator_algebra('Cp{}'.format(s)) for s in self.index_set() } - self._index_of_generator = { v: k for (k, v) in self._generators.items() } - # Define conversion to the other Cp basis self.module_morphism(self.to_Cp_basis, codomain=algebra.Cp(), category=self.category() ).register_as_coercion() @@ -2342,39 +2322,40 @@ def _product_with_generator(self, side, s, x): def _decompose_into_generators(self, w): r""" Decompose `C^{\prime}_w` into a polynomial in the KL generators - `C^{\prime}_s`; see "ALGORITHM". - - - EXAMPLES:: - - # TODO: fix notation + `C^{\prime}_s`; see "ALGORITHM". TODO: Reference "ALGORITHM" + + EXAMPLES: + + :: sage: R. = LaurentPolynomialRing(ZZ, 'v') - sage: A3 = CoxeterGroup('A3', implementation='coxeter3') + sage: W = CoxeterGroup('A3', implementation='coxeter3') sage: H = IwahoriHeckeAlgebra(A3, v**2); Cp=H.Cp_Coxeter3() - When `y` is itself a generator `s`, the decomposition is trivial :: - sage: w= A3([1]) - sage: Cp._decompose_into_generators(w) - Cp[1] + When `y` is itself a generator `s`, the decomposition is trivial:: - Another example, where `C^{\prime}_y` happens to be a monomial :: + sage: Cp._decompose_into_generators(W([1])) + {(1,): 1} - sage: Cp._decompose_into_generators(A3([2,1])) # C_{21} = C_2C_1 - Cp[2]*Cp[1] + Another example, where Cp_y happens to be a monomial; Cp_{21} = + Cp_2*Cp_1:: - In more general situations the sum is a polynomial :: + sage: Cp._decompose_into_generators(A3([2,1])) + {(2, 1): 1} + + In more general situations the sum is a polynomial; Cp_{121} = + Cp_1*Cp_2*Cp_1 - Cp_1 sage: Cp._decompose_into_generators(A3([1,2,1])) # C_{121} = C_1C_2C_1 - C_1 - -Cp1 + Cp1*Cp2*Cp1 + {(1, 2, 1): 1, (1,): -1} sage: Cp._decompose_into_generators(A3([1,2,3,1,2])) - Cp1 - Cp1*Cp2*Cp1 - Cp1*Cp3*Cp2 + Cp1*Cp2*Cp1*Cp3*Cp2 + {(1, 2, 1, 3, 2): 1, (1, 2, 1): -1, (1,): 1, (1, 3, 2): -1} """ # \ell(y) \leq 1 if len(w) == 0: - return self.generator_algebra(1) + return {(): 1} if len(w) == 1: - return self._generators[w[0]] + return {(w[0],): 1} # \ell(y) > 1, we use the induction on `\ell(y)` and recursively # find the decomposition s = w[0] @@ -2392,14 +2373,16 @@ def _decompose_into_generators(self, w): # Compute mu-coefficient via coxeter3 sum_term += self.base_ring()(x.mu_coefficient(w1)) * self.monomial(x_elt) - # In the expression above, we need to recurse and decompose C_{w1} into generators, - # and then go through the terms of sum_term (lower order terms) and decompose those C_y's into generators - alg_element = self._generators[s] * self._decompose_into_generators(w1) - for (v, coeff) in sum_term: - # We're subtracting 'sum_term' - alg_element -= coeff * self._decompose_into_generators(v) + # Recurse and decompose C_{w1} into generators, then go through the + # lower order terms in sum_term and decompose those into generators. + # Perform (distrubute) Cp_s * Cp_{w1} + result = {(s,) + gens: coeff for (gens, coeff) in self._decompose_into_generators(w1).items()} + for (v, c1) in sum_term: + # Subtract off each term from `sum_term`. + for (gens, c2) in self._decompose_into_generators(v).items(): + result[gens] = result.get(gens, 0) - c1*c2 - return alg_element + return result def product_on_basis(self, w1, w2): r""" @@ -2418,7 +2401,7 @@ def product_on_basis(self, w1, w2): sage: Cp.product_on_basis(A3([1,2,1]), A3([3,1,2])) (v^-1+v)*Cp[1,2,1,3,2] + (v^-1+v)*Cp[1,2,1] """ - # Decompose one of `C_{w_1}` and `C_{w_2}` into a polynomial in the + # Decompose one of Cp_{w1} and Cp_{w2} into a polynomial in the # generators, then multiply the remaining one with the polynomial. if len(w1) <= len(w2): side = 'left' @@ -2429,22 +2412,13 @@ def product_on_basis(self, w1, w2): gen_expression = self._decompose_into_generators(w2) other_element = self.monomial(w1) result = self(0) - # Proceed through the terms, multiplying each term onto other_element - # and adding that summand onto result. - for (p, coeff) in gen_expression: - # is a term, e.g. p = Cp1*Cp2*Cp1 and coeff = 2 + # Proceed through the terms, multiplying the generators in each term + # onto other_element and adding that summand onto result. + for (p, coeff) in gen_expression.items(): summand = coeff * other_element p_list = list(p) if side == 'right' else list(p)[::-1] - # Iterate through the generators in the term, multiplying each generator - # onto other_element and multiplying the result onto summand. - for (gen, exponent) in p_list: - # gen is some formal generator Cp{s} (it is in the - # underlying monoid of self._generator_algebra so coercion - # is required). e.g. gen = Cp1 and exponent = 1. - s = self._index_of_generator[self._generator_algebra(gen)] - for i in range(exponent): - # Perform the product C'_s * summand, exponent-many times. - summand = self._product_with_generator(side, s, summand) + for s in p_list: + summand = self._product_with_generator(side, s, summand) result += summand From 2e8eb1e998099b179d12e51058e2adfd4d6b9fb5 Mon Sep 17 00:00:00 2001 From: Chase Meadors Date: Wed, 28 Jul 2021 18:58:09 -0600 Subject: [PATCH 060/359] Documentation fixes; comment consistency; remove coxeter3 bug workaround --- src/sage/algebras/iwahori_hecke_algebra.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/sage/algebras/iwahori_hecke_algebra.py b/src/sage/algebras/iwahori_hecke_algebra.py index 4737788cc10..d0f137fb678 100644 --- a/src/sage/algebras/iwahori_hecke_algebra.py +++ b/src/sage/algebras/iwahori_hecke_algebra.py @@ -2273,7 +2273,7 @@ def _product_with_generator_on_basis(self, side, s, w): # TODO: consistency in our docstring: ticks or not + other things. - # If `s` is a descent of `w` on the `side`, the product is (v + v^-1) C'_w: + # If `s` is a descent of `w` on the `side`, the product is (v + v^-1) Cp_w: if w.has_descent(s, side=side): return self.delta * self.monomial(w) # Otherwise the product is \sum_{v \leq w; sv < v} mu(v, w) C'_v @@ -2288,11 +2288,7 @@ def _product_with_generator_on_basis(self, side, s, w): if x_elt.has_descent(s, side=side): # Compute mu-coefficient via coxeter3 element += x.mu_coefficient(w) * self.monomial(x_elt) - # TODO: do something about the following; there's the bug fix now - # Doing self._W([s]) * w may not ensure that the word is - # normal form Since W's element constructor does ensure that, - # use the constructor. - longer_word = self._W([s] + list(w) if side == 'left' else list(w) + [s]) + longer_word = self._W([s]) * w if side == 'left' else w * self._W([s]) return self.monomial(longer_word) + element def _product_with_generator(self, side, s, x): @@ -2305,7 +2301,7 @@ def _product_with_generator(self, side, s, x): - ``s`` -- integer in self.index_set() - - ``w`` -- any element of self + - ``x`` -- any element of self EXAMPLES:: From cc41a95921ec1182c23ce1f5b3324727dba17634 Mon Sep 17 00:00:00 2001 From: Chase Meadors Date: Wed, 28 Jul 2021 19:15:20 -0600 Subject: [PATCH 061/359] Fix some doctests for dictionary output; use W for group name consistently --- src/sage/algebras/iwahori_hecke_algebra.py | 59 ++++++++++++---------- 1 file changed, 31 insertions(+), 28 deletions(-) diff --git a/src/sage/algebras/iwahori_hecke_algebra.py b/src/sage/algebras/iwahori_hecke_algebra.py index d0f137fb678..e43dfa3d28e 100644 --- a/src/sage/algebras/iwahori_hecke_algebra.py +++ b/src/sage/algebras/iwahori_hecke_algebra.py @@ -2180,16 +2180,18 @@ def __init__(self, algebra, prefix='Cp'): Initialize the Cp_Coxeter3 Kazdahn-Luzstig basis of the Iwahori-Hecke algebra ``algebra''. - EXAMPLES:: + EXAMPLES: + + Valid construction:: - TODO: Do we still need all these here? Space after (to - separate good and bad) sage: R. = LaurentPolynomialRing(ZZ, 'v') - sage: A3 = CoxeterGroup('A3', implementation='coxeter3') - sage: H = IwahoriHeckeAlgebra(A3, v**2) + sage: W = CoxeterGroup('A3', implementation='coxeter3') + sage: H = IwahoriHeckeAlgebra(W, v**2) sage: Cp = H.Cp_Coxeter3() + Invalid construction:: + sage: H = IwahoriHeckeAlgebra('A3', v**2) sage: Cp = H.Cp_Coxeter3() Traceback (most recent call last): @@ -2231,9 +2233,9 @@ def to_Cp_basis(self, w): EXAMPLES:: sage: R. = LaurentPolynomialRing(ZZ, 'v') - sage: A3 = CoxeterGroup('A3', implementation='coxeter3') - sage: H = IwahoriHeckeAlgebra(A3, v**2); Cp=H.Cp(); CpC=H.Cp_Coxeter3() - sage: s1, s2, s3 = A3.simple_reflections() + sage: W = CoxeterGroup('A3', implementation='coxeter3') + sage: H = IwahoriHeckeAlgebra(W, v**2); Cp=H.Cp(); CpC=H.Cp_Coxeter3() + sage: s1, s2, s3 = W.simple_reflections() sage: CpC.to_Cp_basis(s1*s2) Cp[1,2] sage: CpC.to_Cp_basis(s1*s2*s1) @@ -2261,13 +2263,13 @@ def _product_with_generator_on_basis(self, side, s, w): EXAMPLES:: sage: R. = LaurentPolynomialRing(ZZ, 'v') - sage: A3 = CoxeterGroup('A3', implementation='coxeter3') - sage: H = IwahoriHeckeAlgebra(A3, v**2); Cp=H.Cp_Coxeter3() - sage: Cp._product_with_generator_on_basis('left', 1, A3([2,1])) + sage: W = CoxeterGroup('A3', implementation='coxeter3') + sage: H = IwahoriHeckeAlgebra(W, v**2); Cp=H.Cp_Coxeter3() + sage: Cp._product_with_generator_on_basis('left', 1, W([2,1])) Cp[1,2,1] + Cp[1] - sage: Cp._product_with_generator_on_basis('right', 1, A3([2,1])) - (v+v^-1) * Cp[1] - sage: Cp._product_with_generator_on_basis('right', 2, A3([1,3,2,1,3])) + sage: Cp._product_with_generator_on_basis('right', 1, W([2,1])) + (v^-1+v)*Cp[2,1] + sage: Cp._product_with_generator_on_basis('right', 2, W([1,3,2,1,3])) Cp[1,2,1,3,2,1] + Cp[1,2,3,2] + Cp[1,3,2,1] """ @@ -2306,8 +2308,8 @@ def _product_with_generator(self, side, s, x): EXAMPLES:: sage: R. = LaurentPolynomialRing(ZZ, 'v') - sage: A3 = CoxeterGroup('A3', implementation='coxeter3') - sage: H = IwahoriHeckeAlgebra(A3, v**2); Cp=H.Cp_Coxeter3() + sage: W = CoxeterGroup('A3', implementation='coxeter3') + sage: H = IwahoriHeckeAlgebra(W, v**2); Cp=H.Cp_Coxeter3() sage: Cp._product_with_generator('left', 1, Cp[1]+Cp[2]) Cp[1,2] + (v^-1+v)*Cp[1] sage: Cp._product_with_generator('right', 1, Cp[1]+Cp[2]) @@ -2326,7 +2328,7 @@ def _decompose_into_generators(self, w): sage: R. = LaurentPolynomialRing(ZZ, 'v') sage: W = CoxeterGroup('A3', implementation='coxeter3') - sage: H = IwahoriHeckeAlgebra(A3, v**2); Cp=H.Cp_Coxeter3() + sage: H = IwahoriHeckeAlgebra(W, v**2); Cp=H.Cp_Coxeter3() When `y` is itself a generator `s`, the decomposition is trivial:: @@ -2336,16 +2338,16 @@ def _decompose_into_generators(self, w): Another example, where Cp_y happens to be a monomial; Cp_{21} = Cp_2*Cp_1:: - sage: Cp._decompose_into_generators(A3([2,1])) + sage: Cp._decompose_into_generators(W([2,1])) {(2, 1): 1} - In more general situations the sum is a polynomial; Cp_{121} = + In more general situations the sum is a polynomial; e.g. Cp_{121} = Cp_1*Cp_2*Cp_1 - Cp_1 - sage: Cp._decompose_into_generators(A3([1,2,1])) # C_{121} = C_1C_2C_1 - C_1 - {(1, 2, 1): 1, (1,): -1} - sage: Cp._decompose_into_generators(A3([1,2,3,1,2])) - {(1, 2, 1, 3, 2): 1, (1, 2, 1): -1, (1,): 1, (1, 3, 2): -1} + sage: Cp._decompose_into_generators(W([1,2,1])) + {(1,): -1, (1, 2, 1): 1} + sage: Cp._decompose_into_generators(W([1,2,3,1,2])) + {(1,): 1, (1, 2, 1): -1, (1, 2, 1, 3, 2): 1, (1, 3, 2): -1} """ # \ell(y) \leq 1 if len(w) == 0: @@ -2385,16 +2387,17 @@ def product_on_basis(self, w1, w2): Return the expansion of `C^{\prime}_{w_1} \cdot C^{\prime}_{w_2}` in the `C^{\prime}`-basis. - The product is computed in the two steps as described in "ALGORITHM". + The product is computed in the two steps as described in + "ALGORITHM". TODO: Reference "ALGORITHM" EXAMPLES:: sage: R. = LaurentPolynomialRing(ZZ, 'v') - sage: A3 = CoxeterGroup('A3', implementation='coxeter3') - sage: H = IwahoriHeckeAlgebra(A3, v**2); Cp=H.Cp_Coxeter3() - sage: Cp.product_on_basis(A3([1,2,1]), A3([3,1])) + sage: W = CoxeterGroup('A3', implementation='coxeter3') + sage: H = IwahoriHeckeAlgebra(W, v**2); Cp=H.Cp_Coxeter3() + sage: Cp.product_on_basis(W([1,2,1]), W([3,1])) (v^-1+v)*Cp[1,2,1,3] - sage: Cp.product_on_basis(A3([1,2,1]), A3([3,1,2])) + sage: Cp.product_on_basis(W([1,2,1]), W([3,1,2])) (v^-1+v)*Cp[1,2,1,3,2] + (v^-1+v)*Cp[1,2,1] """ # Decompose one of Cp_{w1} and Cp_{w2} into a polynomial in the From f7138c2768db07b75ed1f961eb650ab66ea44c7c Mon Sep 17 00:00:00 2001 From: Chase Meadors Date: Wed, 28 Jul 2021 19:38:03 -0600 Subject: [PATCH 062/359] More docstring additions and edits; take care of some TODOs --- src/sage/algebras/iwahori_hecke_algebra.py | 89 +++++++++++++--------- 1 file changed, 52 insertions(+), 37 deletions(-) diff --git a/src/sage/algebras/iwahori_hecke_algebra.py b/src/sage/algebras/iwahori_hecke_algebra.py index e43dfa3d28e..89f66212500 100644 --- a/src/sage/algebras/iwahori_hecke_algebra.py +++ b/src/sage/algebras/iwahori_hecke_algebra.py @@ -2052,54 +2052,70 @@ class Cp_Coxeter3(_KLHeckeBasis): EXAMPLES: - Basic usage:: - - # To create the basis, define the Coxeter group with 'coxeter3' and - # the Hecke algebra with the standard or normalized presentation. + To create the basis, define the Coxeter group with 'coxeter3' and the + Hecke algebra with the standard or normalized presentation:: sage: R. = LaurentPolynomialRing(ZZ) - sage: A3 = CoxeterGroup('A3', implementation='coxeter3') - sage: H = IwahoriHeckeAlgebra(A3, v**2) # standard presentation - sage: Cp = H.Cp_Coxeter3() + sage: W = CoxeterGroup('A3', implementation='coxeter3') + sage: H = IwahoriHeckeAlgebra(W, v**2) # standard presentation + sage: CpC = H.Cp_Coxeter3() - # TODO: 1. avoid Cp, maybe CpC or CpC3? 2. show that CpC3 IS Cp (more reason for 1) + Perform computations with the `C^{\prime}` basis elements indexed by W:: - sage: s1, s2, s3 = A3.simple_reflections() - sage: Cp(s1*s2*s1) + sage: s1, s2, s3 = W.simple_reflections() + sage: CpC(s1*s2*s1) Cp[1,2,1] - sage: Cp(s1)**2 + sage: CpC(s1)**2 (v^-1+v)*Cp[1] + sage: CpC(s1)*CpC(s2)*CpC(s1) + Cp[1,2,1] + Cp[1] + + TODO: Change the prefix (so that items print CpC[1,2,1] etc.), or not? + This would make this block in particular clearer, but not much elsewhere. + + This basis is a reimplementation of the ``Cp`` basis. The computations + are identical:: + + sage: Cp = H.Cp() sage: Cp(s1)*Cp(s2)*Cp(s1) Cp[1,2,1] + Cp[1] + sage: CpC(Cp(s1)*Cp(s2)*Cp(s1)) + Cp[1,2,1] + Cp[1] + sage: Cp(CpC(s1)*CpC(s2)*CpC(s1)) + Cp[1,2,1] + Cp[1] - The following computation take a long time in the + TODO: reference + The following computation takes a long time in the _Basis.product_on_basis method as mentioned on Line 1941, but it is - instant in the current method :: + instant in the current method:: sage: Cp[1]*Cp[2]*Cp[3]*Cp[1]*Cp[2] Cp[1,2,1,3,2] + Cp[1,2,1] + Cp[1,3,2] - Below is another example, with the Hecke algebra of type `B9` in the normalized - presentation. The (optional) relabeling command ensures that `m(1,2)=4`, i.e., that - the generators 1, 2 form the strong bond in the Dynkin diagram. :: + Below is another example, with the Hecke algebra of type `B9` in the + normalized presentation. The (optional) relabeling command ensures that + `m(1,2)=4`, i.e., that the generators 1, 2 form the strong bond in the + Dynkin diagram:: - sage: B9 = CoxeterGroup(CoxeterType(['B', 9]).relabel({ i: 9-i+1 for i in range(1, 10) }), implementation='coxeter3') - sage: H = IwahoriHeckeAlgebra(B9, v, -1/v) + sage: B9 = CoxeterType(['B', 9]).relabel({ i: 9-i+1 for i in range(1, 10) }) + sage: W = CoxeterGroup(B9, implementation='coxeter3') + sage: H = IwahoriHeckeAlgebra(W, v, -1/v) sage: Cp = H.Cp_Coxeter3() + sage: s = W.simple_reflections() + sage: Cp(s[1]*s[2]*s[1]*s[2]) + Cp[1,2,1,2] - # TODO: create s1 to s9 - sage: Cp[1,2,1,2] - Cp[1,2,1,2] - + TODO: reference The following computation also takes a long time in _Basis.product_on_basis, but it is instant here :: sage: Cp[3,2,3,4,5] * Cp[2,3] (v^-1+v)*Cp[2,3,2,4,3,5] + (v^-1+v)*Cp[2,3,2,5] - Directly creating a Hecke algebra from its Coxeter type does not work - currently. Instead, a Coxeter group implemented with 'coxeter3' must be - created first :: + Since the underlying Coxeter group must be implemented with + ``coxeter3``, directly creating a Hecke algebra from its Coxeter type + does not work. Instead, a Coxeter group implemented with 'coxeter3' must + be created first:: sage: H = IwahoriHeckeAlgebra('A3', v**2) sage: H.Cp_Coxeter3() @@ -2108,10 +2124,10 @@ class Cp_Coxeter3(_KLHeckeBasis): ValueError: algebra must be initialized with a coxeter3-implemented Coxeter group to use the Cp_Coxeter3 basis With the Coxeter group created first, the Hecke algebra must be defined - with the standard or normalized presentation mentioned before :: + with the standard or normalized presentation mentioned before:: - sage: A3 = CoxeterGroup('A3', implementation='coxeter3') - sage: H = IwahoriHeckeAlgebra(A3, QQ(1)) + sage: W = CoxeterGroup('A3', implementation='coxeter3') + sage: H = IwahoriHeckeAlgebra(W, QQ(1)) sage: H.Cp_Coxeter3() Traceback (most recent call last): ... @@ -2207,14 +2223,15 @@ def __init__(self, algebra, prefix='Cp'): v = algebra.base_ring().gen(0) - # TODO: rewrite this horribly ugly condition: - if v != algebra.base_ring().one() and ((algebra.q1() == v**2 and algebra.q2() == -1) or (algebra.q1() == v and algebra.q2() == -1/v)): - self.delta = v + ~v # TODO: this is why we need the two normalizations + parameters = {algebra.q1(), algebra.q2()} + if v != algebra.base_ring().one() and (parameters == {v**2, -1} or parameters == {v, -1/v}): + # TODO: this is why we need the two normalizations + self.delta = v + ~v else: if not algebra._is_generic: # If this algebra is generic, it's only being used to coerce to the T basis, not perform computations - # TODO: Better error message (TX made some changes) - raise ValueError('the Cp_Coxeter3 basis is only supported in a Hecke algebra with the standard or normalized presentations (i.e., need `\{q_1,q_2\} = \{v^2,1\}` or `\{q_1,q_2\} = \{v,-v^-1\}` as sets)') + raise ValueError('the Cp_Coxeter3 basis is only supported in a Hecke algebra with the standard or normalized \ +presentations (i.e., need `\{q_1,q_2\} = \{v^2,1\}` or `\{q_1,q_2\} = \{v,-v^-1\}` as sets)') # Define conversion to the other Cp basis self.module_morphism(self.to_Cp_basis, codomain=algebra.Cp(), category=self.category() @@ -2273,13 +2290,11 @@ def _product_with_generator_on_basis(self, side, s, w): Cp[1,2,1,3,2,1] + Cp[1,2,3,2] + Cp[1,3,2,1] """ - # TODO: consistency in our docstring: ticks or not + other things. - # If `s` is a descent of `w` on the `side`, the product is (v + v^-1) Cp_w: if w.has_descent(s, side=side): return self.delta * self.monomial(w) - # Otherwise the product is \sum_{v \leq w; sv < v} mu(v, w) C'_v - # if `side` is left and \sum_{v \leq w; vs < v} mu(v, w) C'_s if + # Otherwise the product is \sum_{v \leq w; sv < v} mu(v, w) Cp_v + # if `side` is left and \sum_{v \leq w; vs < v} mu(v, w) Cp_s if # `side` is right, as mentioned before. else: element = self(0) From 033053e9e18a9a5b0e528e033214c727b9b0a651 Mon Sep 17 00:00:00 2001 From: Tianyuan Xu Date: Fri, 30 Jul 2021 12:49:52 -0600 Subject: [PATCH 063/359] minor doc string changes --- src/sage/algebras/iwahori_hecke_algebra.py | 99 ++++++++++------------ 1 file changed, 46 insertions(+), 53 deletions(-) diff --git a/src/sage/algebras/iwahori_hecke_algebra.py b/src/sage/algebras/iwahori_hecke_algebra.py index 89f66212500..0dea5dcbf67 100644 --- a/src/sage/algebras/iwahori_hecke_algebra.py +++ b/src/sage/algebras/iwahori_hecke_algebra.py @@ -2019,7 +2019,7 @@ class Cp_Coxeter3(_KLHeckeBasis): `T`-basis, and converting the results back to the `C^{\prime}`-basis (see Line 1303). The latter approach is used in the _Basis.product_on_basis method on Line 1298. The direct - method significantly speeds up the product computations. + method implemented here significantly speeds up the product computations. The following formulas for products of the forms `C^{\prime}_s \cdot C^{\prime}_w` and `C^{\prime}_w \cdot C^{\prime}_s`, where `s` is a @@ -2140,38 +2140,37 @@ class Cp_Coxeter3(_KLHeckeBasis): Write `b` for `C^{\prime}`. This class computes each product `b_x \cdot b_y` in two steps as follows. - If `\ell(x) \leq \ell(y)`, then we first decompose `b_x` into a + If `\ell(x) \leq \ell(y)`, we first decompose `b_x` into a polynomial in the generators `b_s (s\in S)` and then multiply that polynomial with `b_y`. If `\ell(x) > \ell(y)`, we decompose `b_y` into a polynomial in `b_s (s\in S)` and multiply that polynomial with `b_x`. The second step (multiplication) is done by repeatedly applying the key formulas displayed earlier directly. The first step (decomposition) is done by induction on the Bruhat order as - follows: for every element `u\in W` with length `\ell(u)>1` and - every left descent `s` of `u`, write `u=sw` (so `w=su`) and note - that + follows: for every element `u\in W` with length `\ell(u)>1`, pick a + left descent `s` of `u` and write `u=sw` (so `w=su`), then note that .. MATH:: C^{\prime}_u = C^{\prime}_s * C^{\prime}_{w} - \sum_{v\le u; sv< v} \mu(v,w) C^{\prime}_v - by the key formulas, where the element `w` and all elements `v`'s - on the right side are lower than `u` in the Bruhat order; this - allows us to finish the computation by decomposing the lower order - terms `b_w` and each `b_v`. For example, for `u=121, s=1, w=21` in - type `A3` we have + by the key formulas mentioned earlier, where the element `w` and + all elements `v`'s on the right side are lower than `u` in the + Bruhat order; this allows us to finish the computation by + decomposing the lower order terms `b_w` and each `b_v`. For + example, for `u=121, s=1, w=21` in type `A3` we have .. MATH:: b_{121} = b_1*b_{21} - b_1, where the lower order term `b_{21}` further decomposes into `b_2*b_1`, therefore `b_{121}=b_1*b_2 b_1 -b1`. We note that the - the base cases `\ell(x)=1` or `\ell(x)=0` of the above induction - occur when `x` is itself a Coxeter generator `s` or the group - identity, respectively. The decomposition is trivial in these cases - (we have `C_x=C_s` or `C_x=1`, the unit of the Hecke algebra). - + base cases `\ell(x)=1` or `\ell(x)=0` of the above induction occur + when `x` is itself a Coxeter generator `s` or the group identity, + respectively. The decomposition is trivial in these cases (we have + `C_x=C_s` or `C_x=1`, the unit of the Hecke algebra). + .. SEEALSO:: # TODO: edit the following @@ -2185,15 +2184,15 @@ class Cp_Coxeter3(_KLHeckeBasis): Accommodate generic presentations of the Hecke algebra other than the standard and normalized ones. - Use the analog of the displayed formulas to implement - `C^{\prime}`-products in the multi-parameter Iwahori-Hecke algebra; - see Section 6 of [Lus2013]_. + Use analogs of the key formulas to implement `C^{\prime}`-products + in the multi-parameter Iwahori-Hecke algebra; see Section 6 of + [Lus2013]_. """ _basis_name = 'Cp_Coxeter3' def __init__(self, algebra, prefix='Cp'): r""" - Initialize the Cp_Coxeter3 Kazdahn-Luzstig basis of the + Initialize the Cp_Coxeter3 Kazdahn-Lusztig basis of the Iwahori-Hecke algebra ``algebra''. EXAMPLES: @@ -2332,11 +2331,13 @@ def _product_with_generator(self, side, s, x): """ return self.linear_combination((self._product_with_generator_on_basis(side, s, w), coeff) for (w, coeff) in x) - def _decompose_into_generators(self, w): + def _decompose_into_generators(self, u): r""" - Decompose `C^{\prime}_w` into a polynomial in the KL generators + Decompose `C^{\prime}_u` into a polynomial in the KL generators `C^{\prime}_s`; see "ALGORITHM". TODO: Reference "ALGORITHM" + TODO: 1. describe output; 2. possibly: change w to u? + EXAMPLES: :: @@ -2365,34 +2366,27 @@ def _decompose_into_generators(self, w): {(1,): 1, (1, 2, 1): -1, (1, 2, 1, 3, 2): 1, (1, 3, 2): -1} """ # \ell(y) \leq 1 - if len(w) == 0: + if len(u) == 0: return {(): 1} - if len(w) == 1: - return {(w[0],): 1} - # \ell(y) > 1, we use the induction on `\ell(y)` and recursively - # find the decomposition - s = w[0] - w1 = w[1:] - - # TODO: remove some doc strings below. We've explained the ideas in enough detail. - - # Additively build the sum term (lower order terms) + if len(u) == 1: + return {(u[0],): 1} + # \ell(y) > 1, use the recursive method described in ALGORITHM + s = u[0] + w = u[1:] # so C^{prime}_s * C^{\prime}_{w} = C^\prime{u} + lower order terms + # get the lower order terms ("sum_term") sum_term = self(0) - between = self._W.bruhat_interval([], w1) - for x in between: - # Get (coxeter3-implemented) group element corresponding to x - x_elt = self._W(x) - if x_elt.has_left_descent(s): + between = self._W.bruhat_interval([], w) + for v in between: + # Get (coxeter3-implemented) group element corresponding to v + v_elt = self._W(x) + if v_elt.has_left_descent(s): # Compute mu-coefficient via coxeter3 - sum_term += self.base_ring()(x.mu_coefficient(w1)) * self.monomial(x_elt) - - # Recurse and decompose C_{w1} into generators, then go through the - # lower order terms in sum_term and decompose those into generators. - # Perform (distrubute) Cp_s * Cp_{w1} - result = {(s,) + gens: coeff for (gens, coeff) in self._decompose_into_generators(w1).items()} - for (v, c1) in sum_term: + sum_term += self.base_ring()(v.mu_coefficient(w)) * self.monomial(v_elt) + # Recurse now: decompose C_s * C_{w} and the lower order terms + result = {(s,) + gens: coeff for (gens, coeff) in self._decompose_into_generators(w).items()} + for (z, c1) in sum_term: # Subtract off each term from `sum_term`. - for (gens, c2) in self._decompose_into_generators(v).items(): + for (gens, c2) in self._decompose_into_generators(z).items(): result[gens] = result.get(gens, 0) - c1*c2 return result @@ -2402,8 +2396,9 @@ def product_on_basis(self, w1, w2): Return the expansion of `C^{\prime}_{w_1} \cdot C^{\prime}_{w_2}` in the `C^{\prime}`-basis. - The product is computed in the two steps as described in - "ALGORITHM". TODO: Reference "ALGORITHM" + The product is computed in the two steps (decomposition + + multiplication) as described in "ALGORITHM". TODO: Reference + "ALGORITHM" EXAMPLES:: @@ -2415,8 +2410,8 @@ def product_on_basis(self, w1, w2): sage: Cp.product_on_basis(W([1,2,1]), W([3,1,2])) (v^-1+v)*Cp[1,2,1,3,2] + (v^-1+v)*Cp[1,2,1] """ - # Decompose one of Cp_{w1} and Cp_{w2} into a polynomial in the - # generators, then multiply the remaining one with the polynomial. + # Decomposition: write one of Cp_{w1} and Cp_{w2} as a polynomial in the + # generators if len(w1) <= len(w2): side = 'left' gen_expression = self._decompose_into_generators(w1) @@ -2426,16 +2421,14 @@ def product_on_basis(self, w1, w2): gen_expression = self._decompose_into_generators(w2) other_element = self.monomial(w1) result = self(0) - # Proceed through the terms, multiplying the generators in each term - # onto other_element and adding that summand onto result. + # Multiplication: multiply the generators in each term of the above + # polynomial onto other_element and add that summand onto result. for (p, coeff) in gen_expression.items(): summand = coeff * other_element p_list = list(p) if side == 'right' else list(p)[::-1] for s in p_list: summand = self._product_with_generator(side, s, summand) - result += summand - return result From 067c103876b528e0b0f3685554be59dd80d21d88 Mon Sep 17 00:00:00 2001 From: Tianyuan Xu Date: Fri, 30 Jul 2021 16:05:37 -0600 Subject: [PATCH 064/359] Cp-to-CpC label changes --- src/sage/algebras/iwahori_hecke_algebra.py | 195 +++++++++++---------- 1 file changed, 99 insertions(+), 96 deletions(-) diff --git a/src/sage/algebras/iwahori_hecke_algebra.py b/src/sage/algebras/iwahori_hecke_algebra.py index 0dea5dcbf67..795c9539c94 100644 --- a/src/sage/algebras/iwahori_hecke_algebra.py +++ b/src/sage/algebras/iwahori_hecke_algebra.py @@ -1583,23 +1583,23 @@ def to_Cp_basis(self, w): def to_Cp_Coxeter3_basis(self, w): r""" - Return `T-w` as a linear combination of `C^{\prime}`-basis elements, + Return `T_w` as a linear combination of `C^{\prime}`-basis elements, using the ``Cp_Coxeter3`` basis. EXAMPLES:: sage: R. = LaurentPolynomialRing(ZZ, 'v') sage: A3 = CoxeterGroup('A3', implementation='coxeter3') - sage: H = IwahoriHeckeAlgebra(A3, v**2); T=H.T(); Cp=H.Cp_Coxeter3() + sage: H = IwahoriHeckeAlgebra(A3, v**2); T=H.T(); CpC=H.Cp_Coxeter3() sage: s1,s2,s3 = A3.simple_reflections() sage: T.to_Cp_Coxeter3_basis(s1) - v*Cp[1] - 1 - sage: Cp(T(s1)) - v*Cp[1] - 1 - sage: Cp(T[1] + 1) - v*Cp[1] - sage: Cp(T[1,2] + T[1] + T[2] + 1) - v^2*Cp[1,2] + v*CpC[1] - 1 + sage: CpC(T(s1)) + v*CpC[1] - 1 + sage: CpC(T[1] + 1) + v*CpC[1] + sage: CpC(T[1,2] + T[1] + T[2] + 1) + v^2*CpC[1,2] """ H = self.realization_of() generic_T = H._generic_iwahori_hecke_algebra.T() @@ -1968,13 +1968,13 @@ def to_Cp_Coxeter3_basis(self, w): sage: A3 = CoxeterGroup('A3', implementation='coxeter3') sage: H = IwahoriHeckeAlgebra(A3, v**2); Cp = H.Cp(); CpC=H.Cp_Coxeter3() sage: Cp.to_Cp_Coxeter3_basis(A3([1,2])) - Cp[1,2] + CpC[1,2] sage: CpC(Cp[1,2]) - Cp[1,2] + CpC[1,2] """ A = self.realization_of() - Cp = A.Cp_Coxeter3() - return Cp.monomial(w) + CpC = A.Cp_Coxeter3() + return CpC.monomial(w) def hash_involution_on_basis(self, w): r""" @@ -2017,8 +2017,8 @@ class Cp_Coxeter3(_KLHeckeBasis): directly in the `C^{\prime}`-basis, as opposed to converting the `C^{\prime}`-basis to the `T`-basis, calculating the product in the `T`-basis, and converting the results back to the `C^{\prime}`-basis - (see Line 1303). The latter approach is used in the - _Basis.product_on_basis method on Line 1298. The direct + #TODO:(see Line 1303). The latter approach is used in the + #TODO:_Basis.product_on_basis method on Line 1298. The direct method implemented here significantly speeds up the product computations. The following formulas for products of the forms `C^{\prime}_s \cdot @@ -2060,37 +2060,33 @@ class Cp_Coxeter3(_KLHeckeBasis): sage: H = IwahoriHeckeAlgebra(W, v**2) # standard presentation sage: CpC = H.Cp_Coxeter3() - Perform computations with the `C^{\prime}` basis elements indexed by W:: + The new basis here (CpC) and Cp basis are both implementations of the + the `C^{\prime}` basis. The only difference between the implementations + lies in their different methods for computing products:: sage: s1, s2, s3 = W.simple_reflections() - sage: CpC(s1*s2*s1) + sage: Cp = H.Cp() + sage: a = CpC(s1*s2*s1) + CpC[1,2,1] + sage: b = Cp(s1*s2*s1) Cp[1,2,1] + sage: a == b + True + sage: CpC(s1)**2 + (v^-1+v)*CpC[1] + sage: Cp(s1)**2 (v^-1+v)*Cp[1] - sage: CpC(s1)*CpC(s2)*CpC(s1) - Cp[1,2,1] + Cp[1] - - TODO: Change the prefix (so that items print CpC[1,2,1] etc.), or not? - This would make this block in particular clearer, but not much elsewhere. - This basis is a reimplementation of the ``Cp`` basis. The computations - are identical:: - - sage: Cp = H.Cp() sage: Cp(s1)*Cp(s2)*Cp(s1) Cp[1,2,1] + Cp[1] - sage: CpC(Cp(s1)*Cp(s2)*Cp(s1)) - Cp[1,2,1] + Cp[1] - sage: Cp(CpC(s1)*CpC(s2)*CpC(s1)) - Cp[1,2,1] + Cp[1] - - TODO: reference - The following computation takes a long time in the - _Basis.product_on_basis method as mentioned on Line 1941, but it is - instant in the current method:: + sage: CpC(s1)*CpC(s2)*CpC(s1) + CpC[1,2,1] + CpC[1] sage: Cp[1]*Cp[2]*Cp[3]*Cp[1]*Cp[2] - Cp[1,2,1,3,2] + Cp[1,2,1] + Cp[1,3,2] + Cp[1,2,1,3,2] + Cp[1,2,1] + Cp[1,3,2] # long time in the Cp implementation; TODO: ref Line 1941 + sage: CpC[1]*CpC[2]*CpC[3]*CpC[1]*CpC[2] + CpC[1,2,1,3,2] + CpC[1,2,1] + CpC[1,3,2] # instant in the CpC implementation Below is another example, with the Hecke algebra of type `B9` in the normalized presentation. The (optional) relabeling command ensures that @@ -2100,22 +2096,19 @@ class Cp_Coxeter3(_KLHeckeBasis): sage: B9 = CoxeterType(['B', 9]).relabel({ i: 9-i+1 for i in range(1, 10) }) sage: W = CoxeterGroup(B9, implementation='coxeter3') sage: H = IwahoriHeckeAlgebra(W, v, -1/v) - sage: Cp = H.Cp_Coxeter3() + sage: CpC, Cp = H.Cp_Coxeter3(), H.Cp() sage: s = W.simple_reflections() sage: Cp(s[1]*s[2]*s[1]*s[2]) Cp[1,2,1,2] - TODO: reference - The following computation also takes a long time in - _Basis.product_on_basis, but it is instant here :: - sage: Cp[3,2,3,4,5] * Cp[2,3] - (v^-1+v)*Cp[2,3,2,4,3,5] + (v^-1+v)*Cp[2,3,2,5] + (v^-1+v)*Cp[2,3,2,4,3,5] + (v^-1+v)*Cp[2,3,2,5]# long time in the Cp implementation; + sage: CpC[3,2,3,4,5] * CpC[2,3] + (v^-1+v)*CpC[2,3,2,4,3,5] + (v^-1+v)*CpC[2,3,2,5] # instant in the CpC implementation - Since the underlying Coxeter group must be implemented with - ``coxeter3``, directly creating a Hecke algebra from its Coxeter type - does not work. Instead, a Coxeter group implemented with 'coxeter3' must - be created first:: + Note that to use the CpC basis for a Hecke algebra, a Coxeter group + must be created first with implemntation 'coxeter3'. Directly creating + a Hecke algebra from its Coxeter type does not work:: sage: H = IwahoriHeckeAlgebra('A3', v**2) sage: H.Cp_Coxeter3() @@ -2190,7 +2183,7 @@ class Cp_Coxeter3(_KLHeckeBasis): """ _basis_name = 'Cp_Coxeter3' - def __init__(self, algebra, prefix='Cp'): + def __init__(self, algebra, prefix='CpC'): r""" Initialize the Cp_Coxeter3 Kazdahn-Lusztig basis of the Iwahori-Hecke algebra ``algebra''. @@ -2202,16 +2195,28 @@ def __init__(self, algebra, prefix='Cp'): sage: R. = LaurentPolynomialRing(ZZ, 'v') sage: W = CoxeterGroup('A3', implementation='coxeter3') sage: H = IwahoriHeckeAlgebra(W, v**2) - sage: Cp = H.Cp_Coxeter3() + sage: CpC = H.Cp_Coxeter3() - Invalid construction:: + Invalid construction (not creating a Coxeter group with 'coxeter3'):: sage: H = IwahoriHeckeAlgebra('A3', v**2) - sage: Cp = H.Cp_Coxeter3() + sage: H.Cp_Coxeter3() Traceback (most recent call last): ... ValueError: algebra must be initialized with a coxeter3-implemented Coxeter group to use the Cp_Coxeter3 basis + + + Invalid construction (bad presentation for Hecke algebra):: + + sage: W = CoxeterGroup('A3', implementation='coxeter3') + sage: H = IwahoriHeckeAlgebra(W, QQ(1)) + sage: H.Cp_Coxeter3() + Traceback (most recent call last): + ... + ValueError: the Cp_Coxeter3 basis is only supported in a Hecke + algebra with the standard or normalized presentations (i.e., need + `\{q_1,q_2\} = \{v^2,1\}` or `\{q_1,q_2\} = \{v,-v^-1\}` as sets) """ if not isinstance(algebra._W, Coxeter3Group): raise ValueError('algebra must be initialized with a coxeter3-implemented Coxeter group to use the Cp_Coxeter3 basis') @@ -2224,7 +2229,8 @@ def __init__(self, algebra, prefix='Cp'): parameters = {algebra.q1(), algebra.q2()} if v != algebra.base_ring().one() and (parameters == {v**2, -1} or parameters == {v, -1/v}): - # TODO: this is why we need the two normalizations + # The following quantity delta is used in product computations. + # To use it we need the standard or normalized normalizations. self.delta = v + ~v else: if not algebra._is_generic: @@ -2266,8 +2272,6 @@ def _product_with_generator_on_basis(self, side, s, w): Compute the product of `C^{\prime}_s` and `C^{\prime}_w`, putting `C^{\prime}_s` on the given ``side``. - # TODO: again, 'Cp' might be bad; - INPUT: - ``side`` -- string; 'left' or 'right' @@ -2280,21 +2284,17 @@ def _product_with_generator_on_basis(self, side, s, w): sage: R. = LaurentPolynomialRing(ZZ, 'v') sage: W = CoxeterGroup('A3', implementation='coxeter3') - sage: H = IwahoriHeckeAlgebra(W, v**2); Cp=H.Cp_Coxeter3() - sage: Cp._product_with_generator_on_basis('left', 1, W([2,1])) - Cp[1,2,1] + Cp[1] - sage: Cp._product_with_generator_on_basis('right', 1, W([2,1])) - (v^-1+v)*Cp[2,1] - sage: Cp._product_with_generator_on_basis('right', 2, W([1,3,2,1,3])) - Cp[1,2,1,3,2,1] + Cp[1,2,3,2] + Cp[1,3,2,1] + sage: H = IwahoriHeckeAlgebra(W, v**2); CpC=H.Cp_Coxeter3() + sage: CpC._product_with_generator_on_basis('left', 1, W([2,1])) + CpC[1,2,1] + CpC[1] + sage: CpC._product_with_generator_on_basis('right', 1, W([2,1])) + (v^-1+v)*CpC[2,1] + sage: CpC._product_with_generator_on_basis('right', 2, W([1,3,2,1,3])) + CpC[1,2,1,3,2,1] + CpC[1,2,3,2] + CpC[1,3,2,1] """ - - # If `s` is a descent of `w` on the `side`, the product is (v + v^-1) Cp_w: + # use the product formula from TODO: ref algorithm if w.has_descent(s, side=side): return self.delta * self.monomial(w) - # Otherwise the product is \sum_{v \leq w; sv < v} mu(v, w) Cp_v - # if `side` is left and \sum_{v \leq w; vs < v} mu(v, w) Cp_s if - # `side` is right, as mentioned before. else: element = self(0) between = self._W.bruhat_interval([], w) @@ -2323,11 +2323,11 @@ def _product_with_generator(self, side, s, x): sage: R. = LaurentPolynomialRing(ZZ, 'v') sage: W = CoxeterGroup('A3', implementation='coxeter3') - sage: H = IwahoriHeckeAlgebra(W, v**2); Cp=H.Cp_Coxeter3() - sage: Cp._product_with_generator('left', 1, Cp[1]+Cp[2]) - Cp[1,2] + (v^-1+v)*Cp[1] - sage: Cp._product_with_generator('right', 1, Cp[1]+Cp[2]) - Cp[2,1] + (v^-1+v)*Cp[1] + sage: H = IwahoriHeckeAlgebra(W, v**2); CpC=H.Cp_Coxeter3() + sage: CpC._product_with_generator('left', 1, CpC[1]+CpC[2]) + CpC[1,2] + (v^-1+v)*CpC[1] + sage: CpC._product_with_generator('right', 1, CpC[1]+CpC[2]) + CpC[2,1] + (v^-1+v)*CpC[1] """ return self.linear_combination((self._product_with_generator_on_basis(side, s, w), coeff) for (w, coeff) in x) @@ -2336,7 +2336,7 @@ def _decompose_into_generators(self, u): Decompose `C^{\prime}_u` into a polynomial in the KL generators `C^{\prime}_s`; see "ALGORITHM". TODO: Reference "ALGORITHM" - TODO: 1. describe output; 2. possibly: change w to u? + TODO: explain output format EXAMPLES: @@ -2344,48 +2344,51 @@ def _decompose_into_generators(self, u): sage: R. = LaurentPolynomialRing(ZZ, 'v') sage: W = CoxeterGroup('A3', implementation='coxeter3') - sage: H = IwahoriHeckeAlgebra(W, v**2); Cp=H.Cp_Coxeter3() + sage: H = IwahoriHeckeAlgebra(W, v**2); CpC=H.Cp_Coxeter3() - When `y` is itself a generator `s`, the decomposition is trivial:: + When `u` is itself a generator `s`, the decomposition is trivial:: - sage: Cp._decompose_into_generators(W([1])) + sage: CpC._decompose_into_generators(W([1])) {(1,): 1} - Another example, where Cp_y happens to be a monomial; Cp_{21} = - Cp_2*Cp_1:: + Another example, where `C^{\prime}_u` happens to be a monomial + (e.g., CpC_{21} = CpC_2 * CpC_1):: - sage: Cp._decompose_into_generators(W([2,1])) - {(2, 1): 1} + sage: CpC._decompose_into_generators(W([2,1])) + {(2, 1): 1} - In more general situations the sum is a polynomial; e.g. Cp_{121} = - Cp_1*Cp_2*Cp_1 - Cp_1 + In more general situations the sum is a polynomial (e.g., + CpC_{121}=CpC_1*CpC_2*CpC_1-CpC_1):: - sage: Cp._decompose_into_generators(W([1,2,1])) - {(1,): -1, (1, 2, 1): 1} - sage: Cp._decompose_into_generators(W([1,2,3,1,2])) + sage: CpC._decompose_into_generators(W([1,2,1])) + {(1,): -1, (1, 2, 1): 1} + sage: CpC._decompose_into_generators(W([1,2,3,1,2])) {(1,): 1, (1, 2, 1): -1, (1, 2, 1, 3, 2): 1, (1, 3, 2): -1} """ - # \ell(y) \leq 1 + # l(y) = 0 or 1 if len(u) == 0: return {(): 1} if len(u) == 1: return {(u[0],): 1} - # \ell(y) > 1, use the recursive method described in ALGORITHM + + # l(y) > 1, use the recursive method described in TODO:ref ALGORITHM s = u[0] - w = u[1:] # so C^{prime}_s * C^{\prime}_{w} = C^\prime{u} + lower order terms + w = u[1:] # so CpC_s * CpC_w = CpC_u + lower order terms + # get the lower order terms ("sum_term") sum_term = self(0) between = self._W.bruhat_interval([], w) for v in between: # Get (coxeter3-implemented) group element corresponding to v - v_elt = self._W(x) + v_elt = self._W(v) if v_elt.has_left_descent(s): # Compute mu-coefficient via coxeter3 sum_term += self.base_ring()(v.mu_coefficient(w)) * self.monomial(v_elt) - # Recurse now: decompose C_s * C_{w} and the lower order terms + + # recursion: decompose C'_s * C'_w and the lower order terms result = {(s,) + gens: coeff for (gens, coeff) in self._decompose_into_generators(w).items()} for (z, c1) in sum_term: - # Subtract off each term from `sum_term`. + # Subtract off each term from sum_term. for (gens, c2) in self._decompose_into_generators(z).items(): result[gens] = result.get(gens, 0) - c1*c2 @@ -2404,14 +2407,14 @@ def product_on_basis(self, w1, w2): sage: R. = LaurentPolynomialRing(ZZ, 'v') sage: W = CoxeterGroup('A3', implementation='coxeter3') - sage: H = IwahoriHeckeAlgebra(W, v**2); Cp=H.Cp_Coxeter3() - sage: Cp.product_on_basis(W([1,2,1]), W([3,1])) - (v^-1+v)*Cp[1,2,1,3] - sage: Cp.product_on_basis(W([1,2,1]), W([3,1,2])) - (v^-1+v)*Cp[1,2,1,3,2] + (v^-1+v)*Cp[1,2,1] + sage: H = IwahoriHeckeAlgebra(W, v**2); CpC=H.Cp_Coxeter3() + sage: CpC.product_on_basis(W([1,2,1]), W([3,1])) + (v^-1+v)*CpC[1,2,1,3] + sage: CpC.product_on_basis(W([1,2,1]), W([3,1,2])) + (v^-1+v)*CpC[1,2,1,3,2] + (v^-1+v)*CpC[1,2,1] """ - # Decomposition: write one of Cp_{w1} and Cp_{w2} as a polynomial in the - # generators + # Decomposition: write one of C'_{w1} and C'_{w2} as a polynomial in the + # generators C'_{s}. if len(w1) <= len(w2): side = 'left' gen_expression = self._decompose_into_generators(w1) From 32a240ef91023a35cb6e096ddc5d0a60e2c77985 Mon Sep 17 00:00:00 2001 From: Chase Meadors Date: Sat, 31 Jul 2021 02:23:54 -0600 Subject: [PATCH 065/359] Format and fix docstrings; get tests passing --- src/sage/algebras/iwahori_hecke_algebra.py | 101 +++++++++++---------- 1 file changed, 51 insertions(+), 50 deletions(-) diff --git a/src/sage/algebras/iwahori_hecke_algebra.py b/src/sage/algebras/iwahori_hecke_algebra.py index 795c9539c94..4cc5594db70 100644 --- a/src/sage/algebras/iwahori_hecke_algebra.py +++ b/src/sage/algebras/iwahori_hecke_algebra.py @@ -2018,8 +2018,8 @@ class Cp_Coxeter3(_KLHeckeBasis): `C^{\prime}`-basis to the `T`-basis, calculating the product in the `T`-basis, and converting the results back to the `C^{\prime}`-basis #TODO:(see Line 1303). The latter approach is used in the - #TODO:_Basis.product_on_basis method on Line 1298. The direct - method implemented here significantly speeds up the product computations. + #TODO:_Basis.product_on_basis method on Line 1298. The direct method + implemented here significantly speeds up the product computations. The following formulas for products of the forms `C^{\prime}_s \cdot C^{\prime}_w` and `C^{\prime}_w \cdot C^{\prime}_s`, where `s` is a @@ -2028,13 +2028,11 @@ class Cp_Coxeter3(_KLHeckeBasis): presentation of the Hecke algebra, and they control the products of the `C^{\prime}_x \cdot C^{\prime}_y` for arbitrary `x,y`. - .. MATH:: - C^{\prime}_s \cdot C^{\prime}_w = - \begin{cases} - (q+q^-1)C^{\prime}_{w}, & \text{if } \ell(sw) = \ell(w)-1,\\ - C^{\prime}_{sw}+\sum_{v\leq w, sv \leq v} \mu(v,w)C^{\prime}_v, - & \text{if } \ell(sw) = \ell(w)+1. - \end{cases} + .. MATH:: C^{\prime}_s \cdot C^{\prime}_w = \begin{cases} + (q+q^-1)C^{\prime}_{w}, & \text{if } \ell(sw) = \ell(w)-1,\\ + C^{\prime}_{sw}+\sum_{v\leq w, sv \leq v} \mu(v,w)C^{\prime}_v, + & \text{if } \ell(sw) = + \ell(w)+1. \end{cases} C^{\prime}_w \cdot C^{\prime}_s = \begin{cases} @@ -2045,11 +2043,11 @@ class Cp_Coxeter3(_KLHeckeBasis): In the above, `\leq` is the Bruhat order on the Coxeter group and `\mu(v,w)` is the "leading coefficient of Kazhdan-Lusztig polynomials"; - see [KL1979]_ and [Lus2014]_ for more details. The method designates - the computation of the `\mu`-coefficients to Fokko du Cloux's - 'coxeter3' package (wrapped in Sage), which is why the method requires - the creation of the Coxeter group in the 'coxeter3' implementation. - + see [KL1979]_ and [Lus2014]_ for more details. The method designates the + computation of the `\mu`-coefficients to Fokko du Cloux's 'coxeter3' + package (wrapped in Sage), which is why the method requires the creation + of the Coxeter group in the 'coxeter3' implementation. + EXAMPLES: To create the basis, define the Coxeter group with 'coxeter3' and the @@ -2060,33 +2058,38 @@ class Cp_Coxeter3(_KLHeckeBasis): sage: H = IwahoriHeckeAlgebra(W, v**2) # standard presentation sage: CpC = H.Cp_Coxeter3() - The new basis here (CpC) and Cp basis are both implementations of the - the `C^{\prime}` basis. The only difference between the implementations - lies in their different methods for computing products:: + The new basis here (``CpC``) and ``Cp`` basis are both implementations + of the the `C^{\prime}` basis. The only difference between the + implementations lies in their different methods for computing products, + elements can be converted between the two trivially TODO: I'm not sure + this example block is as useful or clear as it could be:: sage: s1, s2, s3 = W.simple_reflections() sage: Cp = H.Cp() - sage: a = CpC(s1*s2*s1) + sage: a = CpC(s1*s2*s1); a CpC[1,2,1] - sage: b = Cp(s1*s2*s1) + sage: b = Cp(s1*s2*s1); b Cp[1,2,1] - sage: a == b + sage: Cp(a) == b True + sage: a == CpC(b) + True + + This example demonstrates an example that takes a long time in the + existing ``Cp`` basis, but is fast using this implementation:: sage: CpC(s1)**2 (v^-1+v)*CpC[1] sage: Cp(s1)**2 (v^-1+v)*Cp[1] - sage: Cp(s1)*Cp(s2)*Cp(s1) Cp[1,2,1] + Cp[1] sage: CpC(s1)*CpC(s2)*CpC(s1) CpC[1,2,1] + CpC[1] - - sage: Cp[1]*Cp[2]*Cp[3]*Cp[1]*Cp[2] - Cp[1,2,1,3,2] + Cp[1,2,1] + Cp[1,3,2] # long time in the Cp implementation; TODO: ref Line 1941 + sage: Cp[1]*Cp[2]*Cp[3]*Cp[1]*Cp[2] # long time + Cp[1,2,1,3,2] + Cp[1,2,1] + Cp[1,3,2] sage: CpC[1]*CpC[2]*CpC[3]*CpC[1]*CpC[2] - CpC[1,2,1,3,2] + CpC[1,2,1] + CpC[1,3,2] # instant in the CpC implementation + CpC[1,2,1,3,2] + CpC[1,2,1] + CpC[1,3,2] Below is another example, with the Hecke algebra of type `B9` in the normalized presentation. The (optional) relabeling command ensures that @@ -2100,15 +2103,14 @@ class Cp_Coxeter3(_KLHeckeBasis): sage: s = W.simple_reflections() sage: Cp(s[1]*s[2]*s[1]*s[2]) Cp[1,2,1,2] - - sage: Cp[3,2,3,4,5] * Cp[2,3] - (v^-1+v)*Cp[2,3,2,4,3,5] + (v^-1+v)*Cp[2,3,2,5]# long time in the Cp implementation; + sage: Cp[3,2,3,4,5] * Cp[2,3] # long time + (v^-1+v)*Cp[2,3,2,4,3,5] + (v^-1+v)*Cp[2,3,2,5] sage: CpC[3,2,3,4,5] * CpC[2,3] - (v^-1+v)*CpC[2,3,2,4,3,5] + (v^-1+v)*CpC[2,3,2,5] # instant in the CpC implementation + (v^-1+v)*CpC[2,3,2,4,3,5] + (v^-1+v)*CpC[2,3,2,5] - Note that to use the CpC basis for a Hecke algebra, a Coxeter group - must be created first with implemntation 'coxeter3'. Directly creating - a Hecke algebra from its Coxeter type does not work:: + Note that to use the CpC basis for a Hecke algebra, a Coxeter group must + be created first with implemntation 'coxeter3'. Directly creating a + Hecke algebra from its Coxeter type does not work:: sage: H = IwahoriHeckeAlgebra('A3', v**2) sage: H.Cp_Coxeter3() @@ -2129,9 +2131,8 @@ class Cp_Coxeter3(_KLHeckeBasis): `\{q_1,q_2\} = \{v^2,1\}` or `\{q_1,q_2\} = \{v,-v^-1\}` as sets) - ALGORITHM : - Write `b` for `C^{\prime}`. This class computes each product `b_x - \cdot b_y` in two steps as follows. + ALGORITHM : Write `b` for `C^{\prime}`. This class computes each product + `b_x \cdot b_y` in two steps as follows. If `\ell(x) \leq \ell(y)`, we first decompose `b_x` into a polynomial in the generators `b_s (s\in S)` and then multiply that @@ -2162,7 +2163,7 @@ class Cp_Coxeter3(_KLHeckeBasis): when `x` is itself a Coxeter generator `s` or the group identity, respectively. The decomposition is trivial in these cases (we have `C_x=C_s` or `C_x=1`, the unit of the Hecke algebra). - + .. SEEALSO:: @@ -2173,7 +2174,7 @@ class Cp_Coxeter3(_KLHeckeBasis): :package?[coxeter3?] .. TODO:: - + Accommodate generic presentations of the Hecke algebra other than the standard and normalized ones. @@ -3027,9 +3028,9 @@ def _to_Cp_basis(self, w, Cp): sage: Cp(T(s1)) v*Cp[1] + (-u^-1*v^2) sage: T._to_Cp_basis(s1, CpC) - v*Cp[1] + (-u^-1*v^2) + v*CpC[1] + (-u^-1*v^2) sage: CpC(T(s1)) - v*Cp[1] + (-u^-1*v^2) + v*CpC[1] + (-u^-1*v^2) """ A = self.realization_of() # Cp = A.Cp() if not use_Cp_Coxeter3 else A.Cp_Coxeter3() @@ -3086,19 +3087,19 @@ def to_Cp_Coxeter3_basis(self, w): sage: H = sage.algebras.iwahori_hecke_algebra.IwahoriHeckeAlgebra_nonstandard(A2) sage: s1,s2 = H.coxeter_group().simple_reflections() sage: T = H.T() - sage: Cp = H.Cp_Coxeter3() + sage: CpC = H.Cp_Coxeter3() sage: T.to_Cp_Coxeter3_basis(s1) - v*Cp[1] + (-u^-1*v^2) - sage: Cp(T(s1)) - v*Cp[1] + (-u^-1*v^2) - sage: Cp(T(s1)+1) - v*Cp[1] + (-u^-1*v^2+1) - sage: Cp(T(s1*s2)+T(s1)+T(s2)+1) - v^2*Cp[1,2] + (-u^-1*v^3+v)*Cp[1] + (-u^-1*v^3+v)*Cp[2] + v*CpC[1] + (-u^-1*v^2) + sage: CpC(T(s1)) + v*CpC[1] + (-u^-1*v^2) + sage: CpC(T(s1)+1) + v*CpC[1] + (-u^-1*v^2+1) + sage: CpC(T(s1*s2)+T(s1)+T(s2)+1) + v^2*CpC[1,2] + (-u^-1*v^3+v)*CpC[1] + (-u^-1*v^3+v)*CpC[2] + (u^-2*v^4-2*u^-1*v^2+1) - sage: Cp(T(s1*s2*s1)) - v^3*Cp[1,2,1] + (-u^-1*v^4)*Cp[1,2] + (-u^-1*v^4)*Cp[2,1] - + (u^-2*v^5)*Cp[1] + (u^-2*v^5)*Cp[2] + (-u^-3*v^6) + sage: CpC(T(s1*s2*s1)) + v^3*CpC[1,2,1] + (-u^-1*v^4)*CpC[1,2] + (-u^-1*v^4)*CpC[2,1] + + (u^-2*v^5)*CpC[1] + (u^-2*v^5)*CpC[2] + (-u^-3*v^6) """ A = self.realization_of() return self._to_Cp_basis(w, A.Cp_Coxeter3()) From 32d0a2aa2af1afb47c783b1b471c6e84c4064dcb Mon Sep 17 00:00:00 2001 From: Chase Meadors Date: Sat, 31 Jul 2021 02:27:16 -0600 Subject: [PATCH 066/359] Change side to be last argument in all methods that take it; default 'left' --- src/sage/algebras/iwahori_hecke_algebra.py | 26 +++++++++++----------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/sage/algebras/iwahori_hecke_algebra.py b/src/sage/algebras/iwahori_hecke_algebra.py index 4cc5594db70..e1791ba229d 100644 --- a/src/sage/algebras/iwahori_hecke_algebra.py +++ b/src/sage/algebras/iwahori_hecke_algebra.py @@ -2268,29 +2268,29 @@ def to_Cp_basis(self, w): Cp = A.Cp() return Cp.monomial(w) - def _product_with_generator_on_basis(self, side, s, w): + def _product_with_generator_on_basis(self, s, w, side='left'): r""" Compute the product of `C^{\prime}_s` and `C^{\prime}_w`, putting `C^{\prime}_s` on the given ``side``. INPUT: - - ``side`` -- string; 'left' or 'right' - - ``s`` -- integer in self.index_set() - ``w`` -- a word in self.coxeter_group() + - ``side`` -- string; 'left' or 'right' + EXAMPLES:: sage: R. = LaurentPolynomialRing(ZZ, 'v') sage: W = CoxeterGroup('A3', implementation='coxeter3') sage: H = IwahoriHeckeAlgebra(W, v**2); CpC=H.Cp_Coxeter3() - sage: CpC._product_with_generator_on_basis('left', 1, W([2,1])) + sage: CpC._product_with_generator_on_basis(1, W([2,1]), 'left') CpC[1,2,1] + CpC[1] - sage: CpC._product_with_generator_on_basis('right', 1, W([2,1])) + sage: CpC._product_with_generator_on_basis(1, W([2,1]), 'right') (v^-1+v)*CpC[2,1] - sage: CpC._product_with_generator_on_basis('right', 2, W([1,3,2,1,3])) + sage: CpC._product_with_generator_on_basis(2, W([1,3,2,1,3]), 'right') CpC[1,2,1,3,2,1] + CpC[1,2,3,2] + CpC[1,3,2,1] """ # use the product formula from TODO: ref algorithm @@ -2308,29 +2308,29 @@ def _product_with_generator_on_basis(self, side, s, w): longer_word = self._W([s]) * w if side == 'left' else w * self._W([s]) return self.monomial(longer_word) + element - def _product_with_generator(self, side, s, x): + def _product_with_generator(self, s, x, side='left'): r""" Compute the product of `C^{\prime}_s` with any linear combination of `C^{\prime}`-basis elements. INPUT: - - ``side`` -- string; 'left' or 'right' - - ``s`` -- integer in self.index_set() - ``x`` -- any element of self + - ``side`` -- string; 'left' or 'right' + EXAMPLES:: sage: R. = LaurentPolynomialRing(ZZ, 'v') sage: W = CoxeterGroup('A3', implementation='coxeter3') sage: H = IwahoriHeckeAlgebra(W, v**2); CpC=H.Cp_Coxeter3() - sage: CpC._product_with_generator('left', 1, CpC[1]+CpC[2]) + sage: CpC._product_with_generator(1, CpC[1]+CpC[2], 'left') CpC[1,2] + (v^-1+v)*CpC[1] - sage: CpC._product_with_generator('right', 1, CpC[1]+CpC[2]) + sage: CpC._product_with_generator(1, CpC[1]+CpC[2], 'right') CpC[2,1] + (v^-1+v)*CpC[1] """ - return self.linear_combination((self._product_with_generator_on_basis(side, s, w), coeff) for (w, coeff) in x) + return self.linear_combination((self._product_with_generator_on_basis(s, w, side), coeff) for (w, coeff) in x) def _decompose_into_generators(self, u): r""" @@ -2431,7 +2431,7 @@ def product_on_basis(self, w1, w2): summand = coeff * other_element p_list = list(p) if side == 'right' else list(p)[::-1] for s in p_list: - summand = self._product_with_generator(side, s, summand) + summand = self._product_with_generator(s, summand, side) result += summand return result From efc5b0e698649f8a11b3b139485bb71509911dfa Mon Sep 17 00:00:00 2001 From: Chase Meadors Date: Sat, 31 Jul 2021 14:08:24 -0600 Subject: [PATCH 067/359] Fix typos; handle some TODOs --- src/sage/algebras/iwahori_hecke_algebra.py | 119 +++++++++++---------- 1 file changed, 64 insertions(+), 55 deletions(-) diff --git a/src/sage/algebras/iwahori_hecke_algebra.py b/src/sage/algebras/iwahori_hecke_algebra.py index e1791ba229d..969ad0c3e20 100644 --- a/src/sage/algebras/iwahori_hecke_algebra.py +++ b/src/sage/algebras/iwahori_hecke_algebra.py @@ -2006,7 +2006,7 @@ class Cp_Coxeter3(_KLHeckeBasis): To use this class, the Hecke algebra needs to be created in the "standard" presentation where `\{q_1,q_2\} = \{v^2,1\}` as sets or the - "normalized" presentations where `\{q_1,q_2\} = \{v,-v^-1\}` as sets. + "normalized" presentations where `\{q_1,q_2\} = \{v,-v^{-1}\}` as sets. The Hecke algebra also needs to be created from a Coxeter group defined using the 'coxeter3' implementation; see the examples to follow. @@ -2016,10 +2016,10 @@ class Cp_Coxeter3(_KLHeckeBasis): algebras. The emphasis of this class is to compute such products more directly in the `C^{\prime}`-basis, as opposed to converting the `C^{\prime}`-basis to the `T`-basis, calculating the product in the - `T`-basis, and converting the results back to the `C^{\prime}`-basis - #TODO:(see Line 1303). The latter approach is used in the - #TODO:_Basis.product_on_basis method on Line 1298. The direct method - implemented here significantly speeds up the product computations. + `T`-basis, and converting the results back to the `C^{\prime}`-basis, as + is the default technique in ``_Basis.product_on_basis``, used by the + :class:`IwahoriHeckeAlgebra.Cp` basis. The direct method implemented + here significantly speeds up the product computations. The following formulas for products of the forms `C^{\prime}_s \cdot C^{\prime}_w` and `C^{\prime}_w \cdot C^{\prime}_s`, where `s` is a @@ -2043,19 +2043,20 @@ class Cp_Coxeter3(_KLHeckeBasis): In the above, `\leq` is the Bruhat order on the Coxeter group and `\mu(v,w)` is the "leading coefficient of Kazhdan-Lusztig polynomials"; - see [KL1979]_ and [Lus2014]_ for more details. The method designates the - computation of the `\mu`-coefficients to Fokko du Cloux's 'coxeter3' - package (wrapped in Sage), which is why the method requires the creation - of the Coxeter group in the 'coxeter3' implementation. + see [KL1979]_ and [Lus2013]_ for more details. The method designates the + computation of the `\mu`-coefficients to Sage's interface to Fokko du + Cloux's ``coxeter3`` package, which is why the method requires the + creation of the Coxeter group using the 'coxeter3' implementation. EXAMPLES: - To create the basis, define the Coxeter group with 'coxeter3' and the - Hecke algebra with the standard or normalized presentation:: + To create the basis, define the Coxeter group with + ``implementation='coxeter3'`` and the Hecke algebra with the standard or + normalized presentation:: sage: R. = LaurentPolynomialRing(ZZ) sage: W = CoxeterGroup('A3', implementation='coxeter3') - sage: H = IwahoriHeckeAlgebra(W, v**2) # standard presentation + sage: H = IwahoriHeckeAlgebra(W, v**2) sage: CpC = H.Cp_Coxeter3() The new basis here (``CpC``) and ``Cp`` basis are both implementations @@ -2091,7 +2092,7 @@ class Cp_Coxeter3(_KLHeckeBasis): sage: CpC[1]*CpC[2]*CpC[3]*CpC[1]*CpC[2] CpC[1,2,1,3,2] + CpC[1,2,1] + CpC[1,3,2] - Below is another example, with the Hecke algebra of type `B9` in the + Below is another example, with the Hecke algebra of type `B_9` in the normalized presentation. The (optional) relabeling command ensures that `m(1,2)=4`, i.e., that the generators 1, 2 form the strong bond in the Dynkin diagram:: @@ -2109,7 +2110,7 @@ class Cp_Coxeter3(_KLHeckeBasis): (v^-1+v)*CpC[2,3,2,4,3,5] + (v^-1+v)*CpC[2,3,2,5] Note that to use the CpC basis for a Hecke algebra, a Coxeter group must - be created first with implemntation 'coxeter3'. Directly creating a + be created first with ``implementation='coxeter3'``. Directly creating a Hecke algebra from its Coxeter type does not work:: sage: H = IwahoriHeckeAlgebra('A3', v**2) @@ -2128,48 +2129,49 @@ class Cp_Coxeter3(_KLHeckeBasis): ... ValueError: the Cp_Coxeter3 basis is only supported in a Hecke algebra with the standard or normalized presentations (i.e., need - `\{q_1,q_2\} = \{v^2,1\}` or `\{q_1,q_2\} = \{v,-v^-1\}` as sets) + {q_1,q_2} = {v^2,1} or {q_1,q_2} = {v,-v^-1} as sets) - ALGORITHM : Write `b` for `C^{\prime}`. This class computes each product - `b_x \cdot b_y` in two steps as follows. + ALGORITHM: - If `\ell(x) \leq \ell(y)`, we first decompose `b_x` into a - polynomial in the generators `b_s (s\in S)` and then multiply that - polynomial with `b_y`. If `\ell(x) > \ell(y)`, we decompose `b_y` - into a polynomial in `b_s (s\in S)` and multiply that polynomial - with `b_x`. The second step (multiplication) is done by repeatedly - applying the key formulas displayed earlier directly. The first - step (decomposition) is done by induction on the Bruhat order as - follows: for every element `u\in W` with length `\ell(u)>1`, pick a - left descent `s` of `u` and write `u=sw` (so `w=su`), then note that + Write `b` for `C^{\prime}`. This class computes each product `b_x \cdot + b_y` in two steps as follows. - .. MATH:: - C^{\prime}_u = C^{\prime}_s * C^{\prime}_{w} - \sum_{v\le u; sv< - v} \mu(v,w) C^{\prime}_v + If `\ell(x) \leq \ell(y)`, we first decompose `b_x` into a polynomial in + the generators `b_s (s\in S)` and then multiply that polynomial with + `b_y`. If `\ell(x) > \ell(y)`, we decompose `b_y` into a polynomial in + `b_s (s\in S)` and multiply that polynomial with `b_x`. The second step + (multiplication) is done by repeatedly applying the key formulas + displayed earlier directly. The first step (decomposition) is done by + induction on the Bruhat order as follows: for every element `u\in W` + with length `\ell(u)>1`, pick a left descent `s` of `u` and write `u=sw` + (so `w=su`), then note that - by the key formulas mentioned earlier, where the element `w` and - all elements `v`'s on the right side are lower than `u` in the - Bruhat order; this allows us to finish the computation by - decomposing the lower order terms `b_w` and each `b_v`. For - example, for `u=121, s=1, w=21` in type `A3` we have + .. MATH:: C^{\prime}_u = C^{\prime}_s \cdot C^{\prime}_{w} - \sum_{v\le + u; sv< v} \mu(v,w) C^{\prime}_v - .. MATH:: - b_{121} = b_1*b_{21} - b_1, + by the key formulas mentioned earlier, where the element `w` and all + elements `v`'s on the right side are lower than `u` in the Bruhat order; + this allows us to finish the computation by decomposing the lower order + terms `b_w` and each `b_v`. For example, for `u=121, s=1, w=21` in type + `A3` we have - where the lower order term `b_{21}` further decomposes into - `b_2*b_1`, therefore `b_{121}=b_1*b_2 b_1 -b1`. We note that the - base cases `\ell(x)=1` or `\ell(x)=0` of the above induction occur - when `x` is itself a Coxeter generator `s` or the group identity, - respectively. The decomposition is trivial in these cases (we have - `C_x=C_s` or `C_x=1`, the unit of the Hecke algebra). + .. MATH:: b_{121} = b_1 b_{21} - b_1, + where the lower order term `b_{21}` further decomposes into `b_2 b_1`, + therefore `b_{121}=b_1 b_2 b_1 - b_1`. We note that the base cases + `\ell(x)=1` or `\ell(x)=0` of the above induction occur when `x` is + itself a Coxeter generator `s` or the group identity, respectively. The + decomposition is trivial in these cases (we have `b_x=C_s` or `b_x=1`, + the unit of the Hecke algebra). + TODO: Edit seealso; We can probably not reference cell stuff given our + decision on that, and we *can't* reference _Basis.product_on_basis. + coxeter3? - .. SEEALSO:: - # TODO: edit the following + .. SEEALSO:: - :ref: [KL1979]_, [Lus2013]_ + [KL1979]_, [Lus2013]_ :meth: _Basis.product_on_basis, cell stuff :package?[coxeter3?] @@ -2180,7 +2182,7 @@ class Cp_Coxeter3(_KLHeckeBasis): Use analogs of the key formulas to implement `C^{\prime}`-products in the multi-parameter Iwahori-Hecke algebra; see Section 6 of - [Lus2013]_. + [Lus2013]_. """ _basis_name = 'Cp_Coxeter3' @@ -2199,7 +2201,8 @@ def __init__(self, algebra, prefix='CpC'): sage: CpC = H.Cp_Coxeter3() - Invalid construction (not creating a Coxeter group with 'coxeter3'):: + Invalid construction (not creating a Coxeter group with + 'coxeter3'):: sage: H = IwahoriHeckeAlgebra('A3', v**2) sage: H.Cp_Coxeter3() @@ -2217,7 +2220,7 @@ def __init__(self, algebra, prefix='CpC'): ... ValueError: the Cp_Coxeter3 basis is only supported in a Hecke algebra with the standard or normalized presentations (i.e., need - `\{q_1,q_2\} = \{v^2,1\}` or `\{q_1,q_2\} = \{v,-v^-1\}` as sets) + {q_1,q_2} = {v^2,1} or {q_1,q_2} = {v,-v^-1} as sets) """ if not isinstance(algebra._W, Coxeter3Group): raise ValueError('algebra must be initialized with a coxeter3-implemented Coxeter group to use the Cp_Coxeter3 basis') @@ -2237,7 +2240,7 @@ def __init__(self, algebra, prefix='CpC'): if not algebra._is_generic: # If this algebra is generic, it's only being used to coerce to the T basis, not perform computations raise ValueError('the Cp_Coxeter3 basis is only supported in a Hecke algebra with the standard or normalized \ -presentations (i.e., need `\{q_1,q_2\} = \{v^2,1\}` or `\{q_1,q_2\} = \{v,-v^-1\}` as sets)') +presentations (i.e., need {q_1,q_2} = {v^2,1} or {q_1,q_2} = {v,-v^-1} as sets)') # Define conversion to the other Cp basis self.module_morphism(self.to_Cp_basis, codomain=algebra.Cp(), category=self.category() @@ -2293,7 +2296,7 @@ def _product_with_generator_on_basis(self, s, w, side='left'): sage: CpC._product_with_generator_on_basis(2, W([1,3,2,1,3]), 'right') CpC[1,2,1,3,2,1] + CpC[1,2,3,2] + CpC[1,3,2,1] """ - # use the product formula from TODO: ref algorithm + # use the product formula described in ALGORITHM if w.has_descent(s, side=side): return self.delta * self.monomial(w) else: @@ -2335,9 +2338,15 @@ def _product_with_generator(self, s, x, side='left'): def _decompose_into_generators(self, u): r""" Decompose `C^{\prime}_u` into a polynomial in the KL generators - `C^{\prime}_s`; see "ALGORITHM". TODO: Reference "ALGORITHM" + `C^{\prime}_s`; see the ALGORITHM section of + :class:`IwahoriHeckeAlgebra.Cp_Coxeter3`. + + OUTPUT: - TODO: explain output format + A dictionary keyed by tuples with integer values. Each entry + represents a term, where the tuple contains the indices of the KL + generators in the term, and its value is the coefficient of that + term. EXAMPLES: @@ -2372,7 +2381,7 @@ def _decompose_into_generators(self, u): if len(u) == 1: return {(u[0],): 1} - # l(y) > 1, use the recursive method described in TODO:ref ALGORITHM + # l(y) > 1, use the recursive method described in ALGORITHM s = u[0] w = u[1:] # so CpC_s * CpC_w = CpC_u + lower order terms @@ -2401,8 +2410,8 @@ def product_on_basis(self, w1, w2): the `C^{\prime}`-basis. The product is computed in the two steps (decomposition + - multiplication) as described in "ALGORITHM". TODO: Reference - "ALGORITHM" + multiplication) as described in the ALGORITHM section of + :class:`IwahoriHeckeAlgebra.Cp_Coxeter3` EXAMPLES:: From e7eecf675e687eb3dded1873e1fa475ce217555d Mon Sep 17 00:00:00 2001 From: Chase Meadors Date: Sat, 31 Jul 2021 15:01:27 -0600 Subject: [PATCH 068/359] Better examples for speed up demonstration --- src/sage/algebras/iwahori_hecke_algebra.py | 50 +++++++++++++++++++--- 1 file changed, 44 insertions(+), 6 deletions(-) diff --git a/src/sage/algebras/iwahori_hecke_algebra.py b/src/sage/algebras/iwahori_hecke_algebra.py index 969ad0c3e20..814425ed3b9 100644 --- a/src/sage/algebras/iwahori_hecke_algebra.py +++ b/src/sage/algebras/iwahori_hecke_algebra.py @@ -2076,8 +2076,9 @@ class Cp_Coxeter3(_KLHeckeBasis): sage: a == CpC(b) True - This example demonstrates an example that takes a long time in the - existing ``Cp`` basis, but is fast using this implementation:: + Some computations that agree with computations in the existing ``Cp`` + basis; the last example is one that significantly faster in this + implementation than in ``Cp``:: sage: CpC(s1)**2 (v^-1+v)*CpC[1] @@ -2087,15 +2088,35 @@ class Cp_Coxeter3(_KLHeckeBasis): Cp[1,2,1] + Cp[1] sage: CpC(s1)*CpC(s2)*CpC(s1) CpC[1,2,1] + CpC[1] - sage: Cp[1]*Cp[2]*Cp[3]*Cp[1]*Cp[2] # long time + sage: Cp[1]*Cp[2]*Cp[3]*Cp[1]*Cp[2] Cp[1,2,1,3,2] + Cp[1,2,1] + Cp[1,3,2] - sage: CpC[1]*CpC[2]*CpC[3]*CpC[1]*CpC[2] + sage: CpC[1]*CpC[2]*CpC[3]*CpC[1]*CpC[2] CpC[1,2,1,3,2] + CpC[1,2,1] + CpC[1,3,2] + A computation in type `H_4` that is significantly faster in this + implementation than in the existing ``Cp`` basis:: + + sage: W = CoxeterGroup('H4', implementation='coxeter3') + sage: H = IwahoriHeckeAlgebra(W, v**2) + sage: Cp = H.Cp(); CpC = H.Cp_Coxeter3() + sage: Cp[3,4,3]*Cp[3,4,3,4]*Cp[1,2,3,4] # long time (5 seconds) + (v^-2+2+v^2)*Cp[4,3,4,3,4,1,2,3,4] + + (v^-2+2+v^2)*Cp[4,3,4,3,4,1,2] + + (v^-1+v)*Cp[3,4,1,2,3,4] + + (v^-3+3*v^-1+3*v+v^3)*Cp[4,3,4,3,4,1] + + (v^-1+v)*Cp[3,4,1,2] + sage: CpC[3,4,3]*CpC[3,4,3,4]*CpC[1,2,3,4] + (v^-2+2+v^2)*CpC[4,3,4,3,4,1,2,3,4] + + (v^-2+2+v^2)*CpC[4,3,4,3,4,1,2] + + (v^-1+v)*CpC[3,4,1,2,3,4] + + (v^-3+3*v^-1+3*v+v^3)*CpC[4,3,4,3,4,1] + + (v^-1+v)*CpC[3,4,1,2] + Below is another example, with the Hecke algebra of type `B_9` in the normalized presentation. The (optional) relabeling command ensures that `m(1,2)=4`, i.e., that the generators 1, 2 form the strong bond in the - Dynkin diagram:: + Dynkin diagram. The final two examples are calculations that are very + quick using this implementation, but infeasible for the ``Cp`` basis:: sage: B9 = CoxeterType(['B', 9]).relabel({ i: 9-i+1 for i in range(1, 10) }) sage: W = CoxeterGroup(B9, implementation='coxeter3') @@ -2104,10 +2125,27 @@ class Cp_Coxeter3(_KLHeckeBasis): sage: s = W.simple_reflections() sage: Cp(s[1]*s[2]*s[1]*s[2]) Cp[1,2,1,2] - sage: Cp[3,2,3,4,5] * Cp[2,3] # long time + sage: Cp[3,2,3,4,5] * Cp[2,3] (v^-1+v)*Cp[2,3,2,4,3,5] + (v^-1+v)*Cp[2,3,2,5] sage: CpC[3,2,3,4,5] * CpC[2,3] (v^-1+v)*CpC[2,3,2,4,3,5] + (v^-1+v)*CpC[2,3,2,5] + sage: CpC[9,5,6,7,8,9,2,3,4,5,6,7,8,9] * CpC[9,8,7,6] + (v^-3+3*v^-1+3*v+v^3)*CpC[2,3,4,5,4,6,5,7,6,8,7,9,8,7,6] + sage: CpC[1,5,4,3,2,1,8,7,6,5,4,3,2,1] * CpC[1,2,3,4] # long time (4 seconds) + (v^-1+v)*CpC[1,5,4,3,2,1,8,7,6,5,4,3,2,1,2,3,4] + + (v^-1+v)*CpC[1,2,1,5,4,3,2,1,2,3,8,7,6,5,4] + + (v^-1+v)*CpC[1,3,2,1,5,4,3,2,1,2,3,4,8,7,6] + + (v^-1+v)*CpC[1,4,3,2,1,5,4,3,2,1,2,3,4,8,7] + + (v^-1+v)*CpC[1,5,4,3,2,1,2,3,8,7,6,5,4,3,2] + + (v^-1+v)*CpC[1,2,5,4,3,2,1,8,7,6,5,4,3] + + (v^-1+v)*CpC[1,2,5,4,3,2,8,7,6,5,4,3,2] + + (v^-1+v)*CpC[1,2,3,2,5,4,3,2,8,7,6] + + (v^-1+v)*CpC[1,2,4,3,2,5,4,3,2,8,7] + + (v^-1+v)*CpC[1,2,5,4,3,2,8,7,6,5,4] + + (v^-1+v)*CpC[1,5,4,3,2,1,8,7,6,5,4] + + (v^-1+v)*CpC[1,5,4,3,8,7,6,5,4,3,2] + + (v^-1+v)*CpC[1,3,5,4,3,2,8,7,6] + + (v^-1+v)*CpC[1,4,3,5,4,3,2,8,7] Note that to use the CpC basis for a Hecke algebra, a Coxeter group must be created first with ``implementation='coxeter3'``. Directly creating a From 4fd9688af683669ff60e2eea4978e897c5da39b8 Mon Sep 17 00:00:00 2001 From: Chase Meadors Date: Sat, 31 Jul 2021 15:02:13 -0600 Subject: [PATCH 069/359] Mark doctests throughout with # optional - coxeter3. Tweak _to_T_basis() tests --- src/sage/algebras/iwahori_hecke_algebra.py | 209 +++++++++++---------- 1 file changed, 110 insertions(+), 99 deletions(-) diff --git a/src/sage/algebras/iwahori_hecke_algebra.py b/src/sage/algebras/iwahori_hecke_algebra.py index 814425ed3b9..d501b571ed0 100644 --- a/src/sage/algebras/iwahori_hecke_algebra.py +++ b/src/sage/algebras/iwahori_hecke_algebra.py @@ -1588,17 +1588,17 @@ def to_Cp_Coxeter3_basis(self, w): EXAMPLES:: - sage: R. = LaurentPolynomialRing(ZZ, 'v') - sage: A3 = CoxeterGroup('A3', implementation='coxeter3') - sage: H = IwahoriHeckeAlgebra(A3, v**2); T=H.T(); CpC=H.Cp_Coxeter3() - sage: s1,s2,s3 = A3.simple_reflections() - sage: T.to_Cp_Coxeter3_basis(s1) + sage: R. = LaurentPolynomialRing(ZZ, 'v') # optional - coxeter3 + sage: A3 = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 + sage: H = IwahoriHeckeAlgebra(A3, v**2); T=H.T(); CpC=H.Cp_Coxeter3() # optional - coxeter3 + sage: s1,s2,s3 = A3.simple_reflections() # optional - coxeter3 + sage: T.to_Cp_Coxeter3_basis(s1) # optional - coxeter3 v*CpC[1] - 1 - sage: CpC(T(s1)) + sage: CpC(T(s1)) # optional - coxeter3 v*CpC[1] - 1 - sage: CpC(T[1] + 1) + sage: CpC(T[1] + 1) # optional - coxeter3 v*CpC[1] - sage: CpC(T[1,2] + T[1] + T[2] + 1) + sage: CpC(T[1,2] + T[1] + T[2] + 1) # optional - coxeter3 v^2*CpC[1,2] """ H = self.realization_of() @@ -2054,10 +2054,10 @@ class Cp_Coxeter3(_KLHeckeBasis): ``implementation='coxeter3'`` and the Hecke algebra with the standard or normalized presentation:: - sage: R. = LaurentPolynomialRing(ZZ) - sage: W = CoxeterGroup('A3', implementation='coxeter3') - sage: H = IwahoriHeckeAlgebra(W, v**2) - sage: CpC = H.Cp_Coxeter3() + sage: R. = LaurentPolynomialRing(ZZ) # optional - coxeter3 + sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 + sage: H = IwahoriHeckeAlgebra(W, v**2) # optional - coxeter3 + sage: CpC = H.Cp_Coxeter3() # optional - coxeter3 The new basis here (``CpC``) and ``Cp`` basis are both implementations of the the `C^{\prime}` basis. The only difference between the @@ -2065,47 +2065,47 @@ class Cp_Coxeter3(_KLHeckeBasis): elements can be converted between the two trivially TODO: I'm not sure this example block is as useful or clear as it could be:: - sage: s1, s2, s3 = W.simple_reflections() - sage: Cp = H.Cp() - sage: a = CpC(s1*s2*s1); a + sage: s1, s2, s3 = W.simple_reflections() # optional - coxeter3 + sage: Cp = H.Cp() # optional - coxeter3 + sage: a = CpC(s1*s2*s1); a # optional - coxeter3 CpC[1,2,1] - sage: b = Cp(s1*s2*s1); b + sage: b = Cp(s1*s2*s1); b # optional - coxeter3 Cp[1,2,1] - sage: Cp(a) == b + sage: Cp(a) == b # optional - coxeter3 True - sage: a == CpC(b) + sage: a == CpC(b) # optional - coxeter3 True Some computations that agree with computations in the existing ``Cp`` basis; the last example is one that significantly faster in this implementation than in ``Cp``:: - sage: CpC(s1)**2 + sage: CpC(s1)**2 # optional - coxeter3 (v^-1+v)*CpC[1] - sage: Cp(s1)**2 + sage: Cp(s1)**2 # optional - coxeter3 (v^-1+v)*Cp[1] - sage: Cp(s1)*Cp(s2)*Cp(s1) + sage: Cp(s1)*Cp(s2)*Cp(s1) # optional - coxeter3 Cp[1,2,1] + Cp[1] - sage: CpC(s1)*CpC(s2)*CpC(s1) + sage: CpC(s1)*CpC(s2)*CpC(s1) # optional - coxeter3 CpC[1,2,1] + CpC[1] - sage: Cp[1]*Cp[2]*Cp[3]*Cp[1]*Cp[2] + sage: Cp[1]*Cp[2]*Cp[3]*Cp[1]*Cp[2] # optional - coxeter3 Cp[1,2,1,3,2] + Cp[1,2,1] + Cp[1,3,2] - sage: CpC[1]*CpC[2]*CpC[3]*CpC[1]*CpC[2] + sage: CpC[1]*CpC[2]*CpC[3]*CpC[1]*CpC[2] # optional - coxeter3 CpC[1,2,1,3,2] + CpC[1,2,1] + CpC[1,3,2] A computation in type `H_4` that is significantly faster in this implementation than in the existing ``Cp`` basis:: - sage: W = CoxeterGroup('H4', implementation='coxeter3') - sage: H = IwahoriHeckeAlgebra(W, v**2) - sage: Cp = H.Cp(); CpC = H.Cp_Coxeter3() - sage: Cp[3,4,3]*Cp[3,4,3,4]*Cp[1,2,3,4] # long time (5 seconds) + sage: W = CoxeterGroup('H4', implementation='coxeter3') # optional - coxeter3 + sage: H = IwahoriHeckeAlgebra(W, v**2) # optional - coxeter3 + sage: Cp = H.Cp(); CpC = H.Cp_Coxeter3() # optional - coxeter3 + sage: Cp[3,4,3]*Cp[3,4,3,4]*Cp[1,2,3,4] # long time (5 seconds) # optional - coxeter3 (v^-2+2+v^2)*Cp[4,3,4,3,4,1,2,3,4] + (v^-2+2+v^2)*Cp[4,3,4,3,4,1,2] + (v^-1+v)*Cp[3,4,1,2,3,4] + (v^-3+3*v^-1+3*v+v^3)*Cp[4,3,4,3,4,1] + (v^-1+v)*Cp[3,4,1,2] - sage: CpC[3,4,3]*CpC[3,4,3,4]*CpC[1,2,3,4] + sage: CpC[3,4,3]*CpC[3,4,3,4]*CpC[1,2,3,4] # optional - coxeter3 (v^-2+2+v^2)*CpC[4,3,4,3,4,1,2,3,4] + (v^-2+2+v^2)*CpC[4,3,4,3,4,1,2] + (v^-1+v)*CpC[3,4,1,2,3,4] @@ -2118,20 +2118,21 @@ class Cp_Coxeter3(_KLHeckeBasis): Dynkin diagram. The final two examples are calculations that are very quick using this implementation, but infeasible for the ``Cp`` basis:: - sage: B9 = CoxeterType(['B', 9]).relabel({ i: 9-i+1 for i in range(1, 10) }) - sage: W = CoxeterGroup(B9, implementation='coxeter3') - sage: H = IwahoriHeckeAlgebra(W, v, -1/v) - sage: CpC, Cp = H.Cp_Coxeter3(), H.Cp() - sage: s = W.simple_reflections() - sage: Cp(s[1]*s[2]*s[1]*s[2]) + sage: B9 = CoxeterType(['B', 9]) + sage: B9 = B9.relabel({ i: 9-i+1 for i in range(1, 10) }) # optional - coxeter3 + sage: W = CoxeterGroup(B9, implementation='coxeter3') # optional - coxeter3 + sage: H = IwahoriHeckeAlgebra(W, v, -1/v) # optional - coxeter3 + sage: CpC, Cp = H.Cp_Coxeter3(), H.Cp() # optional - coxeter3 + sage: s = W.simple_reflections() # optional - coxeter3 + sage: Cp(s[1]*s[2]*s[1]*s[2]) # optional - coxeter3 Cp[1,2,1,2] - sage: Cp[3,2,3,4,5] * Cp[2,3] + sage: Cp[3,2,3,4,5] * Cp[2,3] # optional - coxeter3 (v^-1+v)*Cp[2,3,2,4,3,5] + (v^-1+v)*Cp[2,3,2,5] - sage: CpC[3,2,3,4,5] * CpC[2,3] + sage: CpC[3,2,3,4,5] * CpC[2,3] # optional - coxeter3 (v^-1+v)*CpC[2,3,2,4,3,5] + (v^-1+v)*CpC[2,3,2,5] - sage: CpC[9,5,6,7,8,9,2,3,4,5,6,7,8,9] * CpC[9,8,7,6] + sage: CpC[9,5,6,7,8,9,2,3,4,5,6,7,8,9] * CpC[9,8,7,6] # optional - coxeter3 (v^-3+3*v^-1+3*v+v^3)*CpC[2,3,4,5,4,6,5,7,6,8,7,9,8,7,6] - sage: CpC[1,5,4,3,2,1,8,7,6,5,4,3,2,1] * CpC[1,2,3,4] # long time (4 seconds) + sage: CpC[1,5,4,3,2,1,8,7,6,5,4,3,2,1] * CpC[1,2,3,4] # long time (4 seconds) # optional - coxeter3 (v^-1+v)*CpC[1,5,4,3,2,1,8,7,6,5,4,3,2,1,2,3,4] + (v^-1+v)*CpC[1,2,1,5,4,3,2,1,2,3,8,7,6,5,4] + (v^-1+v)*CpC[1,3,2,1,5,4,3,2,1,2,3,4,8,7,6] @@ -2151,8 +2152,8 @@ class Cp_Coxeter3(_KLHeckeBasis): be created first with ``implementation='coxeter3'``. Directly creating a Hecke algebra from its Coxeter type does not work:: - sage: H = IwahoriHeckeAlgebra('A3', v**2) - sage: H.Cp_Coxeter3() + sage: H = IwahoriHeckeAlgebra('A3', v**2) # optional - coxeter3 + sage: H.Cp_Coxeter3() # optional - coxeter3 Traceback (most recent call last): ... ValueError: algebra must be initialized with a coxeter3-implemented Coxeter group to use the Cp_Coxeter3 basis @@ -2160,9 +2161,9 @@ class Cp_Coxeter3(_KLHeckeBasis): With the Coxeter group created first, the Hecke algebra must be defined with the standard or normalized presentation mentioned before:: - sage: W = CoxeterGroup('A3', implementation='coxeter3') - sage: H = IwahoriHeckeAlgebra(W, QQ(1)) - sage: H.Cp_Coxeter3() + sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 + sage: H = IwahoriHeckeAlgebra(W, QQ(1)) # optional - coxeter3 + sage: H.Cp_Coxeter3() # optional - coxeter3 Traceback (most recent call last): ... ValueError: the Cp_Coxeter3 basis is only supported in a Hecke @@ -2233,17 +2234,17 @@ def __init__(self, algebra, prefix='CpC'): Valid construction:: - sage: R. = LaurentPolynomialRing(ZZ, 'v') - sage: W = CoxeterGroup('A3', implementation='coxeter3') - sage: H = IwahoriHeckeAlgebra(W, v**2) - sage: CpC = H.Cp_Coxeter3() + sage: R. = LaurentPolynomialRing(ZZ, 'v') # optional - coxeter3 + sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 + sage: H = IwahoriHeckeAlgebra(W, v**2) # optional - coxeter3 + sage: CpC = H.Cp_Coxeter3() # optional - coxeter3 Invalid construction (not creating a Coxeter group with 'coxeter3'):: - sage: H = IwahoriHeckeAlgebra('A3', v**2) - sage: H.Cp_Coxeter3() + sage: H = IwahoriHeckeAlgebra('A3', v**2) # optional - coxeter3 + sage: H.Cp_Coxeter3() # optional - coxeter3 Traceback (most recent call last): ... ValueError: algebra must be initialized with a coxeter3-implemented Coxeter group to use the Cp_Coxeter3 basis @@ -2251,9 +2252,9 @@ def __init__(self, algebra, prefix='CpC'): Invalid construction (bad presentation for Hecke algebra):: - sage: W = CoxeterGroup('A3', implementation='coxeter3') - sage: H = IwahoriHeckeAlgebra(W, QQ(1)) - sage: H.Cp_Coxeter3() + sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 + sage: H = IwahoriHeckeAlgebra(W, QQ(1)) # optional - coxeter3 + sage: H.Cp_Coxeter3() # optional - coxeter3 Traceback (most recent call last): ... ValueError: the Cp_Coxeter3 basis is only supported in a Hecke @@ -2296,13 +2297,14 @@ def to_Cp_basis(self, w): EXAMPLES:: - sage: R. = LaurentPolynomialRing(ZZ, 'v') - sage: W = CoxeterGroup('A3', implementation='coxeter3') - sage: H = IwahoriHeckeAlgebra(W, v**2); Cp=H.Cp(); CpC=H.Cp_Coxeter3() - sage: s1, s2, s3 = W.simple_reflections() - sage: CpC.to_Cp_basis(s1*s2) + sage: R. = LaurentPolynomialRing(ZZ, 'v') # optional - coxeter3 + sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 + sage: H = IwahoriHeckeAlgebra(W, v**2) # optional - coxeter3 + sage: Cp=H.Cp(); CpC=H.Cp_Coxeter3() # optional - coxeter3 + sage: s1, s2, s3 = W.simple_reflections() # optional - coxeter3 + sage: CpC.to_Cp_basis(s1*s2) # optional - coxeter3 Cp[1,2] - sage: CpC.to_Cp_basis(s1*s2*s1) + sage: CpC.to_Cp_basis(s1*s2*s1) # optional - coxeter3 Cp[1,2,1] """ A = self.realization_of() @@ -2324,14 +2326,14 @@ def _product_with_generator_on_basis(self, s, w, side='left'): EXAMPLES:: - sage: R. = LaurentPolynomialRing(ZZ, 'v') - sage: W = CoxeterGroup('A3', implementation='coxeter3') - sage: H = IwahoriHeckeAlgebra(W, v**2); CpC=H.Cp_Coxeter3() - sage: CpC._product_with_generator_on_basis(1, W([2,1]), 'left') + sage: R. = LaurentPolynomialRing(ZZ, 'v') # optional - coxeter3 + sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 + sage: H = IwahoriHeckeAlgebra(W, v**2); CpC=H.Cp_Coxeter3() # optional - coxeter3 + sage: CpC._product_with_generator_on_basis(1, W([2,1]), 'left') # optional - coxeter3 CpC[1,2,1] + CpC[1] - sage: CpC._product_with_generator_on_basis(1, W([2,1]), 'right') + sage: CpC._product_with_generator_on_basis(1, W([2,1]), 'right') # optional - coxeter3 (v^-1+v)*CpC[2,1] - sage: CpC._product_with_generator_on_basis(2, W([1,3,2,1,3]), 'right') + sage: CpC._product_with_generator_on_basis(2, W([1,3,2,1,3]), 'right') # optional - coxeter3 CpC[1,2,1,3,2,1] + CpC[1,2,3,2] + CpC[1,3,2,1] """ # use the product formula described in ALGORITHM @@ -2363,12 +2365,12 @@ def _product_with_generator(self, s, x, side='left'): EXAMPLES:: - sage: R. = LaurentPolynomialRing(ZZ, 'v') - sage: W = CoxeterGroup('A3', implementation='coxeter3') - sage: H = IwahoriHeckeAlgebra(W, v**2); CpC=H.Cp_Coxeter3() - sage: CpC._product_with_generator(1, CpC[1]+CpC[2], 'left') + sage: R. = LaurentPolynomialRing(ZZ, 'v') # optional - coxeter3 + sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 + sage: H = IwahoriHeckeAlgebra(W, v**2); CpC=H.Cp_Coxeter3() # optional - coxeter3 + sage: CpC._product_with_generator(1, CpC[1]+CpC[2], 'left') # optional - coxeter3 CpC[1,2] + (v^-1+v)*CpC[1] - sage: CpC._product_with_generator(1, CpC[1]+CpC[2], 'right') + sage: CpC._product_with_generator(1, CpC[1]+CpC[2], 'right') # optional - coxeter3 CpC[2,1] + (v^-1+v)*CpC[1] """ return self.linear_combination((self._product_with_generator_on_basis(s, w, side), coeff) for (w, coeff) in x) @@ -2390,27 +2392,27 @@ def _decompose_into_generators(self, u): :: - sage: R. = LaurentPolynomialRing(ZZ, 'v') - sage: W = CoxeterGroup('A3', implementation='coxeter3') - sage: H = IwahoriHeckeAlgebra(W, v**2); CpC=H.Cp_Coxeter3() + sage: R. = LaurentPolynomialRing(ZZ, 'v') # optional - coxeter3 + sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 + sage: H = IwahoriHeckeAlgebra(W, v**2); CpC=H.Cp_Coxeter3() # optional - coxeter3 When `u` is itself a generator `s`, the decomposition is trivial:: - sage: CpC._decompose_into_generators(W([1])) + sage: CpC._decompose_into_generators(W([1])) # optional - coxeter3 {(1,): 1} Another example, where `C^{\prime}_u` happens to be a monomial (e.g., CpC_{21} = CpC_2 * CpC_1):: - sage: CpC._decompose_into_generators(W([2,1])) + sage: CpC._decompose_into_generators(W([2,1])) # optional - coxeter3 {(2, 1): 1} In more general situations the sum is a polynomial (e.g., CpC_{121}=CpC_1*CpC_2*CpC_1-CpC_1):: - sage: CpC._decompose_into_generators(W([1,2,1])) + sage: CpC._decompose_into_generators(W([1,2,1])) # optional - coxeter3 {(1,): -1, (1, 2, 1): 1} - sage: CpC._decompose_into_generators(W([1,2,3,1,2])) + sage: CpC._decompose_into_generators(W([1,2,3,1,2])) # optional - coxeter3 {(1,): 1, (1, 2, 1): -1, (1, 2, 1, 3, 2): 1, (1, 3, 2): -1} """ # l(y) = 0 or 1 @@ -2453,12 +2455,12 @@ def product_on_basis(self, w1, w2): EXAMPLES:: - sage: R. = LaurentPolynomialRing(ZZ, 'v') - sage: W = CoxeterGroup('A3', implementation='coxeter3') - sage: H = IwahoriHeckeAlgebra(W, v**2); CpC=H.Cp_Coxeter3() - sage: CpC.product_on_basis(W([1,2,1]), W([3,1])) + sage: R. = LaurentPolynomialRing(ZZ, 'v') # optional - coxeter3 + sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 + sage: H = IwahoriHeckeAlgebra(W, v**2); CpC=H.Cp_Coxeter3() # optional - coxeter3 + sage: CpC.product_on_basis(W([1,2,1]), W([3,1])) # optional - coxeter3 (v^-1+v)*CpC[1,2,1,3] - sage: CpC.product_on_basis(W([1,2,1]), W([3,1,2])) + sage: CpC.product_on_basis(W([1,2,1]), W([3,1,2])) # optional - coxeter3 (v^-1+v)*CpC[1,2,1,3,2] + (v^-1+v)*CpC[1,2,1] """ # Decomposition: write one of C'_{w1} and C'_{w2} as a polynomial in the @@ -3064,20 +3066,29 @@ def _to_Cp_basis(self, w, Cp): - ``Cp`` -- the target `C^{\prime}` basis to use; either ``Cp`` or ``Cp_Coxeter3`` - EXAMPLES:: + EXAMPLES: - sage: A3 = CoxeterGroup('A3', implementation='coxeter3') + :: + + sage: A3 = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 + sage: H = sage.algebras.iwahori_hecke_algebra.IwahoriHeckeAlgebra_nonstandard(A3) # optional - coxeter3 + sage: s1,s2,s3 = A3.simple_reflections() # optional - coxeter3 + sage: T = H.T(); CpC = H.Cp_Coxeter3() # optional - coxeter3 + sage: T._to_Cp_basis(s1, CpC) # optional - coxeter3 + v*CpC[1] + (-u^-1*v^2) + sage: CpC(T(s1)) # optional - coxeter3 + v*CpC[1] + (-u^-1*v^2) + + :: + + sage: A3 = CoxeterGroup('A3') sage: H = sage.algebras.iwahori_hecke_algebra.IwahoriHeckeAlgebra_nonstandard(A3) sage: s1,s2,s3 = A3.simple_reflections() - sage: T = H.T(); Cp = H.Cp(); CpC = H.Cp_Coxeter3() + sage: T = H.T(); Cp = H.Cp() sage: T._to_Cp_basis(s1, Cp) v*Cp[1] + (-u^-1*v^2) sage: Cp(T(s1)) v*Cp[1] + (-u^-1*v^2) - sage: T._to_Cp_basis(s1, CpC) - v*CpC[1] + (-u^-1*v^2) - sage: CpC(T(s1)) - v*CpC[1] + (-u^-1*v^2) """ A = self.realization_of() # Cp = A.Cp() if not use_Cp_Coxeter3 else A.Cp_Coxeter3() @@ -3130,21 +3141,21 @@ def to_Cp_Coxeter3_basis(self, w): EXAMPLES:: - sage: A2 = CoxeterGroup('A2', implementation='coxeter3') - sage: H = sage.algebras.iwahori_hecke_algebra.IwahoriHeckeAlgebra_nonstandard(A2) - sage: s1,s2 = H.coxeter_group().simple_reflections() - sage: T = H.T() - sage: CpC = H.Cp_Coxeter3() - sage: T.to_Cp_Coxeter3_basis(s1) + sage: A2 = CoxeterGroup('A2', implementation='coxeter3') # optional - coxeter3 + sage: H = sage.algebras.iwahori_hecke_algebra.IwahoriHeckeAlgebra_nonstandard(A2) # optional - coxeter3 + sage: s1,s2 = H.coxeter_group().simple_reflections() # optional - coxeter3 + sage: T = H.T() # optional - coxeter3 + sage: CpC = H.Cp_Coxeter3() # optional - coxeter3 + sage: T.to_Cp_Coxeter3_basis(s1) # optional - coxeter3 v*CpC[1] + (-u^-1*v^2) - sage: CpC(T(s1)) + sage: CpC(T(s1)) # optional - coxeter3 v*CpC[1] + (-u^-1*v^2) - sage: CpC(T(s1)+1) + sage: CpC(T(s1)+1) # optional - coxeter3 v*CpC[1] + (-u^-1*v^2+1) - sage: CpC(T(s1*s2)+T(s1)+T(s2)+1) + sage: CpC(T(s1*s2)+T(s1)+T(s2)+1) # optional - coxeter3 v^2*CpC[1,2] + (-u^-1*v^3+v)*CpC[1] + (-u^-1*v^3+v)*CpC[2] + (u^-2*v^4-2*u^-1*v^2+1) - sage: CpC(T(s1*s2*s1)) + sage: CpC(T(s1*s2*s1)) # optional - coxeter3 v^3*CpC[1,2,1] + (-u^-1*v^4)*CpC[1,2] + (-u^-1*v^4)*CpC[2,1] + (u^-2*v^5)*CpC[1] + (u^-2*v^5)*CpC[2] + (-u^-3*v^6) """ From 6acc0ec637f92790dd4c249b2c2ab0f4772fa71d Mon Sep 17 00:00:00 2001 From: Chase Meadors Date: Sat, 31 Jul 2021 15:18:21 -0600 Subject: [PATCH 070/359] Move ALGORITHM to the docstring of product_on_basis --- src/sage/algebras/iwahori_hecke_algebra.py | 95 ++++++++++------------ 1 file changed, 45 insertions(+), 50 deletions(-) diff --git a/src/sage/algebras/iwahori_hecke_algebra.py b/src/sage/algebras/iwahori_hecke_algebra.py index d501b571ed0..24e6261e07d 100644 --- a/src/sage/algebras/iwahori_hecke_algebra.py +++ b/src/sage/algebras/iwahori_hecke_algebra.py @@ -2048,6 +2048,9 @@ class Cp_Coxeter3(_KLHeckeBasis): Cloux's ``coxeter3`` package, which is why the method requires the creation of the Coxeter group using the 'coxeter3' implementation. + The multiplication algorithm is described in detail in + :func:`product_on_basis`. + EXAMPLES: To create the basis, define the Coxeter group with @@ -2170,50 +2173,6 @@ class Cp_Coxeter3(_KLHeckeBasis): algebra with the standard or normalized presentations (i.e., need {q_1,q_2} = {v^2,1} or {q_1,q_2} = {v,-v^-1} as sets) - - ALGORITHM: - - Write `b` for `C^{\prime}`. This class computes each product `b_x \cdot - b_y` in two steps as follows. - - If `\ell(x) \leq \ell(y)`, we first decompose `b_x` into a polynomial in - the generators `b_s (s\in S)` and then multiply that polynomial with - `b_y`. If `\ell(x) > \ell(y)`, we decompose `b_y` into a polynomial in - `b_s (s\in S)` and multiply that polynomial with `b_x`. The second step - (multiplication) is done by repeatedly applying the key formulas - displayed earlier directly. The first step (decomposition) is done by - induction on the Bruhat order as follows: for every element `u\in W` - with length `\ell(u)>1`, pick a left descent `s` of `u` and write `u=sw` - (so `w=su`), then note that - - .. MATH:: C^{\prime}_u = C^{\prime}_s \cdot C^{\prime}_{w} - \sum_{v\le - u; sv< v} \mu(v,w) C^{\prime}_v - - by the key formulas mentioned earlier, where the element `w` and all - elements `v`'s on the right side are lower than `u` in the Bruhat order; - this allows us to finish the computation by decomposing the lower order - terms `b_w` and each `b_v`. For example, for `u=121, s=1, w=21` in type - `A3` we have - - .. MATH:: b_{121} = b_1 b_{21} - b_1, - - where the lower order term `b_{21}` further decomposes into `b_2 b_1`, - therefore `b_{121}=b_1 b_2 b_1 - b_1`. We note that the base cases - `\ell(x)=1` or `\ell(x)=0` of the above induction occur when `x` is - itself a Coxeter generator `s` or the group identity, respectively. The - decomposition is trivial in these cases (we have `b_x=C_s` or `b_x=1`, - the unit of the Hecke algebra). - TODO: Edit seealso; We can probably not reference cell stuff given our - decision on that, and we *can't* reference _Basis.product_on_basis. - coxeter3? - - - .. SEEALSO:: - - [KL1979]_, [Lus2013]_ - :meth: _Basis.product_on_basis, cell stuff - :package?[coxeter3?] - .. TODO:: Accommodate generic presentations of the Hecke algebra other than @@ -2336,7 +2295,7 @@ def _product_with_generator_on_basis(self, s, w, side='left'): sage: CpC._product_with_generator_on_basis(2, W([1,3,2,1,3]), 'right') # optional - coxeter3 CpC[1,2,1,3,2,1] + CpC[1,2,3,2] + CpC[1,3,2,1] """ - # use the product formula described in ALGORITHM + # use the product formula described in product_on_basis if w.has_descent(s, side=side): return self.delta * self.monomial(w) else: @@ -2379,7 +2338,7 @@ def _decompose_into_generators(self, u): r""" Decompose `C^{\prime}_u` into a polynomial in the KL generators `C^{\prime}_s`; see the ALGORITHM section of - :class:`IwahoriHeckeAlgebra.Cp_Coxeter3`. + :func:`product_on_basis`. OUTPUT: @@ -2421,7 +2380,7 @@ def _decompose_into_generators(self, u): if len(u) == 1: return {(u[0],): 1} - # l(y) > 1, use the recursive method described in ALGORITHM + # l(y) > 1, use the recursive method described in product_on_basis s = u[0] w = u[1:] # so CpC_s * CpC_w = CpC_u + lower order terms @@ -2449,9 +2408,45 @@ def product_on_basis(self, w1, w2): Return the expansion of `C^{\prime}_{w_1} \cdot C^{\prime}_{w_2}` in the `C^{\prime}`-basis. - The product is computed in the two steps (decomposition + - multiplication) as described in the ALGORITHM section of - :class:`IwahoriHeckeAlgebra.Cp_Coxeter3` + ALGORITHM: + + This class computes each product `C^{\prime}_x \cdot C^{\prime}_y` + in two steps as follows. + + If `\ell(x) \leq \ell(y)`, we first decompose `C^{\prime}_x` into a + polynomial in the generators `C^{\prime}_s (s\in S)` and then + multiply that polynomial with `C^{\prime}_y`. If `\ell(x) > + \ell(y)`, we decompose `C^{\prime}_y` into a polynomial in + `C^{\prime}_s (s\in S)` and multiply that polynomial with + `C^{\prime}_x`. The second step (multiplication) is done by + repeatedly applying the key formulas displayed earlier directly. The + first step (decomposition) is done by induction on the Bruhat order + as follows: for every element `u\in W` with length `\ell(u)>1`, pick + a left descent `s` of `u` and write `u=sw` (so `w=su`), then note + that + + .. MATH:: C^{\prime}_u = C^{\prime}_s \cdot C^{\prime}_{w} - \sum_{v\le u; sv< v} \mu(v,w) C^{\prime}_v + + by the key formulas mentioned earlier, where the element `w` and all + elements `v`'s on the right side are lower than `u` in the Bruhat + order; this allows us to finish the computation by decomposing the + lower order terms `C^{\prime}_w` and each `C^{\prime}_v`. For + example, for `u=121, s=1, w=21` in type `A_3` we have + `C^{\prime}_{121} = C^{\prime}_1 C^{\prime}_{21} - C^{\prime}_1`, + where the lower order term `C^{\prime}_{21}` further decomposes into + `C^{\prime}_2 C^{\prime}_1`, therefore + + .. MATH:: C^{\prime}_{121}=C^{\prime}_1 C^{\prime}_2 C^{\prime}_1 - C^{\prime}_1 + + We note that the base cases `\ell(x)=1` or `\ell(x)=0` of the above + induction occur when `x` is itself a Coxeter generator `s` or the + group identity, respectively. The decomposition is trivial in these + cases (we have `C^{\prime}_x=C^{\prime}_s` or `C^{\prime}_x=1`, the + unit of the Hecke algebra). + + .. SEEALSO:: + + [KL1979]_, [Lus2013]_ EXAMPLES:: From 7d9d80916d722b5533160d53c840d40c080ca227 Mon Sep 17 00:00:00 2001 From: Chase Meadors Date: Sat, 31 Jul 2021 16:40:12 -0600 Subject: [PATCH 071/359] Tweak class docs --- src/sage/algebras/iwahori_hecke_algebra.py | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/src/sage/algebras/iwahori_hecke_algebra.py b/src/sage/algebras/iwahori_hecke_algebra.py index 24e6261e07d..09eeb27d647 100644 --- a/src/sage/algebras/iwahori_hecke_algebra.py +++ b/src/sage/algebras/iwahori_hecke_algebra.py @@ -2065,24 +2065,18 @@ class Cp_Coxeter3(_KLHeckeBasis): The new basis here (``CpC``) and ``Cp`` basis are both implementations of the the `C^{\prime}` basis. The only difference between the implementations lies in their different methods for computing products, - elements can be converted between the two trivially TODO: I'm not sure - this example block is as useful or clear as it could be:: + elements can be converted between the two trivially:: - sage: s1, s2, s3 = W.simple_reflections() # optional - coxeter3 - sage: Cp = H.Cp() # optional - coxeter3 - sage: a = CpC(s1*s2*s1); a # optional - coxeter3 - CpC[1,2,1] - sage: b = Cp(s1*s2*s1); b # optional - coxeter3 + sage: Cp = H.Cp() # optional - coxeter3 + sage: Cp(CpC[1,2,1]) # optional - coxeter3 Cp[1,2,1] - sage: Cp(a) == b # optional - coxeter3 - True - sage: a == CpC(b) # optional - coxeter3 - True + sage: CpC(Cp[1,2,1]) # optional - coxeter3 + CpC[1,2,1] - Some computations that agree with computations in the existing ``Cp`` - basis; the last example is one that significantly faster in this - implementation than in ``Cp``:: + Some computations; these agree with computations in the existing ``Cp`` + basis:: + sage: s1, s2, s3 = W.simple_reflections() # optional - coxeter3 sage: CpC(s1)**2 # optional - coxeter3 (v^-1+v)*CpC[1] sage: Cp(s1)**2 # optional - coxeter3 From dca76a307b95862314b7e07492e6b92f134662f4 Mon Sep 17 00:00:00 2001 From: Tianyuan Xu Date: Sun, 1 Aug 2021 12:05:08 -0600 Subject: [PATCH 072/359] very minor changes to doc strings --- src/sage/algebras/iwahori_hecke_algebra.py | 54 +++++++++++----------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/src/sage/algebras/iwahori_hecke_algebra.py b/src/sage/algebras/iwahori_hecke_algebra.py index 09eeb27d647..1d2ed32b93b 100644 --- a/src/sage/algebras/iwahori_hecke_algebra.py +++ b/src/sage/algebras/iwahori_hecke_algebra.py @@ -2008,7 +2008,8 @@ class Cp_Coxeter3(_KLHeckeBasis): "standard" presentation where `\{q_1,q_2\} = \{v^2,1\}` as sets or the "normalized" presentations where `\{q_1,q_2\} = \{v,-v^{-1}\}` as sets. The Hecke algebra also needs to be created from a Coxeter group defined - using the 'coxeter3' implementation; see the examples to follow. + using the 'coxeter3' implementation, because this class designates the + computation of certain important coefficients to 'coxeter3'. Expanding products of the form `C^{\prime}_x \cdot C^{\prime}_y` in the `C^{\prime}`-basis is useful for computing Kazhdan-Lusztig cells of @@ -2016,10 +2017,10 @@ class Cp_Coxeter3(_KLHeckeBasis): algebras. The emphasis of this class is to compute such products more directly in the `C^{\prime}`-basis, as opposed to converting the `C^{\prime}`-basis to the `T`-basis, calculating the product in the - `T`-basis, and converting the results back to the `C^{\prime}`-basis, as - is the default technique in ``_Basis.product_on_basis``, used by the - :class:`IwahoriHeckeAlgebra.Cp` basis. The direct method implemented - here significantly speeds up the product computations. + `T`-basis, and converting the results back to the `C^{\prime}`-basis. + The latter approach is used in the function ``_Basis.product_on_basis`` + of for the :class:`IwahoriHeckeAlgebra.Cp` basis. The direct method + implemented here significantly speeds up the product computations. The following formulas for products of the forms `C^{\prime}_s \cdot C^{\prime}_w` and `C^{\prime}_w \cdot C^{\prime}_s`, where `s` is a @@ -2064,8 +2065,8 @@ class Cp_Coxeter3(_KLHeckeBasis): The new basis here (``CpC``) and ``Cp`` basis are both implementations of the the `C^{\prime}` basis. The only difference between the - implementations lies in their different methods for computing products, - elements can be converted between the two trivially:: + implementations lies in their different methods for computing products. + The conversion between ``CpC`` and ``Cp`` is trivial:: sage: Cp = H.Cp() # optional - coxeter3 sage: Cp(CpC[1,2,1]) # optional - coxeter3 @@ -2073,14 +2074,14 @@ class Cp_Coxeter3(_KLHeckeBasis): sage: CpC(Cp[1,2,1]) # optional - coxeter3 CpC[1,2,1] - Some computations; these agree with computations in the existing ``Cp`` - basis:: + Some computations in the ``CpC`` basis; these agree with computations + in the existing ``Cp`` basis:: sage: s1, s2, s3 = W.simple_reflections() # optional - coxeter3 - sage: CpC(s1)**2 # optional - coxeter3 - (v^-1+v)*CpC[1] sage: Cp(s1)**2 # optional - coxeter3 (v^-1+v)*Cp[1] + sage: CpC(s1)**2 # optional - coxeter3 + (v^-1+v)*CpC[1] sage: Cp(s1)*Cp(s2)*Cp(s1) # optional - coxeter3 Cp[1,2,1] + Cp[1] sage: CpC(s1)*CpC(s2)*CpC(s1) # optional - coxeter3 @@ -2090,7 +2091,7 @@ class Cp_Coxeter3(_KLHeckeBasis): sage: CpC[1]*CpC[2]*CpC[3]*CpC[1]*CpC[2] # optional - coxeter3 CpC[1,2,1,3,2] + CpC[1,2,1] + CpC[1,3,2] - A computation in type `H_4` that is significantly faster in this + A computation in type `H_4` that is significantly faster in the ``CpC`` implementation than in the existing ``Cp`` basis:: sage: W = CoxeterGroup('H4', implementation='coxeter3') # optional - coxeter3 @@ -2112,8 +2113,9 @@ class Cp_Coxeter3(_KLHeckeBasis): Below is another example, with the Hecke algebra of type `B_9` in the normalized presentation. The (optional) relabeling command ensures that `m(1,2)=4`, i.e., that the generators 1, 2 form the strong bond in the - Dynkin diagram. The final two examples are calculations that are very - quick using this implementation, but infeasible for the ``Cp`` basis:: + Dynkin diagram. The final two examples are calculations that are quick + in this implementation but seem prohibitively slow for the ``Cp`` + basis:: sage: B9 = CoxeterType(['B', 9]) sage: B9 = B9.relabel({ i: 9-i+1 for i in range(1, 10) }) # optional - coxeter3 @@ -2172,7 +2174,8 @@ class Cp_Coxeter3(_KLHeckeBasis): Accommodate generic presentations of the Hecke algebra other than the standard and normalized ones. - Use analogs of the key formulas to implement `C^{\prime}`-products + Use analogs of the formulas for `C^{\prime}_s C^{\prime}_w` and + `C^{\prime}_w C^{\prime}_s` to implement `C^{\prime}`-products in the multi-parameter Iwahori-Hecke algebra; see Section 6 of [Lus2013]_. """ @@ -2180,7 +2183,7 @@ class Cp_Coxeter3(_KLHeckeBasis): def __init__(self, algebra, prefix='CpC'): r""" - Initialize the Cp_Coxeter3 Kazdahn-Lusztig basis of the + Initialize the Cp_Coxeter3 Kazhdan-Lusztig basis of the Iwahori-Hecke algebra ``algebra''. EXAMPLES: @@ -2226,7 +2229,7 @@ def __init__(self, algebra, prefix='CpC'): parameters = {algebra.q1(), algebra.q2()} if v != algebra.base_ring().one() and (parameters == {v**2, -1} or parameters == {v, -1/v}): # The following quantity delta is used in product computations. - # To use it we need the standard or normalized normalizations. + # To use v+~v as its value we need the standard or normalized presentations of the Hecke algebra. self.delta = v + ~v else: if not algebra._is_generic: @@ -2234,7 +2237,7 @@ def __init__(self, algebra, prefix='CpC'): raise ValueError('the Cp_Coxeter3 basis is only supported in a Hecke algebra with the standard or normalized \ presentations (i.e., need {q_1,q_2} = {v^2,1} or {q_1,q_2} = {v,-v^-1} as sets)') - # Define conversion to the other Cp basis + # Define the (trivial) conversion to the other Cp basis self.module_morphism(self.to_Cp_basis, codomain=algebra.Cp(), category=self.category() ).register_as_coercion() @@ -2289,7 +2292,7 @@ def _product_with_generator_on_basis(self, s, w, side='left'): sage: CpC._product_with_generator_on_basis(2, W([1,3,2,1,3]), 'right') # optional - coxeter3 CpC[1,2,1,3,2,1] + CpC[1,2,3,2] + CpC[1,3,2,1] """ - # use the product formula described in product_on_basis + # use the product formula described in the class' documentation if w.has_descent(s, side=side): return self.delta * self.monomial(w) else: @@ -2337,9 +2340,10 @@ def _decompose_into_generators(self, u): OUTPUT: A dictionary keyed by tuples with integer values. Each entry - represents a term, where the tuple contains the indices of the KL - generators in the term, and its value is the coefficient of that - term. + represents a term, where the tuple represents a monomial term in + the KL generators and the value represents the coefficient of that + term. For example, an item `(1,2): 3` stands for `3 * + C^{\prime}_1C^{\prime}_2`. EXAMPLES: @@ -2430,7 +2434,7 @@ def product_on_basis(self, w1, w2): where the lower order term `C^{\prime}_{21}` further decomposes into `C^{\prime}_2 C^{\prime}_1`, therefore - .. MATH:: C^{\prime}_{121}=C^{\prime}_1 C^{\prime}_2 C^{\prime}_1 - C^{\prime}_1 + .. MATH:: C^{\prime}_{121}=C^{\prime}_1 C^{\prime}_2 C^{\prime}_1 - C^{\prime}_1. We note that the base cases `\ell(x)=1` or `\ell(x)=0` of the above induction occur when `x` is itself a Coxeter generator `s` or the @@ -2438,10 +2442,6 @@ def product_on_basis(self, w1, w2): cases (we have `C^{\prime}_x=C^{\prime}_s` or `C^{\prime}_x=1`, the unit of the Hecke algebra). - .. SEEALSO:: - - [KL1979]_, [Lus2013]_ - EXAMPLES:: sage: R. = LaurentPolynomialRing(ZZ, 'v') # optional - coxeter3 From 4d949013a3e9e248ade7aeef04abb5d486cd0d9a Mon Sep 17 00:00:00 2001 From: Chase Meadors Date: Mon, 9 Aug 2021 16:34:09 -0600 Subject: [PATCH 073/359] Include basic cell computations using the CpC basis. --- src/sage/libs/coxeter3/coxeter_group.py | 99 +++++++++++++++++++++++++ 1 file changed, 99 insertions(+) diff --git a/src/sage/libs/coxeter3/coxeter_group.py b/src/sage/libs/coxeter3/coxeter_group.py index d0c13f12a11..746d6080fdb 100644 --- a/src/sage/libs/coxeter3/coxeter_group.py +++ b/src/sage/libs/coxeter3/coxeter_group.py @@ -9,9 +9,13 @@ # http://www.gnu.org/licenses/ #***************************************************************************** +from collections import deque + from sage.libs.coxeter3.coxeter import get_CoxGroup, CoxGroupElement from sage.misc.cachefunc import cached_method +from sage.graphs.digraph import DiGraph + from sage.structure.unique_representation import UniqueRepresentation from sage.structure.element_wrapper import ElementWrapper from sage.structure.richcmp import richcmp @@ -21,6 +25,7 @@ from sage.combinat.root_system.coxeter_matrix import CoxeterMatrix from sage.rings.integer_ring import ZZ +from sage.rings.polynomial.laurent_polynomial_ring import LaurentPolynomialRing from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing @@ -423,6 +428,100 @@ def parabolic_kazhdan_lusztig_polynomial(self, u, v, J, constant_term_one=True): return P.sum((-1)**(z.length()) * self.kazhdan_lusztig_polynomial(u*z,v, constant_term_one=False).shift(z.length()) for z in WOI if (u*z).bruhat_le(v)) + def kazhdan_lusztig_cell(self, w, side='left'): + r""" + Compute the left, right, or two-sided Kazhdan-Lusztig cell containing + the element ``w``. + + This method products in the `C^{\prime}` basis by using the + :class:`IwahoriHeckeAlgebra.CpC` basis. + + INPUT: + + - ``w`` -- an element of self. + + - ``side`` -- string; one of 'left', 'right', or 'both', corresponding + to the kind of cell to compute. + + EXAMPLES: + + Compute some cells in type `B_3`:: + + sage: W = CoxeterGroup('B3', implementation='coxeter3') # optional - coxeter3 + sage: s1,s2,s3 = W.simple_reflections() # optional - coxeter3 + sage: W.kazhdan_lusztig_cell(s1*s2*s1) # optional - coxeter3 + {[2, 1, 2], [2, 3, 2, 1, 2], [3, 2, 1, 2]} + sage: W.kazhdan_lusztig_cell(s2*s3*s2) # optional - coxeter3 + {[1, 2], [1, 2, 3, 2], [2], [2, 3, 2], [3, 2]} + sage: W.kazhdan_lusztig_cell(s1*s2*s3) # optional - coxeter3 + {[1, 2, 3], [2, 3], [3], [3, 2, 3]} + sage: W.kazhdan_lusztig_cell(s3) # optional - coxeter3 + {[1, 2, 3], [2, 3], [3], [3, 2, 3]} + sage: W.kazhdan_lusztig_cell(s3, side='right') # optional - coxeter3 + {[3], [3, 2], [3, 2, 1], [3, 2, 3]} + sage: W.kazhdan_lusztig_cell(s3, side='both') # optional - coxeter3 + {[1], [1, 2], [1, 2, 3], [1, 2, 3, 2], [1, 2, 3, 2, 1], [2], [2, 1], + [2, 3], [2, 3, 2], [2, 3, 2, 1], [3], [3, 2], [3, 2, 1], [3, 2, 3]} + + Some slightly longer computations in type `B_4`:: + + sage: W = CoxeterGroup('B4', implementation='coxeter3') # optional - coxeter3 + sage: s1,s2,s3,s4 = W.simple_reflections() # optional - coxeter3 + sage: W.kazhdan_lusztig_cell(s1) # long time (4 seconds) # optional - coxeter3 + {[1], + [1, 2, 3, 4, 3, 2, 1], + [2, 1], + [2, 3, 4, 3, 2, 1], + [3, 2, 1], + [3, 4, 3, 2, 1], + [4, 3, 2, 1]} + sage: W.kazhdan_lusztig_cell(s4*s2*s3*s4) # long time (2 seconds) # optional - coxeter3 + {[2, 3, 4, 1, 2, 3, 4], + [3, 4, 1, 2, 3, 4], + [3, 4, 2, 3, 4], + [3, 4, 2, 3, 4, 1, 2, 3, 4], + [4, 1, 2, 3, 4], + [4, 2, 3, 4], + [4, 2, 3, 4, 1, 2, 3, 4], + [4, 3, 4, 1, 2, 3, 4], + [4, 3, 4, 2, 3, 4], + [4, 3, 4, 2, 3, 4, 1, 2, 3, 4]} + """ + from sage.algebras.iwahori_hecke_algebra import IwahoriHeckeAlgebra + + R = LaurentPolynomialRing(ZZ, 'v') + v = R.gen(0) + H = IwahoriHeckeAlgebra(self, v**2) + CpC = H.Cp_Coxeter3() + + w = self(w) + + vertices, edges = {w}, set() + queue = deque([w]) + + while queue: + x = queue.pop() + cp_x = CpC(x) + for s in self.simple_reflections(): + cp_s = CpC(s) + terms = [] + # Determine the Cp basis elements appearing in the product of Cp_s and Cp_w + if side == 'left' or side == 'both': + terms.extend(list(cp_s * cp_x)) + if side == 'right' or side == 'both': + terms.extend(list(cp_x * cp_s)) + for (y, coeff) in terms: + # the result of multiplication will always have coeff != 0 + if y != x: + edges.add((x, y)) + if y not in vertices: + vertices.add(y) + queue.appendleft(y) + + g = DiGraph([list(vertices), list(edges)]) + return set(g.strongly_connected_component_containing_vertex(w)) + + class Element(ElementWrapper): wrapped_class = CoxGroupElement From 8baaf18793a5f9ff37d70dad92a1f942ab91051b Mon Sep 17 00:00:00 2001 From: Chase Meadors Date: Mon, 9 Aug 2021 19:17:24 -0600 Subject: [PATCH 074/359] Change kazhdan_lusztig_cell side argument to accept 'two-sided' instead of 'both' --- src/sage/libs/coxeter3/coxeter_group.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/sage/libs/coxeter3/coxeter_group.py b/src/sage/libs/coxeter3/coxeter_group.py index 746d6080fdb..5349229d0b1 100644 --- a/src/sage/libs/coxeter3/coxeter_group.py +++ b/src/sage/libs/coxeter3/coxeter_group.py @@ -440,8 +440,8 @@ def kazhdan_lusztig_cell(self, w, side='left'): - ``w`` -- an element of self. - - ``side`` -- string; one of 'left', 'right', or 'both', corresponding - to the kind of cell to compute. + - ``side`` -- string (default: ``'left'``); one of 'left', 'right', or + 'two-sided', corresponding to the kind of cell to compute. EXAMPLES: @@ -459,7 +459,7 @@ def kazhdan_lusztig_cell(self, w, side='left'): {[1, 2, 3], [2, 3], [3], [3, 2, 3]} sage: W.kazhdan_lusztig_cell(s3, side='right') # optional - coxeter3 {[3], [3, 2], [3, 2, 1], [3, 2, 3]} - sage: W.kazhdan_lusztig_cell(s3, side='both') # optional - coxeter3 + sage: W.kazhdan_lusztig_cell(s3, side='two-sided') # optional - coxeter3 {[1], [1, 2], [1, 2, 3], [1, 2, 3, 2], [1, 2, 3, 2, 1], [2], [2, 1], [2, 3], [2, 3, 2], [2, 3, 2, 1], [3], [3, 2], [3, 2, 1], [3, 2, 3]} @@ -506,9 +506,9 @@ def kazhdan_lusztig_cell(self, w, side='left'): cp_s = CpC(s) terms = [] # Determine the Cp basis elements appearing in the product of Cp_s and Cp_w - if side == 'left' or side == 'both': + if side == 'left' or side == 'two-sided': terms.extend(list(cp_s * cp_x)) - if side == 'right' or side == 'both': + if side == 'right' or side == 'two-sided': terms.extend(list(cp_x * cp_s)) for (y, coeff) in terms: # the result of multiplication will always have coeff != 0 From 79d843fe1484a951b09ee9eb3c84c93fc74e5ac2 Mon Sep 17 00:00:00 2001 From: Chase Meadors Date: Mon, 9 Aug 2021 19:18:08 -0600 Subject: [PATCH 075/359] Improve kazhdan_lusztig_cell docstring --- src/sage/libs/coxeter3/coxeter_group.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/sage/libs/coxeter3/coxeter_group.py b/src/sage/libs/coxeter3/coxeter_group.py index 5349229d0b1..09970bec27b 100644 --- a/src/sage/libs/coxeter3/coxeter_group.py +++ b/src/sage/libs/coxeter3/coxeter_group.py @@ -431,7 +431,8 @@ def parabolic_kazhdan_lusztig_polynomial(self, u, v, J, constant_term_one=True): def kazhdan_lusztig_cell(self, w, side='left'): r""" Compute the left, right, or two-sided Kazhdan-Lusztig cell containing - the element ``w``. + the element ``w``. Computes left cells by default; use the optional + argument ``side`` to specify right or two-sided cells. This method products in the `C^{\prime}` basis by using the :class:`IwahoriHeckeAlgebra.CpC` basis. From 863520c57c6e728eccd4269b82cef7d4e576d932 Mon Sep 17 00:00:00 2001 From: Chase Meadors Date: Mon, 9 Aug 2021 19:35:34 -0600 Subject: [PATCH 076/359] Add A9 example to class docs --- src/sage/algebras/iwahori_hecke_algebra.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/sage/algebras/iwahori_hecke_algebra.py b/src/sage/algebras/iwahori_hecke_algebra.py index 1d2ed32b93b..b0b6d81daaa 100644 --- a/src/sage/algebras/iwahori_hecke_algebra.py +++ b/src/sage/algebras/iwahori_hecke_algebra.py @@ -2074,8 +2074,8 @@ class Cp_Coxeter3(_KLHeckeBasis): sage: CpC(Cp[1,2,1]) # optional - coxeter3 CpC[1,2,1] - Some computations in the ``CpC`` basis; these agree with computations - in the existing ``Cp`` basis:: + Some computations in the ``CpC`` basis; these agree with computations in + the existing ``Cp`` basis:: sage: s1, s2, s3 = W.simple_reflections() # optional - coxeter3 sage: Cp(s1)**2 # optional - coxeter3 @@ -2110,6 +2110,18 @@ class Cp_Coxeter3(_KLHeckeBasis): + (v^-3+3*v^-1+3*v+v^3)*CpC[4,3,4,3,4,1] + (v^-1+v)*CpC[3,4,1,2] + A computation in type `A_9` that seems prohibitively slow for the ``Cp`` + basis:: + + sage: W = CoxeterGroup('A9', implementation='coxeter3') # optional - coxeter3 + sage: H = IwahoriHeckeAlgebra(W, v**2) # optional - coxeter3 + sage: CpC = H.Cp_Coxeter3() # optional - coxeter3 + sage: CpC[1,2,1,8,9,8]*CpC[1,2,3,7,8,9] # optional - coxeter3 + (v^-2+2+v^2)*CpC[1,2,1,3,7,8,7,9,8,7] + + (v^-2+2+v^2)*CpC[1,2,1,3,8,9,8,7] + + (v^-3+3*v^-1+3*v+v^3)*CpC[1,2,1,3,8,9,8] + + Below is another example, with the Hecke algebra of type `B_9` in the normalized presentation. The (optional) relabeling command ensures that `m(1,2)=4`, i.e., that the generators 1, 2 form the strong bond in the From c34b92aa952f2892fc0e89f02c76aee3432f9e85 Mon Sep 17 00:00:00 2001 From: Tianyuan Xu Date: Wed, 11 Aug 2021 15:58:49 -0600 Subject: [PATCH 077/359] slight change to doc string for KL cell function --- src/sage/libs/coxeter3/coxeter_group.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/sage/libs/coxeter3/coxeter_group.py b/src/sage/libs/coxeter3/coxeter_group.py index 09970bec27b..4f5840b8445 100644 --- a/src/sage/libs/coxeter3/coxeter_group.py +++ b/src/sage/libs/coxeter3/coxeter_group.py @@ -434,8 +434,13 @@ def kazhdan_lusztig_cell(self, w, side='left'): the element ``w``. Computes left cells by default; use the optional argument ``side`` to specify right or two-sided cells. - This method products in the `C^{\prime}` basis by using the - :class:`IwahoriHeckeAlgebra.CpC` basis. + Two elements `x,y` of a Coxeter group `W` are said lie in the same left Kazhdan-Lusztig cell if there exist + sequences `x=w_1, w_2, ..., w_k=y` and `y=u_1, u_2, ..., u_l=x` such that for all `1 \leq i < k` and all `1 + \leq j < l`, there exist some Coxeter generators `s,t` for which `C'_{w_{i+1}}` appears in `C'_sC'_{w_i}` + and `C'_{u_{j+1}}` appears in `C'_sC'_{u_j}` in the Hecke algebra of the Coxeter group, where `C'` denotes + the Kazhdan-Lusztig `C^{\prime}`-basis. Right and two-sided Kazhdan-Lusztig cells of `W` are defined + similarly. In this function, we compute products of the form `C_sC_w` using the function + :func:`product_on_basis` of the class :class:`IwahoriHeckeAlgebra.Cp_Coxeter3`. INPUT: @@ -454,8 +459,6 @@ def kazhdan_lusztig_cell(self, w, side='left'): {[2, 1, 2], [2, 3, 2, 1, 2], [3, 2, 1, 2]} sage: W.kazhdan_lusztig_cell(s2*s3*s2) # optional - coxeter3 {[1, 2], [1, 2, 3, 2], [2], [2, 3, 2], [3, 2]} - sage: W.kazhdan_lusztig_cell(s1*s2*s3) # optional - coxeter3 - {[1, 2, 3], [2, 3], [3], [3, 2, 3]} sage: W.kazhdan_lusztig_cell(s3) # optional - coxeter3 {[1, 2, 3], [2, 3], [3], [3, 2, 3]} sage: W.kazhdan_lusztig_cell(s3, side='right') # optional - coxeter3 From 01ce92a7f9cfad0169e2fb3b959b8fe39b7486f1 Mon Sep 17 00:00:00 2001 From: Chase Meadors Date: Wed, 11 Aug 2021 18:45:33 -0600 Subject: [PATCH 078/359] Remove unused import --- src/sage/algebras/iwahori_hecke_algebra.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/sage/algebras/iwahori_hecke_algebra.py b/src/sage/algebras/iwahori_hecke_algebra.py index b0b6d81daaa..2cc262a6117 100644 --- a/src/sage/algebras/iwahori_hecke_algebra.py +++ b/src/sage/algebras/iwahori_hecke_algebra.py @@ -37,7 +37,6 @@ from sage.combinat.root_system.coxeter_group import CoxeterGroup from sage.combinat.family import Family from sage.combinat.free_module import CombinatorialFreeModule -from sage.algebras.free_algebra import FreeAlgebra from sage.libs.coxeter3.coxeter_group import CoxeterGroup as Coxeter3Group From 7428c98b5d8c11bb35dbcd6bc2528198de2174be Mon Sep 17 00:00:00 2001 From: Chase Meadors Date: Thu, 12 Aug 2021 11:19:52 -0600 Subject: [PATCH 079/359] Trim whitespace / fix pycodestyle errors --- src/sage/algebras/iwahori_hecke_algebra.py | 45 +++++++++++----------- src/sage/libs/coxeter3/coxeter_group.py | 5 +-- 2 files changed, 24 insertions(+), 26 deletions(-) diff --git a/src/sage/algebras/iwahori_hecke_algebra.py b/src/sage/algebras/iwahori_hecke_algebra.py index 2cc262a6117..5ef71273363 100644 --- a/src/sage/algebras/iwahori_hecke_algebra.py +++ b/src/sage/algebras/iwahori_hecke_algebra.py @@ -10,8 +10,8 @@ Kazhdan-Lusztig `C` and `C^{\prime}` bases - Chase Meadors, Tianyuan Xu (2021): - Implemented direct computation of products in the - `C^{\prime}` basis using du Cloux's Coxeter3 package + Implemented direct computation of products in the + `C^{\prime}` basis using du Cloux's Coxeter3 package """ # **************************************************************************** @@ -2026,7 +2026,7 @@ class Cp_Coxeter3(_KLHeckeBasis): generator of the Coxeter group and `w` an arbitrary element, are key to this class. The formulas are valid for both the standard and normalized presentation of the Hecke algebra, and they control the products of the - `C^{\prime}_x \cdot C^{\prime}_y` for arbitrary `x,y`. + `C^{\prime}_x \cdot C^{\prime}_y` for arbitrary `x,y`. .. MATH:: C^{\prime}_s \cdot C^{\prime}_w = \begin{cases} (q+q^-1)C^{\prime}_{w}, & \text{if } \ell(sw) = \ell(w)-1,\\ @@ -2034,11 +2034,11 @@ class Cp_Coxeter3(_KLHeckeBasis): & \text{if } \ell(sw) = \ell(w)+1. \end{cases} - C^{\prime}_w \cdot C^{\prime}_s = + C^{\prime}_w \cdot C^{\prime}_s = \begin{cases} (q+q^-1)C^{\prime}_{w}, & \text{if } \ell(ws) = \ell(w)-1,\\ - C^{\prime}_{ws}+\sum_{v\leq w, vs \leq v} \mu(v,w)C^{\prime}_v, - & \text{if } \ell(ws) = \ell(w)+1. + C^{\prime}_{ws}+\sum_{v\leq w, vs \leq v} \mu(v,w)C^{\prime}_v, + & \text{if } \ell(ws) = \ell(w)+1. \end{cases} In the above, `\leq` is the Bruhat order on the Coxeter group and @@ -2119,7 +2119,7 @@ class Cp_Coxeter3(_KLHeckeBasis): (v^-2+2+v^2)*CpC[1,2,1,3,7,8,7,9,8,7] + (v^-2+2+v^2)*CpC[1,2,1,3,8,9,8,7] + (v^-3+3*v^-1+3*v+v^3)*CpC[1,2,1,3,8,9,8] - + Below is another example, with the Hecke algebra of type `B_9` in the normalized presentation. The (optional) relabeling command ensures that @@ -2162,7 +2162,7 @@ class Cp_Coxeter3(_KLHeckeBasis): be created first with ``implementation='coxeter3'``. Directly creating a Hecke algebra from its Coxeter type does not work:: - sage: H = IwahoriHeckeAlgebra('A3', v**2) # optional - coxeter3 + sage: H = IwahoriHeckeAlgebra('A3', v**2) # optional - coxeter3 sage: H.Cp_Coxeter3() # optional - coxeter3 Traceback (most recent call last): ... @@ -2172,7 +2172,7 @@ class Cp_Coxeter3(_KLHeckeBasis): with the standard or normalized presentation mentioned before:: sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 - sage: H = IwahoriHeckeAlgebra(W, QQ(1)) # optional - coxeter3 + sage: H = IwahoriHeckeAlgebra(W, QQ(1)) # optional - coxeter3 sage: H.Cp_Coxeter3() # optional - coxeter3 Traceback (most recent call last): ... @@ -2220,7 +2220,7 @@ def __init__(self, algebra, prefix='CpC'): Invalid construction (bad presentation for Hecke algebra):: sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 - sage: H = IwahoriHeckeAlgebra(W, QQ(1)) # optional - coxeter3 + sage: H = IwahoriHeckeAlgebra(W, QQ(1)) # optional - coxeter3 sage: H.Cp_Coxeter3() # optional - coxeter3 Traceback (most recent call last): ... @@ -2317,10 +2317,10 @@ def _product_with_generator_on_basis(self, s, w, side='left'): element += x.mu_coefficient(w) * self.monomial(x_elt) longer_word = self._W([s]) * w if side == 'left' else w * self._W([s]) return self.monomial(longer_word) + element - - def _product_with_generator(self, s, x, side='left'): - r""" - Compute the product of `C^{\prime}_s` with any linear combination of `C^{\prime}`-basis elements. + + def _product_with_generator(self, s, x, side='left'): + r""" + Compute the product of `C^{\prime}_s` with any linear combination of `C^{\prime}`-basis elements. INPUT: @@ -2342,7 +2342,7 @@ def _product_with_generator(self, s, x, side='left'): """ return self.linear_combination((self._product_with_generator_on_basis(s, w, side), coeff) for (w, coeff) in x) - def _decompose_into_generators(self, u): + def _decompose_into_generators(self, u): r""" Decompose `C^{\prime}_u` into a polynomial in the KL generators `C^{\prime}_s`; see the ALGORITHM section of @@ -2373,13 +2373,13 @@ def _decompose_into_generators(self, u): (e.g., CpC_{21} = CpC_2 * CpC_1):: sage: CpC._decompose_into_generators(W([2,1])) # optional - coxeter3 - {(2, 1): 1} + {(2, 1): 1} In more general situations the sum is a polynomial (e.g., CpC_{121}=CpC_1*CpC_2*CpC_1-CpC_1):: sage: CpC._decompose_into_generators(W([1,2,1])) # optional - coxeter3 - {(1,): -1, (1, 2, 1): 1} + {(1,): -1, (1, 2, 1): 1} sage: CpC._decompose_into_generators(W([1,2,3,1,2])) # optional - coxeter3 {(1,): 1, (1, 2, 1): -1, (1, 2, 1, 3, 2): 1, (1, 3, 2): -1} """ @@ -2401,7 +2401,7 @@ def _decompose_into_generators(self, u): v_elt = self._W(v) if v_elt.has_left_descent(s): # Compute mu-coefficient via coxeter3 - sum_term += self.base_ring()(v.mu_coefficient(w)) * self.monomial(v_elt) + sum_term += self.base_ring()(v.mu_coefficient(w)) * self.monomial(v_elt) # recursion: decompose C'_s * C'_w and the lower order terms result = {(s,) + gens: coeff for (gens, coeff) in self._decompose_into_generators(w).items()} @@ -2409,9 +2409,9 @@ def _decompose_into_generators(self, u): # Subtract off each term from sum_term. for (gens, c2) in self._decompose_into_generators(z).items(): result[gens] = result.get(gens, 0) - c1*c2 - + return result - + def product_on_basis(self, w1, w2): r""" Return the expansion of `C^{\prime}_{w_1} \cdot C^{\prime}_{w_2}` in @@ -2420,7 +2420,7 @@ def product_on_basis(self, w1, w2): ALGORITHM: This class computes each product `C^{\prime}_x \cdot C^{\prime}_y` - in two steps as follows. + in two steps as follows. If `\ell(x) \leq \ell(y)`, we first decompose `C^{\prime}_x` into a polynomial in the generators `C^{\prime}_s (s\in S)` and then @@ -2464,7 +2464,7 @@ def product_on_basis(self, w1, w2): (v^-1+v)*CpC[1,2,1,3,2] + (v^-1+v)*CpC[1,2,1] """ # Decomposition: write one of C'_{w1} and C'_{w2} as a polynomial in the - # generators C'_{s}. + # generators C'_{s}. if len(w1) <= len(w2): side = 'left' gen_expression = self._decompose_into_generators(w1) @@ -2483,7 +2483,6 @@ def product_on_basis(self, w1, w2): summand = self._product_with_generator(s, summand, side) result += summand return result - class C(_KLHeckeBasis): r""" diff --git a/src/sage/libs/coxeter3/coxeter_group.py b/src/sage/libs/coxeter3/coxeter_group.py index 4f5840b8445..7c3f0cfd509 100644 --- a/src/sage/libs/coxeter3/coxeter_group.py +++ b/src/sage/libs/coxeter3/coxeter_group.py @@ -440,7 +440,7 @@ def kazhdan_lusztig_cell(self, w, side='left'): and `C'_{u_{j+1}}` appears in `C'_sC'_{u_j}` in the Hecke algebra of the Coxeter group, where `C'` denotes the Kazhdan-Lusztig `C^{\prime}`-basis. Right and two-sided Kazhdan-Lusztig cells of `W` are defined similarly. In this function, we compute products of the form `C_sC_w` using the function - :func:`product_on_basis` of the class :class:`IwahoriHeckeAlgebra.Cp_Coxeter3`. + :func:`product_on_basis` of the class :class:`IwahoriHeckeAlgebra.Cp_Coxeter3`. INPUT: @@ -521,11 +521,10 @@ def kazhdan_lusztig_cell(self, w, side='left'): if y not in vertices: vertices.add(y) queue.appendleft(y) - + g = DiGraph([list(vertices), list(edges)]) return set(g.strongly_connected_component_containing_vertex(w)) - class Element(ElementWrapper): wrapped_class = CoxGroupElement From 5f1ab3e42c082cb22f7faba60c319a67efa1923b Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Fri, 13 Aug 2021 12:12:00 +1000 Subject: [PATCH 080/359] Added example from ticket and coxeter3 optional marker for doctests. --- src/sage/libs/coxeter3/coxeter_group.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/sage/libs/coxeter3/coxeter_group.py b/src/sage/libs/coxeter3/coxeter_group.py index d0c13f12a11..38fe82451ff 100644 --- a/src/sage/libs/coxeter3/coxeter_group.py +++ b/src/sage/libs/coxeter3/coxeter_group.py @@ -171,10 +171,10 @@ def from_reduced_word(self, w): EXAMPLES:: - sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') - sage: W.from_reduced_word([1, 3]) + sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3 + sage: W.from_reduced_word([1, 3]) # optional - coxeter3 [1, 3] - sage: W.from_reduced_word([3, 1]) + sage: W.from_reduced_word([3, 1]) # optional - coxeter3 [1, 3] """ return self.element_class(self, w) @@ -433,6 +433,17 @@ def __init__(self, parent, x): sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3 sage: W([2,1,2]) # optional - coxeter3 [1, 2, 1] + + Check that :trac:`32266` is fixed:: + + sage: A3 = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 + sage: s1,s2,s3 = A3.simple_reflections() # optional - coxeter3 + sage: s1*s3 # optional - coxeter3 + [1, 3] + sage: s3*s1 # optional - coxeter3 + [1, 3] + sage: s3*s1 == s1*s3 # optional - coxeter3 + True """ if not isinstance(x, CoxGroupElement): x = CoxGroupElement(parent._coxgroup, x).reduced() From 6492ab1b9433b53eede0b4c640853d208e5b4191 Mon Sep 17 00:00:00 2001 From: Chase Meadors Date: Fri, 13 Aug 2021 09:35:00 -0600 Subject: [PATCH 081/359] Remove basis coercions in prep for integrating into the Cp class --- src/sage/algebras/iwahori_hecke_algebra.py | 145 ++------------------- 1 file changed, 13 insertions(+), 132 deletions(-) diff --git a/src/sage/algebras/iwahori_hecke_algebra.py b/src/sage/algebras/iwahori_hecke_algebra.py index 5ef71273363..b20c84303e7 100644 --- a/src/sage/algebras/iwahori_hecke_algebra.py +++ b/src/sage/algebras/iwahori_hecke_algebra.py @@ -1580,30 +1580,6 @@ def to_Cp_basis(self, w): generic_T = H._generic_iwahori_hecke_algebra.T() return generic_T.to_Cp_basis(w).specialize_to(H) - def to_Cp_Coxeter3_basis(self, w): - r""" - Return `T_w` as a linear combination of `C^{\prime}`-basis elements, - using the ``Cp_Coxeter3`` basis. - - EXAMPLES:: - - sage: R. = LaurentPolynomialRing(ZZ, 'v') # optional - coxeter3 - sage: A3 = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 - sage: H = IwahoriHeckeAlgebra(A3, v**2); T=H.T(); CpC=H.Cp_Coxeter3() # optional - coxeter3 - sage: s1,s2,s3 = A3.simple_reflections() # optional - coxeter3 - sage: T.to_Cp_Coxeter3_basis(s1) # optional - coxeter3 - v*CpC[1] - 1 - sage: CpC(T(s1)) # optional - coxeter3 - v*CpC[1] - 1 - sage: CpC(T[1] + 1) # optional - coxeter3 - v*CpC[1] - sage: CpC(T[1,2] + T[1] + T[2] + 1) # optional - coxeter3 - v^2*CpC[1,2] - """ - H = self.realization_of() - generic_T = H._generic_iwahori_hecke_algebra.T() - return generic_T.to_Cp_Coxeter3_basis(w).specialize_to(H) - def bar_on_basis(self, w): """ Return the bar involution of `T_w`, which is `T^{-1}_{w^-1}`. @@ -1955,26 +1931,6 @@ class Cp(_KLHeckeBasis): """ _basis_name = 'Cp' # this is used, for example, by specialize_to and is the default prefix - def to_Cp_Coxeter3_basis(self, w): - r""" - Return ``self[w]`` as an element of the ``Cp_Coxeter3`` basis. This - transformation is trivial since both bases are implementations of - the `C^{\prime}` basis. - - EXAMPLES:: - - sage: R. = LaurentPolynomialRing(ZZ, 'v') - sage: A3 = CoxeterGroup('A3', implementation='coxeter3') - sage: H = IwahoriHeckeAlgebra(A3, v**2); Cp = H.Cp(); CpC=H.Cp_Coxeter3() - sage: Cp.to_Cp_Coxeter3_basis(A3([1,2])) - CpC[1,2] - sage: CpC(Cp[1,2]) - CpC[1,2] - """ - A = self.realization_of() - CpC = A.Cp_Coxeter3() - return CpC.monomial(w) - def hash_involution_on_basis(self, w): r""" Return the effect of applying the hash involution to the basis @@ -3053,62 +3009,11 @@ class T(IwahoriHeckeAlgebra.T): r""" The `T`-basis for the generic Iwahori-Hecke algebra. """ - def _to_Cp_basis(self, w, Cp): - r""" - Return `T_w` as a linear combination of `C^{\prime}`-basis elements, - using either the ``Cp`` basis or the ``Cp_Coxeter3`` implementation. - - INPUT: - - - ``w`` -- a word in self.coxeter_group() - - - ``Cp`` -- the target `C^{\prime}` basis to use; either ``Cp`` or - ``Cp_Coxeter3`` - - EXAMPLES: - - :: - - sage: A3 = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 - sage: H = sage.algebras.iwahori_hecke_algebra.IwahoriHeckeAlgebra_nonstandard(A3) # optional - coxeter3 - sage: s1,s2,s3 = A3.simple_reflections() # optional - coxeter3 - sage: T = H.T(); CpC = H.Cp_Coxeter3() # optional - coxeter3 - sage: T._to_Cp_basis(s1, CpC) # optional - coxeter3 - v*CpC[1] + (-u^-1*v^2) - sage: CpC(T(s1)) # optional - coxeter3 - v*CpC[1] + (-u^-1*v^2) - - :: - - sage: A3 = CoxeterGroup('A3') - sage: H = sage.algebras.iwahori_hecke_algebra.IwahoriHeckeAlgebra_nonstandard(A3) - sage: s1,s2,s3 = A3.simple_reflections() - sage: T = H.T(); Cp = H.Cp() - sage: T._to_Cp_basis(s1, Cp) - v*Cp[1] + (-u^-1*v^2) - sage: Cp(T(s1)) - v*Cp[1] + (-u^-1*v^2) - """ - A = self.realization_of() - # Cp = A.Cp() if not use_Cp_Coxeter3 else A.Cp_Coxeter3() - - if w == A._W.one(): # the identity element of the Coxeter group - return Cp.one() - - T0 = self.zero() - inp = self.monomial(w) - result = Cp.zero() - while inp != T0: - (x, c) = inp.trailing_item(key=sorting_key) - inp = inp - c * A._root**x.length() * Cp.to_T_basis(x) - result = result + c * A._root**x.length() * Cp.monomial(x) - - return result - @cached_method def to_Cp_basis(self, w): r""" - Return `T_w` as a linear combination of `C^{\prime}`-basis elements + Return `T_w` as a linear combination of `C^{\prime}`-basis + elements. EXAMPLES:: @@ -3130,36 +3035,20 @@ def to_Cp_basis(self, w): + (u^-2*v^5)*Cp[1] + (u^-2*v^5)*Cp[2] + (-u^-3*v^6) """ A = self.realization_of() - return self._to_Cp_basis(w, A.Cp()) + Cp = A.Cp() - @cached_method - def to_Cp_Coxeter3_basis(self, w): - r""" - Return `T_w` as a linear combination of `C^{\prime}`-basis elements, - using the ``Cp_Coxeter3`` implementation. + if w == A._W.one(): # the identity element of the Coxeter group + return Cp.one() - EXAMPLES:: + T0 = self.zero() + inp = self.monomial(w) + result = Cp.zero() + while inp != T0: + (x, c) = inp.trailing_item(key=sorting_key) + inp = inp - c * A._root**x.length() * Cp.to_T_basis(x) + result = result + c * A._root**x.length() * Cp.monomial(x) - sage: A2 = CoxeterGroup('A2', implementation='coxeter3') # optional - coxeter3 - sage: H = sage.algebras.iwahori_hecke_algebra.IwahoriHeckeAlgebra_nonstandard(A2) # optional - coxeter3 - sage: s1,s2 = H.coxeter_group().simple_reflections() # optional - coxeter3 - sage: T = H.T() # optional - coxeter3 - sage: CpC = H.Cp_Coxeter3() # optional - coxeter3 - sage: T.to_Cp_Coxeter3_basis(s1) # optional - coxeter3 - v*CpC[1] + (-u^-1*v^2) - sage: CpC(T(s1)) # optional - coxeter3 - v*CpC[1] + (-u^-1*v^2) - sage: CpC(T(s1)+1) # optional - coxeter3 - v*CpC[1] + (-u^-1*v^2+1) - sage: CpC(T(s1*s2)+T(s1)+T(s2)+1) # optional - coxeter3 - v^2*CpC[1,2] + (-u^-1*v^3+v)*CpC[1] + (-u^-1*v^3+v)*CpC[2] - + (u^-2*v^4-2*u^-1*v^2+1) - sage: CpC(T(s1*s2*s1)) # optional - coxeter3 - v^3*CpC[1,2,1] + (-u^-1*v^4)*CpC[1,2] + (-u^-1*v^4)*CpC[2,1] - + (u^-2*v^5)*CpC[1] + (u^-2*v^5)*CpC[2] + (-u^-3*v^6) - """ - A = self.realization_of() - return self._to_Cp_basis(w, A.Cp_Coxeter3()) + return result @cached_method def to_C_basis(self, w): @@ -3272,14 +3161,6 @@ def key_func(x): C_prime = Cp - class Cp_Coxeter3(IwahoriHeckeAlgebra.Cp_Coxeter3): - @cached_method - def to_T_basis(self, w): - A = self.realization_of() - Cp = A.Cp() - T = A.T() - return T(Cp.monomial(w)) - class C(IwahoriHeckeAlgebra.C): r""" The Kazhdan-Lusztig `C`-basis for the generic Iwahori-Hecke algebra. From aa63aaa62e6dc457ac0db7616592d7d0ca15f64d Mon Sep 17 00:00:00 2001 From: bhutz Date: Fri, 13 Aug 2021 10:46:11 -0500 Subject: [PATCH 082/359] 31994: removed duplicated import --- 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 d2bc3d22592..0eb9aada345 100644 --- a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py +++ b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py @@ -52,7 +52,7 @@ class initialization directly. # https://www.gnu.org/licenses/ # **************************************************************************** -from sage.arith.misc import is_prime, moebius +from sage.arith.misc import is_prime from sage.calculus.functions import jacobian from sage.categories.fields import Fields from sage.categories.function_fields import FunctionFields From ac2c397d65bc42da10ece4826d5707879d206543 Mon Sep 17 00:00:00 2001 From: Chase Meadors Date: Fri, 13 Aug 2021 10:10:57 -0600 Subject: [PATCH 083/359] Draft implementation of the functionality integrated with Cp --- src/sage/algebras/iwahori_hecke_algebra.py | 323 +++------------------ 1 file changed, 36 insertions(+), 287 deletions(-) diff --git a/src/sage/algebras/iwahori_hecke_algebra.py b/src/sage/algebras/iwahori_hecke_algebra.py index b20c84303e7..a349a709e5a 100644 --- a/src/sage/algebras/iwahori_hecke_algebra.py +++ b/src/sage/algebras/iwahori_hecke_algebra.py @@ -1931,6 +1931,28 @@ class Cp(_KLHeckeBasis): """ _basis_name = 'Cp' # this is used, for example, by specialize_to and is the default prefix + def __init__(self, IHAlgebra, prefix=None): + r""" + TODO: docstring + """ + super().__init__(IHAlgebra, prefix) + + v = IHAlgebra.base_ring().gen(0) + parameters = {IHAlgebra.q1(), IHAlgebra.q2()} + if v != IHAlgebra.base_ring().one() and (parameters == {v**2, -1} or parameters == {v, -1/v}): + # The following quantity delta is used in product computations. + # To use v+~v as its value we need the standard or normalized presentations of the Hecke algebra. + self.delta = v + ~v + + try: + from sage.libs.coxeter3.coxeter_group import CoxeterGroup as Coxeter3Group + if isinstance(IHAlgebra._W, Coxeter3Group): + self._W_Coxeter3 = IHAlgebra._W + else: + self._W_Coxeter3 = CoxeterGroup(IHAlgebra._W.coxeter_type(), implementation='coxeter3') + except ImportError: + pass + def hash_involution_on_basis(self, w): r""" Return the effect of applying the hash involution to the basis @@ -1952,288 +1974,6 @@ def hash_involution_on_basis(self, w): """ return (-1)**w.length() * self(self.realization_of().C().monomial(w)) - C_prime = Cp - - class Cp_Coxeter3(_KLHeckeBasis): - r""" - Directly compute products in the `C^{\prime}`-basis by using du Cloux's - Coxeter3 package. - - To use this class, the Hecke algebra needs to be created in the - "standard" presentation where `\{q_1,q_2\} = \{v^2,1\}` as sets or the - "normalized" presentations where `\{q_1,q_2\} = \{v,-v^{-1}\}` as sets. - The Hecke algebra also needs to be created from a Coxeter group defined - using the 'coxeter3' implementation, because this class designates the - computation of certain important coefficients to 'coxeter3'. - - Expanding products of the form `C^{\prime}_x \cdot C^{\prime}_y` in the - `C^{\prime}`-basis is useful for computing Kazhdan-Lusztig cells of - Coxeter systems and the corresponding cell modules of Iwahori-Hecke - algebras. The emphasis of this class is to compute such products more - directly in the `C^{\prime}`-basis, as opposed to converting the - `C^{\prime}`-basis to the `T`-basis, calculating the product in the - `T`-basis, and converting the results back to the `C^{\prime}`-basis. - The latter approach is used in the function ``_Basis.product_on_basis`` - of for the :class:`IwahoriHeckeAlgebra.Cp` basis. The direct method - implemented here significantly speeds up the product computations. - - The following formulas for products of the forms `C^{\prime}_s \cdot - C^{\prime}_w` and `C^{\prime}_w \cdot C^{\prime}_s`, where `s` is a - generator of the Coxeter group and `w` an arbitrary element, are key to - this class. The formulas are valid for both the standard and normalized - presentation of the Hecke algebra, and they control the products of the - `C^{\prime}_x \cdot C^{\prime}_y` for arbitrary `x,y`. - - .. MATH:: C^{\prime}_s \cdot C^{\prime}_w = \begin{cases} - (q+q^-1)C^{\prime}_{w}, & \text{if } \ell(sw) = \ell(w)-1,\\ - C^{\prime}_{sw}+\sum_{v\leq w, sv \leq v} \mu(v,w)C^{\prime}_v, - & \text{if } \ell(sw) = - \ell(w)+1. \end{cases} - - C^{\prime}_w \cdot C^{\prime}_s = - \begin{cases} - (q+q^-1)C^{\prime}_{w}, & \text{if } \ell(ws) = \ell(w)-1,\\ - C^{\prime}_{ws}+\sum_{v\leq w, vs \leq v} \mu(v,w)C^{\prime}_v, - & \text{if } \ell(ws) = \ell(w)+1. - \end{cases} - - In the above, `\leq` is the Bruhat order on the Coxeter group and - `\mu(v,w)` is the "leading coefficient of Kazhdan-Lusztig polynomials"; - see [KL1979]_ and [Lus2013]_ for more details. The method designates the - computation of the `\mu`-coefficients to Sage's interface to Fokko du - Cloux's ``coxeter3`` package, which is why the method requires the - creation of the Coxeter group using the 'coxeter3' implementation. - - The multiplication algorithm is described in detail in - :func:`product_on_basis`. - - EXAMPLES: - - To create the basis, define the Coxeter group with - ``implementation='coxeter3'`` and the Hecke algebra with the standard or - normalized presentation:: - - sage: R. = LaurentPolynomialRing(ZZ) # optional - coxeter3 - sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 - sage: H = IwahoriHeckeAlgebra(W, v**2) # optional - coxeter3 - sage: CpC = H.Cp_Coxeter3() # optional - coxeter3 - - The new basis here (``CpC``) and ``Cp`` basis are both implementations - of the the `C^{\prime}` basis. The only difference between the - implementations lies in their different methods for computing products. - The conversion between ``CpC`` and ``Cp`` is trivial:: - - sage: Cp = H.Cp() # optional - coxeter3 - sage: Cp(CpC[1,2,1]) # optional - coxeter3 - Cp[1,2,1] - sage: CpC(Cp[1,2,1]) # optional - coxeter3 - CpC[1,2,1] - - Some computations in the ``CpC`` basis; these agree with computations in - the existing ``Cp`` basis:: - - sage: s1, s2, s3 = W.simple_reflections() # optional - coxeter3 - sage: Cp(s1)**2 # optional - coxeter3 - (v^-1+v)*Cp[1] - sage: CpC(s1)**2 # optional - coxeter3 - (v^-1+v)*CpC[1] - sage: Cp(s1)*Cp(s2)*Cp(s1) # optional - coxeter3 - Cp[1,2,1] + Cp[1] - sage: CpC(s1)*CpC(s2)*CpC(s1) # optional - coxeter3 - CpC[1,2,1] + CpC[1] - sage: Cp[1]*Cp[2]*Cp[3]*Cp[1]*Cp[2] # optional - coxeter3 - Cp[1,2,1,3,2] + Cp[1,2,1] + Cp[1,3,2] - sage: CpC[1]*CpC[2]*CpC[3]*CpC[1]*CpC[2] # optional - coxeter3 - CpC[1,2,1,3,2] + CpC[1,2,1] + CpC[1,3,2] - - A computation in type `H_4` that is significantly faster in the ``CpC`` - implementation than in the existing ``Cp`` basis:: - - sage: W = CoxeterGroup('H4', implementation='coxeter3') # optional - coxeter3 - sage: H = IwahoriHeckeAlgebra(W, v**2) # optional - coxeter3 - sage: Cp = H.Cp(); CpC = H.Cp_Coxeter3() # optional - coxeter3 - sage: Cp[3,4,3]*Cp[3,4,3,4]*Cp[1,2,3,4] # long time (5 seconds) # optional - coxeter3 - (v^-2+2+v^2)*Cp[4,3,4,3,4,1,2,3,4] - + (v^-2+2+v^2)*Cp[4,3,4,3,4,1,2] - + (v^-1+v)*Cp[3,4,1,2,3,4] - + (v^-3+3*v^-1+3*v+v^3)*Cp[4,3,4,3,4,1] - + (v^-1+v)*Cp[3,4,1,2] - sage: CpC[3,4,3]*CpC[3,4,3,4]*CpC[1,2,3,4] # optional - coxeter3 - (v^-2+2+v^2)*CpC[4,3,4,3,4,1,2,3,4] - + (v^-2+2+v^2)*CpC[4,3,4,3,4,1,2] - + (v^-1+v)*CpC[3,4,1,2,3,4] - + (v^-3+3*v^-1+3*v+v^3)*CpC[4,3,4,3,4,1] - + (v^-1+v)*CpC[3,4,1,2] - - A computation in type `A_9` that seems prohibitively slow for the ``Cp`` - basis:: - - sage: W = CoxeterGroup('A9', implementation='coxeter3') # optional - coxeter3 - sage: H = IwahoriHeckeAlgebra(W, v**2) # optional - coxeter3 - sage: CpC = H.Cp_Coxeter3() # optional - coxeter3 - sage: CpC[1,2,1,8,9,8]*CpC[1,2,3,7,8,9] # optional - coxeter3 - (v^-2+2+v^2)*CpC[1,2,1,3,7,8,7,9,8,7] - + (v^-2+2+v^2)*CpC[1,2,1,3,8,9,8,7] - + (v^-3+3*v^-1+3*v+v^3)*CpC[1,2,1,3,8,9,8] - - - Below is another example, with the Hecke algebra of type `B_9` in the - normalized presentation. The (optional) relabeling command ensures that - `m(1,2)=4`, i.e., that the generators 1, 2 form the strong bond in the - Dynkin diagram. The final two examples are calculations that are quick - in this implementation but seem prohibitively slow for the ``Cp`` - basis:: - - sage: B9 = CoxeterType(['B', 9]) - sage: B9 = B9.relabel({ i: 9-i+1 for i in range(1, 10) }) # optional - coxeter3 - sage: W = CoxeterGroup(B9, implementation='coxeter3') # optional - coxeter3 - sage: H = IwahoriHeckeAlgebra(W, v, -1/v) # optional - coxeter3 - sage: CpC, Cp = H.Cp_Coxeter3(), H.Cp() # optional - coxeter3 - sage: s = W.simple_reflections() # optional - coxeter3 - sage: Cp(s[1]*s[2]*s[1]*s[2]) # optional - coxeter3 - Cp[1,2,1,2] - sage: Cp[3,2,3,4,5] * Cp[2,3] # optional - coxeter3 - (v^-1+v)*Cp[2,3,2,4,3,5] + (v^-1+v)*Cp[2,3,2,5] - sage: CpC[3,2,3,4,5] * CpC[2,3] # optional - coxeter3 - (v^-1+v)*CpC[2,3,2,4,3,5] + (v^-1+v)*CpC[2,3,2,5] - sage: CpC[9,5,6,7,8,9,2,3,4,5,6,7,8,9] * CpC[9,8,7,6] # optional - coxeter3 - (v^-3+3*v^-1+3*v+v^3)*CpC[2,3,4,5,4,6,5,7,6,8,7,9,8,7,6] - sage: CpC[1,5,4,3,2,1,8,7,6,5,4,3,2,1] * CpC[1,2,3,4] # long time (4 seconds) # optional - coxeter3 - (v^-1+v)*CpC[1,5,4,3,2,1,8,7,6,5,4,3,2,1,2,3,4] - + (v^-1+v)*CpC[1,2,1,5,4,3,2,1,2,3,8,7,6,5,4] - + (v^-1+v)*CpC[1,3,2,1,5,4,3,2,1,2,3,4,8,7,6] - + (v^-1+v)*CpC[1,4,3,2,1,5,4,3,2,1,2,3,4,8,7] - + (v^-1+v)*CpC[1,5,4,3,2,1,2,3,8,7,6,5,4,3,2] - + (v^-1+v)*CpC[1,2,5,4,3,2,1,8,7,6,5,4,3] - + (v^-1+v)*CpC[1,2,5,4,3,2,8,7,6,5,4,3,2] - + (v^-1+v)*CpC[1,2,3,2,5,4,3,2,8,7,6] - + (v^-1+v)*CpC[1,2,4,3,2,5,4,3,2,8,7] - + (v^-1+v)*CpC[1,2,5,4,3,2,8,7,6,5,4] - + (v^-1+v)*CpC[1,5,4,3,2,1,8,7,6,5,4] - + (v^-1+v)*CpC[1,5,4,3,8,7,6,5,4,3,2] - + (v^-1+v)*CpC[1,3,5,4,3,2,8,7,6] - + (v^-1+v)*CpC[1,4,3,5,4,3,2,8,7] - - Note that to use the CpC basis for a Hecke algebra, a Coxeter group must - be created first with ``implementation='coxeter3'``. Directly creating a - Hecke algebra from its Coxeter type does not work:: - - sage: H = IwahoriHeckeAlgebra('A3', v**2) # optional - coxeter3 - sage: H.Cp_Coxeter3() # optional - coxeter3 - Traceback (most recent call last): - ... - ValueError: algebra must be initialized with a coxeter3-implemented Coxeter group to use the Cp_Coxeter3 basis - - With the Coxeter group created first, the Hecke algebra must be defined - with the standard or normalized presentation mentioned before:: - - sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 - sage: H = IwahoriHeckeAlgebra(W, QQ(1)) # optional - coxeter3 - sage: H.Cp_Coxeter3() # optional - coxeter3 - Traceback (most recent call last): - ... - ValueError: the Cp_Coxeter3 basis is only supported in a Hecke - algebra with the standard or normalized presentations (i.e., need - {q_1,q_2} = {v^2,1} or {q_1,q_2} = {v,-v^-1} as sets) - - .. TODO:: - - Accommodate generic presentations of the Hecke algebra other than - the standard and normalized ones. - - Use analogs of the formulas for `C^{\prime}_s C^{\prime}_w` and - `C^{\prime}_w C^{\prime}_s` to implement `C^{\prime}`-products - in the multi-parameter Iwahori-Hecke algebra; see Section 6 of - [Lus2013]_. - """ - _basis_name = 'Cp_Coxeter3' - - def __init__(self, algebra, prefix='CpC'): - r""" - Initialize the Cp_Coxeter3 Kazhdan-Lusztig basis of the - Iwahori-Hecke algebra ``algebra''. - - EXAMPLES: - - Valid construction:: - - sage: R. = LaurentPolynomialRing(ZZ, 'v') # optional - coxeter3 - sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 - sage: H = IwahoriHeckeAlgebra(W, v**2) # optional - coxeter3 - sage: CpC = H.Cp_Coxeter3() # optional - coxeter3 - - - Invalid construction (not creating a Coxeter group with - 'coxeter3'):: - - sage: H = IwahoriHeckeAlgebra('A3', v**2) # optional - coxeter3 - sage: H.Cp_Coxeter3() # optional - coxeter3 - Traceback (most recent call last): - ... - ValueError: algebra must be initialized with a coxeter3-implemented Coxeter group to use the Cp_Coxeter3 basis - - - Invalid construction (bad presentation for Hecke algebra):: - - sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 - sage: H = IwahoriHeckeAlgebra(W, QQ(1)) # optional - coxeter3 - sage: H.Cp_Coxeter3() # optional - coxeter3 - Traceback (most recent call last): - ... - ValueError: the Cp_Coxeter3 basis is only supported in a Hecke - algebra with the standard or normalized presentations (i.e., need - {q_1,q_2} = {v^2,1} or {q_1,q_2} = {v,-v^-1} as sets) - """ - if not isinstance(algebra._W, Coxeter3Group): - raise ValueError('algebra must be initialized with a coxeter3-implemented Coxeter group to use the Cp_Coxeter3 basis') - - super(IwahoriHeckeAlgebra.Cp_Coxeter3, self).__init__(algebra, prefix) - - self._W = algebra._W - - v = algebra.base_ring().gen(0) - - parameters = {algebra.q1(), algebra.q2()} - if v != algebra.base_ring().one() and (parameters == {v**2, -1} or parameters == {v, -1/v}): - # The following quantity delta is used in product computations. - # To use v+~v as its value we need the standard or normalized presentations of the Hecke algebra. - self.delta = v + ~v - else: - if not algebra._is_generic: - # If this algebra is generic, it's only being used to coerce to the T basis, not perform computations - raise ValueError('the Cp_Coxeter3 basis is only supported in a Hecke algebra with the standard or normalized \ -presentations (i.e., need {q_1,q_2} = {v^2,1} or {q_1,q_2} = {v,-v^-1} as sets)') - - # Define the (trivial) conversion to the other Cp basis - self.module_morphism(self.to_Cp_basis, codomain=algebra.Cp(), category=self.category() - ).register_as_coercion() - - # ...and from the other Cp basis to the Cp_Coxeter3 basis - Cp = algebra.Cp() - Cp.module_morphism(Cp.to_Cp_Coxeter3_basis, codomain=self, category=self.category()).register_as_coercion() - - def to_Cp_basis(self, w): - r""" - Return the element ``self[w]`` in the ``Cp``-basis. This - transformation is trivial as both bases are implementations of the - `C^{\prime}` basis. - - EXAMPLES:: - - sage: R. = LaurentPolynomialRing(ZZ, 'v') # optional - coxeter3 - sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 - sage: H = IwahoriHeckeAlgebra(W, v**2) # optional - coxeter3 - sage: Cp=H.Cp(); CpC=H.Cp_Coxeter3() # optional - coxeter3 - sage: s1, s2, s3 = W.simple_reflections() # optional - coxeter3 - sage: CpC.to_Cp_basis(s1*s2) # optional - coxeter3 - Cp[1,2] - sage: CpC.to_Cp_basis(s1*s2*s1) # optional - coxeter3 - Cp[1,2,1] - """ - A = self.realization_of() - Cp = A.Cp() - return Cp.monomial(w) - def _product_with_generator_on_basis(self, s, w, side='left'): r""" Compute the product of `C^{\prime}_s` and `C^{\prime}_w`, putting @@ -2264,14 +2004,14 @@ def _product_with_generator_on_basis(self, s, w, side='left'): return self.delta * self.monomial(w) else: element = self(0) - between = self._W.bruhat_interval([], w) + between = self._W_Coxeter3.bruhat_interval([], w) for x in between: # Get (coxeter3-implemented) group element corresponding to x - x_elt = self._W(x) + x_elt = self._W_Coxeter3(x) if x_elt.has_descent(s, side=side): # Compute mu-coefficient via coxeter3 element += x.mu_coefficient(w) * self.monomial(x_elt) - longer_word = self._W([s]) * w if side == 'left' else w * self._W([s]) + longer_word = self._W_Coxeter3([s]) * w if side == 'left' else w * self._W_Coxeter3([s]) return self.monomial(longer_word) + element def _product_with_generator(self, s, x, side='left'): @@ -2351,10 +2091,10 @@ def _decompose_into_generators(self, u): # get the lower order terms ("sum_term") sum_term = self(0) - between = self._W.bruhat_interval([], w) + between = self._W_Coxeter3.bruhat_interval([], w) for v in between: # Get (coxeter3-implemented) group element corresponding to v - v_elt = self._W(v) + v_elt = self._W_Coxeter3(v) if v_elt.has_left_descent(s): # Compute mu-coefficient via coxeter3 sum_term += self.base_ring()(v.mu_coefficient(w)) * self.monomial(v_elt) @@ -2370,6 +2110,7 @@ def _decompose_into_generators(self, u): def product_on_basis(self, w1, w2): r""" + TODO: Mention fallback and conditions to use this algorithm. Return the expansion of `C^{\prime}_{w_1} \cdot C^{\prime}_{w_2}` in the `C^{\prime}`-basis. @@ -2419,6 +2160,12 @@ def product_on_basis(self, w1, w2): sage: CpC.product_on_basis(W([1,2,1]), W([3,1,2])) # optional - coxeter3 (v^-1+v)*CpC[1,2,1,3,2] + (v^-1+v)*CpC[1,2,1] """ + if self.delta is None or self._W_Coxeter3 is None: + return super().product_on_basis(w1, w2) + + w1 = self._W_Coxeter3.from_reduced_word(w1.reduced_word()) + w2 = self._W_Coxeter3.from_reduced_word(w2.reduced_word()) + # Decomposition: write one of C'_{w1} and C'_{w2} as a polynomial in the # generators C'_{s}. if len(w1) <= len(w2): @@ -2440,6 +2187,8 @@ def product_on_basis(self, w1, w2): result += summand return result + C_prime = Cp + class C(_KLHeckeBasis): r""" The Kazhdan-Lusztig `C`-basis of Iwahori-Hecke algebra. From d1663cbcf64be32e07044f8b7a12c76b9e3463ff Mon Sep 17 00:00:00 2001 From: Chase Meadors Date: Fri, 13 Aug 2021 10:50:35 -0600 Subject: [PATCH 084/359] Implement conversion to/from original underlying Coxeter group in product_on_basis --- src/sage/algebras/iwahori_hecke_algebra.py | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/sage/algebras/iwahori_hecke_algebra.py b/src/sage/algebras/iwahori_hecke_algebra.py index a349a709e5a..eb851a76c1e 100644 --- a/src/sage/algebras/iwahori_hecke_algebra.py +++ b/src/sage/algebras/iwahori_hecke_algebra.py @@ -1937,6 +1937,9 @@ def __init__(self, IHAlgebra, prefix=None): """ super().__init__(IHAlgebra, prefix) + self.delta = None + self._W_Coxeter3 = None + v = IHAlgebra.base_ring().gen(0) parameters = {IHAlgebra.q1(), IHAlgebra.q2()} if v != IHAlgebra.base_ring().one() and (parameters == {v**2, -1} or parameters == {v, -1/v}): @@ -2161,10 +2164,15 @@ def product_on_basis(self, w1, w2): (v^-1+v)*CpC[1,2,1,3,2] + (v^-1+v)*CpC[1,2,1] """ if self.delta is None or self._W_Coxeter3 is None: + # We do not meet the conditions to use the direct product + # algorithm; fall back to conversion to/from the T-basis. return super().product_on_basis(w1, w2) - w1 = self._W_Coxeter3.from_reduced_word(w1.reduced_word()) - w2 = self._W_Coxeter3.from_reduced_word(w2.reduced_word()) + # If self._W_Coxeter3 is not the underlying Coxeter group, we need + # to convert elements first for this algorithm. + if (self._W_Coxeter3 != self.realization_of()._W): + w1 = self._W_Coxeter3.from_reduced_word(w1.reduced_word()) + w2 = self._W_Coxeter3.from_reduced_word(w2.reduced_word()) # Decomposition: write one of C'_{w1} and C'_{w2} as a polynomial in the # generators C'_{s}. @@ -2185,6 +2193,15 @@ def product_on_basis(self, w1, w2): for s in p_list: summand = self._product_with_generator(s, summand, side) result += summand + + # Again, if self._W_Coxeter3 is not the underlying Coxeter group, + # we need to convert result. Specifically, make sure basis elements + # appearing therein are actually indexed by elements of the original + # underlying Coxeter group. + if (self._W_Coxeter3 != self.realization_of()._W): + _W = self.realization_of()._W + result = self.linear_combination((self(_W.from_reduced_word(w.reduced_word())), c) for (w, c) in result) + return result C_prime = Cp From 1e47c60c85304fd8d9410cb8b7871e70b95e624f Mon Sep 17 00:00:00 2001 From: Chase Meadors Date: Fri, 13 Aug 2021 11:01:28 -0600 Subject: [PATCH 085/359] Fix doctests for product_on_basis and helper methods --- src/sage/algebras/iwahori_hecke_algebra.py | 44 +++++++++++----------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/sage/algebras/iwahori_hecke_algebra.py b/src/sage/algebras/iwahori_hecke_algebra.py index eb851a76c1e..23b987476be 100644 --- a/src/sage/algebras/iwahori_hecke_algebra.py +++ b/src/sage/algebras/iwahori_hecke_algebra.py @@ -1994,13 +1994,13 @@ def _product_with_generator_on_basis(self, s, w, side='left'): sage: R. = LaurentPolynomialRing(ZZ, 'v') # optional - coxeter3 sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 - sage: H = IwahoriHeckeAlgebra(W, v**2); CpC=H.Cp_Coxeter3() # optional - coxeter3 - sage: CpC._product_with_generator_on_basis(1, W([2,1]), 'left') # optional - coxeter3 - CpC[1,2,1] + CpC[1] - sage: CpC._product_with_generator_on_basis(1, W([2,1]), 'right') # optional - coxeter3 - (v^-1+v)*CpC[2,1] - sage: CpC._product_with_generator_on_basis(2, W([1,3,2,1,3]), 'right') # optional - coxeter3 - CpC[1,2,1,3,2,1] + CpC[1,2,3,2] + CpC[1,3,2,1] + sage: H = IwahoriHeckeAlgebra(W, v**2); Cp=H.Cp() # optional - coxeter3 + sage: Cp._product_with_generator_on_basis(1, W([2,1]), 'left') # optional - coxeter3 + Cp[1,2,1] + Cp[1] + sage: Cp._product_with_generator_on_basis(1, W([2,1]), 'right') # optional - coxeter3 + (v^-1+v)*Cp[2,1] + sage: Cp._product_with_generator_on_basis(2, W([1,3,2,1,3]), 'right') # optional - coxeter3 + Cp[1,2,1,3,2,1] + Cp[1,2,3,2] + Cp[1,3,2,1] """ # use the product formula described in the class' documentation if w.has_descent(s, side=side): @@ -2033,11 +2033,11 @@ def _product_with_generator(self, s, x, side='left'): sage: R. = LaurentPolynomialRing(ZZ, 'v') # optional - coxeter3 sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 - sage: H = IwahoriHeckeAlgebra(W, v**2); CpC=H.Cp_Coxeter3() # optional - coxeter3 - sage: CpC._product_with_generator(1, CpC[1]+CpC[2], 'left') # optional - coxeter3 - CpC[1,2] + (v^-1+v)*CpC[1] - sage: CpC._product_with_generator(1, CpC[1]+CpC[2], 'right') # optional - coxeter3 - CpC[2,1] + (v^-1+v)*CpC[1] + sage: H = IwahoriHeckeAlgebra(W, v**2); Cp=H.Cp() # optional - coxeter3 + sage: Cp._product_with_generator(1, Cp[1]+Cp[2], 'left') # optional - coxeter3 + Cp[1,2] + (v^-1+v)*Cp[1] + sage: Cp._product_with_generator(1, Cp[1]+Cp[2], 'right') # optional - coxeter3 + Cp[2,1] + (v^-1+v)*Cp[1] """ return self.linear_combination((self._product_with_generator_on_basis(s, w, side), coeff) for (w, coeff) in x) @@ -2061,25 +2061,25 @@ def _decompose_into_generators(self, u): sage: R. = LaurentPolynomialRing(ZZ, 'v') # optional - coxeter3 sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 - sage: H = IwahoriHeckeAlgebra(W, v**2); CpC=H.Cp_Coxeter3() # optional - coxeter3 + sage: H = IwahoriHeckeAlgebra(W, v**2); Cp=H.Cp() # optional - coxeter3 When `u` is itself a generator `s`, the decomposition is trivial:: - sage: CpC._decompose_into_generators(W([1])) # optional - coxeter3 + sage: Cp._decompose_into_generators(W([1])) # optional - coxeter3 {(1,): 1} Another example, where `C^{\prime}_u` happens to be a monomial (e.g., CpC_{21} = CpC_2 * CpC_1):: - sage: CpC._decompose_into_generators(W([2,1])) # optional - coxeter3 + sage: Cp._decompose_into_generators(W([2,1])) # optional - coxeter3 {(2, 1): 1} In more general situations the sum is a polynomial (e.g., CpC_{121}=CpC_1*CpC_2*CpC_1-CpC_1):: - sage: CpC._decompose_into_generators(W([1,2,1])) # optional - coxeter3 + sage: Cp._decompose_into_generators(W([1,2,1])) # optional - coxeter3 {(1,): -1, (1, 2, 1): 1} - sage: CpC._decompose_into_generators(W([1,2,3,1,2])) # optional - coxeter3 + sage: Cp._decompose_into_generators(W([1,2,3,1,2])) # optional - coxeter3 {(1,): 1, (1, 2, 1): -1, (1, 2, 1, 3, 2): 1, (1, 3, 2): -1} """ # l(y) = 0 or 1 @@ -2157,11 +2157,11 @@ def product_on_basis(self, w1, w2): sage: R. = LaurentPolynomialRing(ZZ, 'v') # optional - coxeter3 sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 - sage: H = IwahoriHeckeAlgebra(W, v**2); CpC=H.Cp_Coxeter3() # optional - coxeter3 - sage: CpC.product_on_basis(W([1,2,1]), W([3,1])) # optional - coxeter3 - (v^-1+v)*CpC[1,2,1,3] - sage: CpC.product_on_basis(W([1,2,1]), W([3,1,2])) # optional - coxeter3 - (v^-1+v)*CpC[1,2,1,3,2] + (v^-1+v)*CpC[1,2,1] + sage: H = IwahoriHeckeAlgebra(W, v**2); Cp=H.Cp() # optional - coxeter3 + sage: Cp.product_on_basis(W([1,2,1]), W([3,1])) # optional - coxeter3 + (v^-1+v)*Cp[1,2,1,3] + sage: Cp.product_on_basis(W([1,2,1]), W([3,1,2])) # optional - coxeter3 + (v^-1+v)*Cp[1,2,1,3,2] + (v^-1+v)*Cp[1,2,1] """ if self.delta is None or self._W_Coxeter3 is None: # We do not meet the conditions to use the direct product From 58b92a1a9b501efc443d524956411d2d2afa8aa8 Mon Sep 17 00:00:00 2001 From: Chase Meadors Date: Fri, 13 Aug 2021 15:39:33 -0600 Subject: [PATCH 086/359] Documentation --- src/sage/algebras/iwahori_hecke_algebra.py | 53 ++++++++++++++++++++-- 1 file changed, 49 insertions(+), 4 deletions(-) diff --git a/src/sage/algebras/iwahori_hecke_algebra.py b/src/sage/algebras/iwahori_hecke_algebra.py index 23b987476be..80cbbdd843b 100644 --- a/src/sage/algebras/iwahori_hecke_algebra.py +++ b/src/sage/algebras/iwahori_hecke_algebra.py @@ -1882,6 +1882,16 @@ class Cp(_KLHeckeBasis): See [KL1979]_ for more details. + If the optional ``coxeter3`` package is available, and the + Iwahori--Hecke algebra was initialized in the "standard" presentation + (where `\{q_1,q_2\} = \{v^2,1\}` as sets) or the "normalized" + presentation (where `\{q_1,q_2\} = \{v,-v^{-1}\}`), a performant direct + algorithm is available to compute products in the `C^{\prime}` basis, + documented in :func:`product_on_basis`. If these conditions are not met, + the class will fall back to the default implementation which computes + products by converting elements to the `T`-basis and back. This default + implementation may be prohibitively slow for complex calculations. + EXAMPLES:: sage: R = LaurentPolynomialRing(QQ, 'v') @@ -1916,6 +1926,21 @@ class Cp(_KLHeckeBasis): sage: Cp(s1)*Cp(s2)*Cp(s3)*Cp(s1)*Cp(s2) # long time Cp[1,2,3,1,2] + Cp[1,2,1] + Cp[3,1,2] + The most efficient way to use this class is to create the algebra from a + Coxeter group implemented with ``coxeter3``. This will ensure the direct + algorithm can work as efficiently as possible with no unnecessary + conversions:: + + sage: R = LaurentPolynomialRing(QQ, 'v') # optional - coxeter3 + sage: v = R.gen(0) # optional - coxeter3 + sage: W = CoxeterGroup('A9', implementation='coxeter3') # optional - coxeter3 + sage: H = IwahoriHeckeAlgebra(W, v**2) # optional - coxeter3 + sage: Cp = H.Cp() # optional - coxeter3 + sage: Cp[1,2,1,8,9,8]*Cp[1,2,3,7,8,9] # optional - coxeter3 + (v^-2+2+v^2)*Cp[1,2,1,3,7,8,7,9,8,7] + + (v^-2+2+v^2)*Cp[1,2,1,3,8,9,8,7] + + (v^-3+3*v^-1+3*v+v^3)*Cp[1,2,1,3,8,9,8] + TESTS:: sage: R. = LaurentPolynomialRing(QQ, 'v') @@ -1933,13 +1958,30 @@ class Cp(_KLHeckeBasis): def __init__(self, IHAlgebra, prefix=None): r""" - TODO: docstring + TESTS:: + + sage: R = LaurentPolynomialRing(QQ, 'v') # optional - coxeter3 + sage: v = R.gen(0) # optional - coxeter3 + sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 + sage: H = IwahoriHeckeAlgebra(W, v**2) # optional - coxeter3 + sage: Cp = H.Cp() # optional - coxeter3 + sage: Cp.delta == v + ~v # optional - coxeter3 + True + sage: Cp._W_Coxeter3 == H._W # optional - coxeter3 + True + sage: H = IwahoriHeckeAlgebra(W, QQ(1)) # optional - coxeter3 + sage: Cp = H.Cp() # optional - coxeter3 + sage: Cp.delta == None # optional - coxeter3 + True """ super().__init__(IHAlgebra, prefix) self.delta = None self._W_Coxeter3 = None + # See if we meet the conditions to use the direct product_on_basis algorithm. + # If we do, both of these will be non-None + v = IHAlgebra.base_ring().gen(0) parameters = {IHAlgebra.q1(), IHAlgebra.q2()} if v != IHAlgebra.base_ring().one() and (parameters == {v**2, -1} or parameters == {v, -1/v}): @@ -2113,9 +2155,12 @@ def _decompose_into_generators(self, u): def product_on_basis(self, w1, w2): r""" - TODO: Mention fallback and conditions to use this algorithm. - Return the expansion of `C^{\prime}_{w_1} \cdot C^{\prime}_{w_2}` in - the `C^{\prime}`-basis. + If possible, uses a direct algorithm to compute the product + `C^{\prime}_{w_1} \cdot C^{\prime}_{w_2}` (in particular, if + ``coxeter3`` is installed and the Iwahori--Hecke algebra is in the + standard or normalized presentation), detailed below. If not, this + method uses the default implementation of converting to the + `T`-basis, computing the product there, and converting back. ALGORITHM: From 1b0bae1994d9b21436374e7ff06b699e0f8c43f7 Mon Sep 17 00:00:00 2001 From: Chase Meadors Date: Fri, 13 Aug 2021 16:11:11 -0600 Subject: [PATCH 087/359] Move .kazhdan_lusztig_cell --- src/sage/categories/coxeter_groups.py | 109 ++++++++++++++++++++++++ src/sage/libs/coxeter3/coxeter_group.py | 102 ---------------------- 2 files changed, 109 insertions(+), 102 deletions(-) diff --git a/src/sage/categories/coxeter_groups.py b/src/sage/categories/coxeter_groups.py index a2a6a44b5b8..559316ad601 100644 --- a/src/sage/categories/coxeter_groups.py +++ b/src/sage/categories/coxeter_groups.py @@ -22,7 +22,10 @@ from sage.categories.generalized_coxeter_groups import GeneralizedCoxeterGroups from sage.structure.element import have_same_parent, parent from sage.misc.flatten import flatten +from sage.graphs.digraph import DiGraph +from sage.rings.integer_ring import ZZ from copy import copy +from collections import deque class CoxeterGroups(Category_singleton): @@ -2683,3 +2686,109 @@ def upper_covers(self, side='right', index_set=None): """ return self.weak_covers(side=side, index_set=index_set, positive=True) + + def kazhdan_lusztig_cell(self, side='left'): + r""" + Compute the left, right, or two-sided Kazhdan-Lusztig cell + containing the element ``self``. Computes left cells by default; use + the optional argument ``side`` to specify right or two-sided cells. + + Two elements `x,y` of a Coxeter group `W` are said lie in the same + left Kazhdan-Lusztig cell if there exist sequences `x=w_1, w_2, ..., + w_k=y` and `y=u_1, u_2, ..., u_l=x` such that for all `1 \leq i < k` + and all `1 \leq j < l`, there exist some Coxeter generators `s,t` + for which `C'_{w_{i+1}}` appears in `C'_sC'_{w_i}` and + `C'_{u_{j+1}}` appears in `C'_sC'_{u_j}` in the Hecke algebra of the + Coxeter group, where `C'` denotes the Kazhdan-Lusztig + `C^{\prime}`-basis. Right and two-sided Kazhdan-Lusztig cells of `W` + are defined similarly. + + In this function, we compute products in the `C^{\prime}` basis by + using :class:`IwahoriHeckeAlgebra.Cp`. To use the direct algorithm + for computing such products detailed therein, the package + ``coxeter3`` must be installed; otherwise, this method will most + likely be computationally infeasible. + + INPUT: + + - ``w`` -- an element of self. + + - ``side`` -- string (default: ``'left'``); one of 'left', 'right', + or 'two-sided', corresponding to the kind of cell to compute. + + EXAMPLES: + + Compute some cells in type `B_3`:: + + sage: W = CoxeterGroup('B3', implementation='coxeter3') # optional - coxeter3 + sage: s1,s2,s3 = W.simple_reflections() # optional - coxeter3 + sage: (s1*s2*s1).kazhdan_lusztig_cell() # optional - coxeter3 + {[2, 1, 2], [2, 3, 2, 1, 2], [3, 2, 1, 2]} + sage: (s2*s3*s2).kazhdan_lusztig_cell() # optional - coxeter3 + {[1, 2], [1, 2, 3, 2], [2], [2, 3, 2], [3, 2]} + sage: s3.kazhdan_lusztig_cell() # optional - coxeter3 + {[1, 2, 3], [2, 3], [3], [3, 2, 3]} + sage: s3.kazhdan_lusztig_cell('right') # optional - coxeter3 + {[3], [3, 2], [3, 2, 1], [3, 2, 3]} + sage: s3.kazhdan_lusztig_cell('two-sided') # optional - coxeter3 + {[1], [1, 2], [1, 2, 3], [1, 2, 3, 2], [1, 2, 3, 2, 1], [2], [2, 1], + [2, 3], [2, 3, 2], [2, 3, 2, 1], [3], [3, 2], [3, 2, 1], [3, 2, 3]} + + Some slightly longer computations in type `B_4`:: + + sage: W = CoxeterGroup('B4', implementation='coxeter3') # optional - coxeter3 + sage: s1,s2,s3,s4 = W.simple_reflections() # optional - coxeter3 + sage: s1.kazhdan_lusztig_cell() # long time (4 seconds) # optional - coxeter3 + {[1], + [1, 2, 3, 4, 3, 2, 1], + [2, 1], + [2, 3, 4, 3, 2, 1], + [3, 2, 1], + [3, 4, 3, 2, 1], + [4, 3, 2, 1]} + sage: (s4*s2*s3*s4).kazhdan_lusztig_cell() # long time (2 seconds) # optional - coxeter3 + {[2, 3, 4, 1, 2, 3, 4], + [3, 4, 1, 2, 3, 4], + [3, 4, 2, 3, 4], + [3, 4, 2, 3, 4, 1, 2, 3, 4], + [4, 1, 2, 3, 4], + [4, 2, 3, 4], + [4, 2, 3, 4, 1, 2, 3, 4], + [4, 3, 4, 1, 2, 3, 4], + [4, 3, 4, 2, 3, 4], + [4, 3, 4, 2, 3, 4, 1, 2, 3, 4]} + """ + from sage.algebras.iwahori_hecke_algebra import IwahoriHeckeAlgebra + from sage.rings.polynomial.laurent_polynomial_ring import LaurentPolynomialRing + + R = LaurentPolynomialRing(ZZ, 'v') + v = R.gen(0) + H = IwahoriHeckeAlgebra(self.parent(), v**2) + Cp = H.Cp() + + w = self.parent()(self) + + vertices, edges = {w}, set() + queue = deque([w]) + + while queue: + x = queue.pop() + cp_x = Cp(x) + for s in self.parent().simple_reflections(): + cp_s = Cp(s) + terms = [] + # Determine the Cp basis elements appearing in the product of Cp_s and Cp_w + if side == 'left' or side == 'two-sided': + terms.extend(list(cp_s * cp_x)) + if side == 'right' or side == 'two-sided': + terms.extend(list(cp_x * cp_s)) + for (y, coeff) in terms: + # the result of multiplication will always have coeff != 0 + if y != x: + edges.add((x, y)) + if y not in vertices: + vertices.add(y) + queue.appendleft(y) + + g = DiGraph([list(vertices), list(edges)]) + return set(g.strongly_connected_component_containing_vertex(w)) \ No newline at end of file diff --git a/src/sage/libs/coxeter3/coxeter_group.py b/src/sage/libs/coxeter3/coxeter_group.py index 7c3f0cfd509..d0c13f12a11 100644 --- a/src/sage/libs/coxeter3/coxeter_group.py +++ b/src/sage/libs/coxeter3/coxeter_group.py @@ -9,13 +9,9 @@ # http://www.gnu.org/licenses/ #***************************************************************************** -from collections import deque - from sage.libs.coxeter3.coxeter import get_CoxGroup, CoxGroupElement from sage.misc.cachefunc import cached_method -from sage.graphs.digraph import DiGraph - from sage.structure.unique_representation import UniqueRepresentation from sage.structure.element_wrapper import ElementWrapper from sage.structure.richcmp import richcmp @@ -25,7 +21,6 @@ from sage.combinat.root_system.coxeter_matrix import CoxeterMatrix from sage.rings.integer_ring import ZZ -from sage.rings.polynomial.laurent_polynomial_ring import LaurentPolynomialRing from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing @@ -428,103 +423,6 @@ def parabolic_kazhdan_lusztig_polynomial(self, u, v, J, constant_term_one=True): return P.sum((-1)**(z.length()) * self.kazhdan_lusztig_polynomial(u*z,v, constant_term_one=False).shift(z.length()) for z in WOI if (u*z).bruhat_le(v)) - def kazhdan_lusztig_cell(self, w, side='left'): - r""" - Compute the left, right, or two-sided Kazhdan-Lusztig cell containing - the element ``w``. Computes left cells by default; use the optional - argument ``side`` to specify right or two-sided cells. - - Two elements `x,y` of a Coxeter group `W` are said lie in the same left Kazhdan-Lusztig cell if there exist - sequences `x=w_1, w_2, ..., w_k=y` and `y=u_1, u_2, ..., u_l=x` such that for all `1 \leq i < k` and all `1 - \leq j < l`, there exist some Coxeter generators `s,t` for which `C'_{w_{i+1}}` appears in `C'_sC'_{w_i}` - and `C'_{u_{j+1}}` appears in `C'_sC'_{u_j}` in the Hecke algebra of the Coxeter group, where `C'` denotes - the Kazhdan-Lusztig `C^{\prime}`-basis. Right and two-sided Kazhdan-Lusztig cells of `W` are defined - similarly. In this function, we compute products of the form `C_sC_w` using the function - :func:`product_on_basis` of the class :class:`IwahoriHeckeAlgebra.Cp_Coxeter3`. - - INPUT: - - - ``w`` -- an element of self. - - - ``side`` -- string (default: ``'left'``); one of 'left', 'right', or - 'two-sided', corresponding to the kind of cell to compute. - - EXAMPLES: - - Compute some cells in type `B_3`:: - - sage: W = CoxeterGroup('B3', implementation='coxeter3') # optional - coxeter3 - sage: s1,s2,s3 = W.simple_reflections() # optional - coxeter3 - sage: W.kazhdan_lusztig_cell(s1*s2*s1) # optional - coxeter3 - {[2, 1, 2], [2, 3, 2, 1, 2], [3, 2, 1, 2]} - sage: W.kazhdan_lusztig_cell(s2*s3*s2) # optional - coxeter3 - {[1, 2], [1, 2, 3, 2], [2], [2, 3, 2], [3, 2]} - sage: W.kazhdan_lusztig_cell(s3) # optional - coxeter3 - {[1, 2, 3], [2, 3], [3], [3, 2, 3]} - sage: W.kazhdan_lusztig_cell(s3, side='right') # optional - coxeter3 - {[3], [3, 2], [3, 2, 1], [3, 2, 3]} - sage: W.kazhdan_lusztig_cell(s3, side='two-sided') # optional - coxeter3 - {[1], [1, 2], [1, 2, 3], [1, 2, 3, 2], [1, 2, 3, 2, 1], [2], [2, 1], - [2, 3], [2, 3, 2], [2, 3, 2, 1], [3], [3, 2], [3, 2, 1], [3, 2, 3]} - - Some slightly longer computations in type `B_4`:: - - sage: W = CoxeterGroup('B4', implementation='coxeter3') # optional - coxeter3 - sage: s1,s2,s3,s4 = W.simple_reflections() # optional - coxeter3 - sage: W.kazhdan_lusztig_cell(s1) # long time (4 seconds) # optional - coxeter3 - {[1], - [1, 2, 3, 4, 3, 2, 1], - [2, 1], - [2, 3, 4, 3, 2, 1], - [3, 2, 1], - [3, 4, 3, 2, 1], - [4, 3, 2, 1]} - sage: W.kazhdan_lusztig_cell(s4*s2*s3*s4) # long time (2 seconds) # optional - coxeter3 - {[2, 3, 4, 1, 2, 3, 4], - [3, 4, 1, 2, 3, 4], - [3, 4, 2, 3, 4], - [3, 4, 2, 3, 4, 1, 2, 3, 4], - [4, 1, 2, 3, 4], - [4, 2, 3, 4], - [4, 2, 3, 4, 1, 2, 3, 4], - [4, 3, 4, 1, 2, 3, 4], - [4, 3, 4, 2, 3, 4], - [4, 3, 4, 2, 3, 4, 1, 2, 3, 4]} - """ - from sage.algebras.iwahori_hecke_algebra import IwahoriHeckeAlgebra - - R = LaurentPolynomialRing(ZZ, 'v') - v = R.gen(0) - H = IwahoriHeckeAlgebra(self, v**2) - CpC = H.Cp_Coxeter3() - - w = self(w) - - vertices, edges = {w}, set() - queue = deque([w]) - - while queue: - x = queue.pop() - cp_x = CpC(x) - for s in self.simple_reflections(): - cp_s = CpC(s) - terms = [] - # Determine the Cp basis elements appearing in the product of Cp_s and Cp_w - if side == 'left' or side == 'two-sided': - terms.extend(list(cp_s * cp_x)) - if side == 'right' or side == 'two-sided': - terms.extend(list(cp_x * cp_s)) - for (y, coeff) in terms: - # the result of multiplication will always have coeff != 0 - if y != x: - edges.add((x, y)) - if y not in vertices: - vertices.add(y) - queue.appendleft(y) - - g = DiGraph([list(vertices), list(edges)]) - return set(g.strongly_connected_component_containing_vertex(w)) - class Element(ElementWrapper): wrapped_class = CoxGroupElement From 5634be53a37a43bb1521c024d56c306b3ea42061 Mon Sep 17 00:00:00 2001 From: Chase Meadors Date: Fri, 13 Aug 2021 16:58:55 -0600 Subject: [PATCH 088/359] Move product_on_basis to be first. --- src/sage/algebras/iwahori_hecke_algebra.py | 192 ++++++++++----------- 1 file changed, 96 insertions(+), 96 deletions(-) diff --git a/src/sage/algebras/iwahori_hecke_algebra.py b/src/sage/algebras/iwahori_hecke_algebra.py index 80cbbdd843b..74269eb7030 100644 --- a/src/sage/algebras/iwahori_hecke_algebra.py +++ b/src/sage/algebras/iwahori_hecke_algebra.py @@ -2019,6 +2019,102 @@ def hash_involution_on_basis(self, w): """ return (-1)**w.length() * self(self.realization_of().C().monomial(w)) + def product_on_basis(self, w1, w2): + r""" + If possible, uses a direct algorithm to compute the product + `C^{\prime}_{w_1} \cdot C^{\prime}_{w_2}` (in particular, if + ``coxeter3`` is installed and the Iwahori--Hecke algebra is in the + standard or normalized presentation), detailed below. If not, this + method uses the default implementation of converting to the + `T`-basis, computing the product there, and converting back. + + ALGORITHM: + + This class computes each product `C^{\prime}_x \cdot C^{\prime}_y` + in two steps as follows. + + If `\ell(x) \leq \ell(y)`, we first decompose `C^{\prime}_x` into a + polynomial in the generators `C^{\prime}_s (s\in S)` and then + multiply that polynomial with `C^{\prime}_y`. If `\ell(x) > + \ell(y)`, we decompose `C^{\prime}_y` into a polynomial in + `C^{\prime}_s (s\in S)` and multiply that polynomial with + `C^{\prime}_x`. The second step (multiplication) is done by + repeatedly applying the key formulas displayed earlier directly. The + first step (decomposition) is done by induction on the Bruhat order + as follows: for every element `u\in W` with length `\ell(u)>1`, pick + a left descent `s` of `u` and write `u=sw` (so `w=su`), then note + that + + .. MATH:: C^{\prime}_u = C^{\prime}_s \cdot C^{\prime}_{w} - \sum_{v\le u; sv< v} \mu(v,w) C^{\prime}_v + + by the key formulas mentioned earlier, where the element `w` and all + elements `v`'s on the right side are lower than `u` in the Bruhat + order; this allows us to finish the computation by decomposing the + lower order terms `C^{\prime}_w` and each `C^{\prime}_v`. For + example, for `u=121, s=1, w=21` in type `A_3` we have + `C^{\prime}_{121} = C^{\prime}_1 C^{\prime}_{21} - C^{\prime}_1`, + where the lower order term `C^{\prime}_{21}` further decomposes into + `C^{\prime}_2 C^{\prime}_1`, therefore + + .. MATH:: C^{\prime}_{121}=C^{\prime}_1 C^{\prime}_2 C^{\prime}_1 - C^{\prime}_1. + + We note that the base cases `\ell(x)=1` or `\ell(x)=0` of the above + induction occur when `x` is itself a Coxeter generator `s` or the + group identity, respectively. The decomposition is trivial in these + cases (we have `C^{\prime}_x=C^{\prime}_s` or `C^{\prime}_x=1`, the + unit of the Hecke algebra). + + EXAMPLES:: + + sage: R. = LaurentPolynomialRing(ZZ, 'v') # optional - coxeter3 + sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 + sage: H = IwahoriHeckeAlgebra(W, v**2); Cp=H.Cp() # optional - coxeter3 + sage: Cp.product_on_basis(W([1,2,1]), W([3,1])) # optional - coxeter3 + (v^-1+v)*Cp[1,2,1,3] + sage: Cp.product_on_basis(W([1,2,1]), W([3,1,2])) # optional - coxeter3 + (v^-1+v)*Cp[1,2,1,3,2] + (v^-1+v)*Cp[1,2,1] + """ + if self.delta is None or self._W_Coxeter3 is None: + # We do not meet the conditions to use the direct product + # algorithm; fall back to conversion to/from the T-basis. + return super().product_on_basis(w1, w2) + + # If self._W_Coxeter3 is not the underlying Coxeter group, we need + # to convert elements first for this algorithm. + if (self._W_Coxeter3 != self.realization_of()._W): + w1 = self._W_Coxeter3.from_reduced_word(w1.reduced_word()) + w2 = self._W_Coxeter3.from_reduced_word(w2.reduced_word()) + + # Decomposition: write one of C'_{w1} and C'_{w2} as a polynomial in the + # generators C'_{s}. + if len(w1) <= len(w2): + side = 'left' + gen_expression = self._decompose_into_generators(w1) + other_element = self.monomial(w2) + else: + side = 'right' + gen_expression = self._decompose_into_generators(w2) + other_element = self.monomial(w1) + result = self(0) + # Multiplication: multiply the generators in each term of the above + # polynomial onto other_element and add that summand onto result. + for (p, coeff) in gen_expression.items(): + summand = coeff * other_element + p_list = list(p) if side == 'right' else list(p)[::-1] + for s in p_list: + summand = self._product_with_generator(s, summand, side) + result += summand + + # Again, if self._W_Coxeter3 is not the underlying Coxeter group, + # we need to convert result. Specifically, make sure basis elements + # appearing therein are actually indexed by elements of the original + # underlying Coxeter group. + if (self._W_Coxeter3 != self.realization_of()._W): + _W = self.realization_of()._W + result = self.linear_combination((self(_W.from_reduced_word(w.reduced_word())), c) for (w, c) in result) + + return result + def _product_with_generator_on_basis(self, s, w, side='left'): r""" Compute the product of `C^{\prime}_s` and `C^{\prime}_w`, putting @@ -2153,102 +2249,6 @@ def _decompose_into_generators(self, u): return result - def product_on_basis(self, w1, w2): - r""" - If possible, uses a direct algorithm to compute the product - `C^{\prime}_{w_1} \cdot C^{\prime}_{w_2}` (in particular, if - ``coxeter3`` is installed and the Iwahori--Hecke algebra is in the - standard or normalized presentation), detailed below. If not, this - method uses the default implementation of converting to the - `T`-basis, computing the product there, and converting back. - - ALGORITHM: - - This class computes each product `C^{\prime}_x \cdot C^{\prime}_y` - in two steps as follows. - - If `\ell(x) \leq \ell(y)`, we first decompose `C^{\prime}_x` into a - polynomial in the generators `C^{\prime}_s (s\in S)` and then - multiply that polynomial with `C^{\prime}_y`. If `\ell(x) > - \ell(y)`, we decompose `C^{\prime}_y` into a polynomial in - `C^{\prime}_s (s\in S)` and multiply that polynomial with - `C^{\prime}_x`. The second step (multiplication) is done by - repeatedly applying the key formulas displayed earlier directly. The - first step (decomposition) is done by induction on the Bruhat order - as follows: for every element `u\in W` with length `\ell(u)>1`, pick - a left descent `s` of `u` and write `u=sw` (so `w=su`), then note - that - - .. MATH:: C^{\prime}_u = C^{\prime}_s \cdot C^{\prime}_{w} - \sum_{v\le u; sv< v} \mu(v,w) C^{\prime}_v - - by the key formulas mentioned earlier, where the element `w` and all - elements `v`'s on the right side are lower than `u` in the Bruhat - order; this allows us to finish the computation by decomposing the - lower order terms `C^{\prime}_w` and each `C^{\prime}_v`. For - example, for `u=121, s=1, w=21` in type `A_3` we have - `C^{\prime}_{121} = C^{\prime}_1 C^{\prime}_{21} - C^{\prime}_1`, - where the lower order term `C^{\prime}_{21}` further decomposes into - `C^{\prime}_2 C^{\prime}_1`, therefore - - .. MATH:: C^{\prime}_{121}=C^{\prime}_1 C^{\prime}_2 C^{\prime}_1 - C^{\prime}_1. - - We note that the base cases `\ell(x)=1` or `\ell(x)=0` of the above - induction occur when `x` is itself a Coxeter generator `s` or the - group identity, respectively. The decomposition is trivial in these - cases (we have `C^{\prime}_x=C^{\prime}_s` or `C^{\prime}_x=1`, the - unit of the Hecke algebra). - - EXAMPLES:: - - sage: R. = LaurentPolynomialRing(ZZ, 'v') # optional - coxeter3 - sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 - sage: H = IwahoriHeckeAlgebra(W, v**2); Cp=H.Cp() # optional - coxeter3 - sage: Cp.product_on_basis(W([1,2,1]), W([3,1])) # optional - coxeter3 - (v^-1+v)*Cp[1,2,1,3] - sage: Cp.product_on_basis(W([1,2,1]), W([3,1,2])) # optional - coxeter3 - (v^-1+v)*Cp[1,2,1,3,2] + (v^-1+v)*Cp[1,2,1] - """ - if self.delta is None or self._W_Coxeter3 is None: - # We do not meet the conditions to use the direct product - # algorithm; fall back to conversion to/from the T-basis. - return super().product_on_basis(w1, w2) - - # If self._W_Coxeter3 is not the underlying Coxeter group, we need - # to convert elements first for this algorithm. - if (self._W_Coxeter3 != self.realization_of()._W): - w1 = self._W_Coxeter3.from_reduced_word(w1.reduced_word()) - w2 = self._W_Coxeter3.from_reduced_word(w2.reduced_word()) - - # Decomposition: write one of C'_{w1} and C'_{w2} as a polynomial in the - # generators C'_{s}. - if len(w1) <= len(w2): - side = 'left' - gen_expression = self._decompose_into_generators(w1) - other_element = self.monomial(w2) - else: - side = 'right' - gen_expression = self._decompose_into_generators(w2) - other_element = self.monomial(w1) - result = self(0) - # Multiplication: multiply the generators in each term of the above - # polynomial onto other_element and add that summand onto result. - for (p, coeff) in gen_expression.items(): - summand = coeff * other_element - p_list = list(p) if side == 'right' else list(p)[::-1] - for s in p_list: - summand = self._product_with_generator(s, summand, side) - result += summand - - # Again, if self._W_Coxeter3 is not the underlying Coxeter group, - # we need to convert result. Specifically, make sure basis elements - # appearing therein are actually indexed by elements of the original - # underlying Coxeter group. - if (self._W_Coxeter3 != self.realization_of()._W): - _W = self.realization_of()._W - result = self.linear_combination((self(_W.from_reduced_word(w.reduced_word())), c) for (w, c) in result) - - return result - C_prime = Cp class C(_KLHeckeBasis): From cb5dfff6efa80a1122475315e697f60ef4279229 Mon Sep 17 00:00:00 2001 From: Chase Meadors Date: Fri, 13 Aug 2021 17:05:31 -0600 Subject: [PATCH 089/359] Add H4 example --- src/sage/algebras/iwahori_hecke_algebra.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/sage/algebras/iwahori_hecke_algebra.py b/src/sage/algebras/iwahori_hecke_algebra.py index 74269eb7030..585e50dc36d 100644 --- a/src/sage/algebras/iwahori_hecke_algebra.py +++ b/src/sage/algebras/iwahori_hecke_algebra.py @@ -1926,10 +1926,24 @@ class Cp(_KLHeckeBasis): sage: Cp(s1)*Cp(s2)*Cp(s3)*Cp(s1)*Cp(s2) # long time Cp[1,2,3,1,2] + Cp[1,2,1] + Cp[3,1,2] + This computation in type `H_4` takes about 5 seconds without + ``coxeter3`` installed, but is instant in the case that it is installed + and the direct algorithm can be used. + + sage: H = IwahoriHeckeAlgebra('H4', v**2) # optional - coxeter3 + sage: Cp = H.Cp() # optional - coxeter3 + sage: Cp[3,4,3]*Cp[3,4,3,4]*Cp[1,2,3,4] # optional - coxeter3 + (v^-2+2+v^2)*Cp[3,4,3,4,1,2,3,4,2] + + (v^-2+2+v^2)*Cp[3,4,3,4,3,1,2] + + (v^-3+3*v^-1+3*v+v^3)*Cp[3,4,3,4,3,1] + + (v^-1+v)*Cp[3,4,1,2,3,4] + + (v^-1+v)*Cp[3,4,1,2] + The most efficient way to use this class is to create the algebra from a Coxeter group implemented with ``coxeter3``. This will ensure the direct algorithm can work as efficiently as possible with no unnecessary - conversions:: + conversions. This computuation seems to be infeasible without using the + direct algorithm:: sage: R = LaurentPolynomialRing(QQ, 'v') # optional - coxeter3 sage: v = R.gen(0) # optional - coxeter3 From 7e912e8da36e69b9748fecaa5bd0ab4208197fa6 Mon Sep 17 00:00:00 2001 From: Tianyuan Xu Date: Fri, 13 Aug 2021 18:20:05 -0600 Subject: [PATCH 090/359] doc changes in Cp class --- src/sage/algebras/iwahori_hecke_algebra.py | 141 ++++++++++++++------- 1 file changed, 94 insertions(+), 47 deletions(-) diff --git a/src/sage/algebras/iwahori_hecke_algebra.py b/src/sage/algebras/iwahori_hecke_algebra.py index 585e50dc36d..dcbad08667f 100644 --- a/src/sage/algebras/iwahori_hecke_algebra.py +++ b/src/sage/algebras/iwahori_hecke_algebra.py @@ -1882,15 +1882,17 @@ class Cp(_KLHeckeBasis): See [KL1979]_ for more details. - If the optional ``coxeter3`` package is available, and the + If the optional ``coxeter3`` package is available and the Iwahori--Hecke algebra was initialized in the "standard" presentation - (where `\{q_1,q_2\} = \{v^2,1\}` as sets) or the "normalized" - presentation (where `\{q_1,q_2\} = \{v,-v^{-1}\}`), a performant direct - algorithm is available to compute products in the `C^{\prime}` basis, - documented in :func:`product_on_basis`. If these conditions are not met, - the class will fall back to the default implementation which computes - products by converting elements to the `T`-basis and back. This default - implementation may be prohibitively slow for complex calculations. + where `\{q_1,q_2\} = \{v^2,1\}` as sets or the "normalized" + presentation where `\{q_1,q_2\} = \{v,-v^{-1}\}` as sets, the function + :func::`product_on_basis` in this class computes products in the + `C^{\prime}`-basis directly in the basis itself, using ``coxeter3`` to + calculate certain `\mu`-coefficients quickly. If the above conditions + are not all met, the function computes such products indirectly, by + converting elements to the `T`-basis, computing products there, and + converting back. The indirect method can be prohibitively slow for more + complex calculations; the direct method is faster. EXAMPLES:: @@ -1923,12 +1925,14 @@ class Cp(_KLHeckeBasis): (v^-1+v)*Cp[1] sage: Cp(s1)*Cp(s2)*Cp(s1) Cp[1,2,1] + Cp[1] - sage: Cp(s1)*Cp(s2)*Cp(s3)*Cp(s1)*Cp(s2) # long time + sage: Cp(s1)*Cp(s2)*Cp(s3)*Cp(s1)*Cp(s2) # long time Cp[1,2,3,1,2] + Cp[1,2,1] + Cp[3,1,2] - This computation in type `H_4` takes about 5 seconds without - ``coxeter3`` installed, but is instant in the case that it is installed - and the direct algorithm can be used. + In the following product computations, whether ``coxeter3`` is + installed makes a big difference: without ``coxeter3`` the product in + type `H_4` takes about 5 seconds to compute and the product in type + `A_9` seems infeasible, while with ``coxeter3`` both the computations + are instant:: sage: H = IwahoriHeckeAlgebra('H4', v**2) # optional - coxeter3 sage: Cp = H.Cp() # optional - coxeter3 @@ -1939,11 +1943,17 @@ class Cp(_KLHeckeBasis): + (v^-1+v)*Cp[3,4,1,2,3,4] + (v^-1+v)*Cp[3,4,1,2] - The most efficient way to use this class is to create the algebra from a - Coxeter group implemented with ``coxeter3``. This will ensure the direct - algorithm can work as efficiently as possible with no unnecessary - conversions. This computuation seems to be infeasible without using the - direct algorithm:: + sage: H = IwahoriHeckeAlgebra('A9', v**2) # optional - coxeter3 + sage: Cp = H.Cp() # optional - coxeter3 + sage: Cp[1,2,1,8,9,8]*Cp[1,2,3,7,8,9] # optional - coxeter3 + (v^-2+2+v^2)*Cp[1,2,1,3,7,8,7,9,8,7] + + (v^-2+2+v^2)*Cp[1,2,1,3,8,9,8,7] + + (v^-3+3*v^-1+3*v+v^3)*Cp[1,2,1,3,8,9,8] + + To use ``coxeter3`` for product computations most efficiently, we + recommend creating the Iwahori-Hecke algebra from a Coxeter group + implemented with ``coxeter3`` to avoid unnecessary conversions, as in + the following example with the same product computed in the last one:: sage: R = LaurentPolynomialRing(QQ, 'v') # optional - coxeter3 sage: v = R.gen(0) # optional - coxeter3 @@ -1994,7 +2004,7 @@ def __init__(self, IHAlgebra, prefix=None): self._W_Coxeter3 = None # See if we meet the conditions to use the direct product_on_basis algorithm. - # If we do, both of these will be non-None + # If we do, both of these will be non-None. v = IHAlgebra.base_ring().gen(0) parameters = {IHAlgebra.q1(), IHAlgebra.q2()} @@ -2002,7 +2012,8 @@ def __init__(self, IHAlgebra, prefix=None): # The following quantity delta is used in product computations. # To use v+~v as its value we need the standard or normalized presentations of the Hecke algebra. self.delta = v + ~v - + + # check if products can be computed directly using ``coxeter3``: try: from sage.libs.coxeter3.coxeter_group import CoxeterGroup as Coxeter3Group if isinstance(IHAlgebra._W, Coxeter3Group): @@ -2035,17 +2046,48 @@ def hash_involution_on_basis(self, w): def product_on_basis(self, w1, w2): r""" - If possible, uses a direct algorithm to compute the product - `C^{\prime}_{w_1} \cdot C^{\prime}_{w_2}` (in particular, if - ``coxeter3`` is installed and the Iwahori--Hecke algebra is in the - standard or normalized presentation), detailed below. If not, this - method uses the default implementation of converting to the - `T`-basis, computing the product there, and converting back. + Return the expansion of `C^{\prime}_{w_1} \cdot C^{\prime}_{w_2}` in + the `C^{\prime}`-basis. + + If ``coxeter3`` is installed and the Iwahori--Hecke algebra is in + the standard or normalized presentation, the product is computed + directly using the method described in ALGORITHM. If not, the + product is computed indirectly by converting the factors to the + `T`-basis, computing the product there, and converting back. + + The following formulas for products of the forms `C^{\prime}_s + \cdot C^{\prime}_w` and `C^{\prime}_w \cdot C^{\prime}_s`, where + `s` is a generator of the Coxeter group and `w` an arbitrary + element, are key to the direct computation method. The formulas are + valid for both the standard and normalized presentation of the + Hecke algebra. + + .. MATH:: + C^{\prime}_s \cdot C^{\prime}_w = \begin{cases} + (q+q^-1)C^{\prime}_{w}, & \text{if } \ell(sw) = \ell(w)-1,\\ + C^{\prime}_{sw}+\sum_{v\leq w, sv \leq v} \mu(v,w)C^{\prime}_v, + & \text{if } \ell(sw) = \ell(w)+1. + \end{cases} + + C^{\prime}_w \cdot C^{\prime}_s = \begin{cases} + (q+q^-1)C^{\prime}_{w}, & \text{if } \ell(ws) = \ell(w)-1,\\ + C^{\prime}_{ws}+\sum_{v\leq w, vs \leq v} \mu(v,w)C^{\prime}_v, + & \text{if } \ell(ws) = \ell(w)+1. + \end{cases} + + In the above, `\leq` is the Bruhat order on the Coxeter group and + `\mu(v,w)` is the "leading coefficient of Kazhdan-Lusztig + polynomials"; see [KL1979]_ and [Lus2013]_ for more details. The + method designates the computation of the `\mu`-coefficients to + Sage's interface to Fokko du Cloux's ``coxeter3`` package, which is + why the method requires the creation of the Coxeter group using the + 'coxeter3' implementation. + ALGORITHM: - This class computes each product `C^{\prime}_x \cdot C^{\prime}_y` - in two steps as follows. + The direct algorithm for computing `C^{\prime}_x \cdot + C^{\prime}_y` runs in two steps as follows. If `\ell(x) \leq \ell(y)`, we first decompose `C^{\prime}_x` into a polynomial in the generators `C^{\prime}_s (s\in S)` and then @@ -2053,24 +2095,28 @@ def product_on_basis(self, w1, w2): \ell(y)`, we decompose `C^{\prime}_y` into a polynomial in `C^{\prime}_s (s\in S)` and multiply that polynomial with `C^{\prime}_x`. The second step (multiplication) is done by - repeatedly applying the key formulas displayed earlier directly. The + repeatedly applying the formulas displayed earlier directly. The first step (decomposition) is done by induction on the Bruhat order - as follows: for every element `u\in W` with length `\ell(u)>1`, pick - a left descent `s` of `u` and write `u=sw` (so `w=su`), then note - that - - .. MATH:: C^{\prime}_u = C^{\prime}_s \cdot C^{\prime}_{w} - \sum_{v\le u; sv< v} \mu(v,w) C^{\prime}_v - - by the key formulas mentioned earlier, where the element `w` and all - elements `v`'s on the right side are lower than `u` in the Bruhat - order; this allows us to finish the computation by decomposing the - lower order terms `C^{\prime}_w` and each `C^{\prime}_v`. For - example, for `u=121, s=1, w=21` in type `A_3` we have - `C^{\prime}_{121} = C^{\prime}_1 C^{\prime}_{21} - C^{\prime}_1`, - where the lower order term `C^{\prime}_{21}` further decomposes into - `C^{\prime}_2 C^{\prime}_1`, therefore - - .. MATH:: C^{\prime}_{121}=C^{\prime}_1 C^{\prime}_2 C^{\prime}_1 - C^{\prime}_1. + as follows: for every element `u\in W` with length `\ell(u)>1`, + pick a left descent `s` of `u` and write `u=sw` (so `w=su`), then + note that + + .. MATH:: + C^{\prime}_u = C^{\prime}_s \cdot C^{\prime}_{w} + - \sum_{v\le u; sv< v} \mu(v,w) C^{\prime}_v + + by the earlier formulas, where the element `w` and all elements + `v`'s on the right side are lower than `u` in the Bruhat order; + this allows us to finish the computation by decomposing the lower + order terms `C^{\prime}_w` and each `C^{\prime}_v`. For example, + for `u=121, s=1, w=21` in type `A_3` we have `C^{\prime}_{121} = + C^{\prime}_1 C^{\prime}_{21} - C^{\prime}_1`, where the lower + order term `C^{\prime}_{21}` further decomposes into `C^{\prime}_2 + C^{\prime}_1`, therefore + + .. MATH:: + C^{\prime}_{121} = C^{\prime}_1 C^{\prime}_2 C^{\prime}_1 + - C^{\prime}_1. We note that the base cases `\ell(x)=1` or `\ell(x)=0` of the above induction occur when `x` is itself a Coxeter generator `s` or the @@ -2120,9 +2166,10 @@ def product_on_basis(self, w1, w2): result += summand # Again, if self._W_Coxeter3 is not the underlying Coxeter group, - # we need to convert result. Specifically, make sure basis elements - # appearing therein are actually indexed by elements of the original - # underlying Coxeter group. + # we need to convert the result. Specifically, make sure basis + # elements appearing therein are actually indexed by elements of + # the original underlying Coxeter group. + if (self._W_Coxeter3 != self.realization_of()._W): _W = self.realization_of()._W result = self.linear_combination((self(_W.from_reduced_word(w.reduced_word())), c) for (w, c) in result) From ee2edc72bbfd2bec46ed002b802626228bec40c6 Mon Sep 17 00:00:00 2001 From: Chase Meadors Date: Sat, 14 Aug 2021 09:44:30 -0600 Subject: [PATCH 091/359] Tweak/fix some docstrings --- src/sage/algebras/iwahori_hecke_algebra.py | 71 +++++++++++----------- 1 file changed, 36 insertions(+), 35 deletions(-) diff --git a/src/sage/algebras/iwahori_hecke_algebra.py b/src/sage/algebras/iwahori_hecke_algebra.py index dcbad08667f..fa38e115f11 100644 --- a/src/sage/algebras/iwahori_hecke_algebra.py +++ b/src/sage/algebras/iwahori_hecke_algebra.py @@ -1953,7 +1953,7 @@ class Cp(_KLHeckeBasis): To use ``coxeter3`` for product computations most efficiently, we recommend creating the Iwahori-Hecke algebra from a Coxeter group implemented with ``coxeter3`` to avoid unnecessary conversions, as in - the following example with the same product computed in the last one:: + the following example with the same product computed in the last one:: sage: R = LaurentPolynomialRing(QQ, 'v') # optional - coxeter3 sage: v = R.gen(0) # optional - coxeter3 @@ -2012,7 +2012,7 @@ def __init__(self, IHAlgebra, prefix=None): # The following quantity delta is used in product computations. # To use v+~v as its value we need the standard or normalized presentations of the Hecke algebra. self.delta = v + ~v - + # check if products can be computed directly using ``coxeter3``: try: from sage.libs.coxeter3.coxeter_group import CoxeterGroup as Coxeter3Group @@ -2053,27 +2053,28 @@ def product_on_basis(self, w1, w2): the standard or normalized presentation, the product is computed directly using the method described in ALGORITHM. If not, the product is computed indirectly by converting the factors to the - `T`-basis, computing the product there, and converting back. - + `T`-basis, computing the product there, and converting back. + The following formulas for products of the forms `C^{\prime}_s \cdot C^{\prime}_w` and `C^{\prime}_w \cdot C^{\prime}_s`, where `s` is a generator of the Coxeter group and `w` an arbitrary element, are key to the direct computation method. The formulas are valid for both the standard and normalized presentation of the - Hecke algebra. + Hecke algebra. + + .. MATH:: - .. MATH:: - C^{\prime}_s \cdot C^{\prime}_w = \begin{cases} - (q+q^-1)C^{\prime}_{w}, & \text{if } \ell(sw) = \ell(w)-1,\\ - C^{\prime}_{sw}+\sum_{v\leq w, sv \leq v} \mu(v,w)C^{\prime}_v, - & \text{if } \ell(sw) = \ell(w)+1. - \end{cases} + C^{\prime}_s \cdot C^{\prime}_w = \begin{cases} + (q+q^{-1})C^{\prime}_{w}, & \text{if } \ell(sw) = \ell(w)-1,\\ + C^{\prime}_{sw}+\sum_{v\leq w, sv \leq v} \mu(v,w)C^{\prime}_v, + & \text{if } \ell(sw) = \ell(w)+1. + \end{cases} - C^{\prime}_w \cdot C^{\prime}_s = \begin{cases} - (q+q^-1)C^{\prime}_{w}, & \text{if } \ell(ws) = \ell(w)-1,\\ - C^{\prime}_{ws}+\sum_{v\leq w, vs \leq v} \mu(v,w)C^{\prime}_v, - & \text{if } \ell(ws) = \ell(w)+1. - \end{cases} + C^{\prime}_w \cdot C^{\prime}_s = \begin{cases} + (q+q^{-1})C^{\prime}_{w}, & \text{if } \ell(ws) = \ell(w)-1,\\ + C^{\prime}_{ws}+\sum_{v\leq w, vs \leq v} \mu(v,w)C^{\prime}_v, + & \text{if } \ell(ws) = \ell(w)+1. + \end{cases} In the above, `\leq` is the Bruhat order on the Coxeter group and `\mu(v,w)` is the "leading coefficient of Kazhdan-Lusztig @@ -2083,7 +2084,6 @@ def product_on_basis(self, w1, w2): why the method requires the creation of the Coxeter group using the 'coxeter3' implementation. - ALGORITHM: The direct algorithm for computing `C^{\prime}_x \cdot @@ -2101,9 +2101,9 @@ def product_on_basis(self, w1, w2): pick a left descent `s` of `u` and write `u=sw` (so `w=su`), then note that - .. MATH:: - C^{\prime}_u = C^{\prime}_s \cdot C^{\prime}_{w} - - \sum_{v\le u; sv< v} \mu(v,w) C^{\prime}_v + .. MATH:: + + C^{\prime}_u = C^{\prime}_s \cdot C^{\prime}_{w} - \sum_{v\le u; sv< v} \mu(v,w) C^{\prime}_v by the earlier formulas, where the element `w` and all elements `v`'s on the right side are lower than `u` in the Bruhat order; @@ -2114,9 +2114,9 @@ def product_on_basis(self, w1, w2): order term `C^{\prime}_{21}` further decomposes into `C^{\prime}_2 C^{\prime}_1`, therefore - .. MATH:: - C^{\prime}_{121} = C^{\prime}_1 C^{\prime}_2 C^{\prime}_1 - - C^{\prime}_1. + .. MATH:: + + C^{\prime}_{121} = C^{\prime}_1 C^{\prime}_2 C^{\prime}_1 - C^{\prime}_1. We note that the base cases `\ell(x)=1` or `\ell(x)=0` of the above induction occur when `x` is itself a Coxeter generator `s` or the @@ -2135,7 +2135,7 @@ def product_on_basis(self, w1, w2): (v^-1+v)*Cp[1,2,1,3,2] + (v^-1+v)*Cp[1,2,1] """ if self.delta is None or self._W_Coxeter3 is None: - # We do not meet the conditions to use the direct product + # We do not meet the conditions to use the direct product # algorithm; fall back to conversion to/from the T-basis. return super().product_on_basis(w1, w2) @@ -2164,10 +2164,10 @@ def product_on_basis(self, w1, w2): for s in p_list: summand = self._product_with_generator(s, summand, side) result += summand - + # Again, if self._W_Coxeter3 is not the underlying Coxeter group, - # we need to convert the result. Specifically, make sure basis - # elements appearing therein are actually indexed by elements of + # we need to convert the result. Specifically, make sure basis + # elements appearing therein are actually indexed by elements of # the original underlying Coxeter group. if (self._W_Coxeter3 != self.realization_of()._W): @@ -2187,7 +2187,7 @@ def _product_with_generator_on_basis(self, s, w, side='left'): - ``w`` -- a word in self.coxeter_group() - - ``side`` -- string; 'left' or 'right' + - ``side`` -- string; ``'left'`` or ``'right'`` EXAMPLES:: @@ -2218,7 +2218,8 @@ def _product_with_generator_on_basis(self, s, w, side='left'): def _product_with_generator(self, s, x, side='left'): r""" - Compute the product of `C^{\prime}_s` with any linear combination of `C^{\prime}`-basis elements. + Compute the product of `C^{\prime}_s` with any linear combination of + `C^{\prime}`-basis elements. INPUT: @@ -2226,7 +2227,7 @@ def _product_with_generator(self, s, x, side='left'): - ``x`` -- any element of self - - ``side`` -- string; 'left' or 'right' + - ``side`` -- string; ``'left'`` or ``'right'`` EXAMPLES:: @@ -2249,9 +2250,9 @@ def _decompose_into_generators(self, u): OUTPUT: A dictionary keyed by tuples with integer values. Each entry - represents a term, where the tuple represents a monomial term in - the KL generators and the value represents the coefficient of that - term. For example, an item `(1,2): 3` stands for `3 * + represents a term, where the tuple represents a monomial term in the + KL generators and the value represents the coefficient of that term. + For example, an item `(1,2): 3` stands for `3 \cdot C^{\prime}_1C^{\prime}_2`. EXAMPLES: @@ -2268,13 +2269,13 @@ def _decompose_into_generators(self, u): {(1,): 1} Another example, where `C^{\prime}_u` happens to be a monomial - (e.g., CpC_{21} = CpC_2 * CpC_1):: + (e.g., `C'_{21} = C'_2 C'_1`):: sage: Cp._decompose_into_generators(W([2,1])) # optional - coxeter3 {(2, 1): 1} In more general situations the sum is a polynomial (e.g., - CpC_{121}=CpC_1*CpC_2*CpC_1-CpC_1):: + `C'_{121}=C'_1 C'_2 C'_1 - C'_1)`:: sage: Cp._decompose_into_generators(W([1,2,1])) # optional - coxeter3 {(1,): -1, (1, 2, 1): 1} From eea7340fdfef566a1984bf8883f1553d4b8de6a3 Mon Sep 17 00:00:00 2001 From: Chase Meadors Date: Sat, 14 Aug 2021 09:54:13 -0600 Subject: [PATCH 092/359] Make auxiliary product_on_basis helpers public --- src/sage/algebras/iwahori_hecke_algebra.py | 36 +++++++++++----------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/sage/algebras/iwahori_hecke_algebra.py b/src/sage/algebras/iwahori_hecke_algebra.py index fa38e115f11..b268b468d0e 100644 --- a/src/sage/algebras/iwahori_hecke_algebra.py +++ b/src/sage/algebras/iwahori_hecke_algebra.py @@ -2149,11 +2149,11 @@ def product_on_basis(self, w1, w2): # generators C'_{s}. if len(w1) <= len(w2): side = 'left' - gen_expression = self._decompose_into_generators(w1) + gen_expression = self.decompose_into_generators(w1) other_element = self.monomial(w2) else: side = 'right' - gen_expression = self._decompose_into_generators(w2) + gen_expression = self.decompose_into_generators(w2) other_element = self.monomial(w1) result = self(0) # Multiplication: multiply the generators in each term of the above @@ -2162,7 +2162,7 @@ def product_on_basis(self, w1, w2): summand = coeff * other_element p_list = list(p) if side == 'right' else list(p)[::-1] for s in p_list: - summand = self._product_with_generator(s, summand, side) + summand = self.product_with_generator(s, summand, side) result += summand # Again, if self._W_Coxeter3 is not the underlying Coxeter group, @@ -2176,7 +2176,7 @@ def product_on_basis(self, w1, w2): return result - def _product_with_generator_on_basis(self, s, w, side='left'): + def product_with_generator_on_basis(self, s, w, side='left'): r""" Compute the product of `C^{\prime}_s` and `C^{\prime}_w`, putting `C^{\prime}_s` on the given ``side``. @@ -2194,11 +2194,11 @@ def _product_with_generator_on_basis(self, s, w, side='left'): sage: R. = LaurentPolynomialRing(ZZ, 'v') # optional - coxeter3 sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 sage: H = IwahoriHeckeAlgebra(W, v**2); Cp=H.Cp() # optional - coxeter3 - sage: Cp._product_with_generator_on_basis(1, W([2,1]), 'left') # optional - coxeter3 + sage: Cp.product_with_generator_on_basis(1, W([2,1]), 'left') # optional - coxeter3 Cp[1,2,1] + Cp[1] - sage: Cp._product_with_generator_on_basis(1, W([2,1]), 'right') # optional - coxeter3 + sage: Cp.product_with_generator_on_basis(1, W([2,1]), 'right') # optional - coxeter3 (v^-1+v)*Cp[2,1] - sage: Cp._product_with_generator_on_basis(2, W([1,3,2,1,3]), 'right') # optional - coxeter3 + sage: Cp.product_with_generator_on_basis(2, W([1,3,2,1,3]), 'right') # optional - coxeter3 Cp[1,2,1,3,2,1] + Cp[1,2,3,2] + Cp[1,3,2,1] """ # use the product formula described in the class' documentation @@ -2216,7 +2216,7 @@ def _product_with_generator_on_basis(self, s, w, side='left'): longer_word = self._W_Coxeter3([s]) * w if side == 'left' else w * self._W_Coxeter3([s]) return self.monomial(longer_word) + element - def _product_with_generator(self, s, x, side='left'): + def product_with_generator(self, s, x, side='left'): r""" Compute the product of `C^{\prime}_s` with any linear combination of `C^{\prime}`-basis elements. @@ -2234,14 +2234,14 @@ def _product_with_generator(self, s, x, side='left'): sage: R. = LaurentPolynomialRing(ZZ, 'v') # optional - coxeter3 sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 sage: H = IwahoriHeckeAlgebra(W, v**2); Cp=H.Cp() # optional - coxeter3 - sage: Cp._product_with_generator(1, Cp[1]+Cp[2], 'left') # optional - coxeter3 + sage: Cp.product_with_generator(1, Cp[1]+Cp[2], 'left') # optional - coxeter3 Cp[1,2] + (v^-1+v)*Cp[1] - sage: Cp._product_with_generator(1, Cp[1]+Cp[2], 'right') # optional - coxeter3 + sage: Cp.product_with_generator(1, Cp[1]+Cp[2], 'right') # optional - coxeter3 Cp[2,1] + (v^-1+v)*Cp[1] """ - return self.linear_combination((self._product_with_generator_on_basis(s, w, side), coeff) for (w, coeff) in x) + return self.linear_combination((self.product_with_generator_on_basis(s, w, side), coeff) for (w, coeff) in x) - def _decompose_into_generators(self, u): + def decompose_into_generators(self, u): r""" Decompose `C^{\prime}_u` into a polynomial in the KL generators `C^{\prime}_s`; see the ALGORITHM section of @@ -2265,21 +2265,21 @@ def _decompose_into_generators(self, u): When `u` is itself a generator `s`, the decomposition is trivial:: - sage: Cp._decompose_into_generators(W([1])) # optional - coxeter3 + sage: Cp.decompose_into_generators(W([1])) # optional - coxeter3 {(1,): 1} Another example, where `C^{\prime}_u` happens to be a monomial (e.g., `C'_{21} = C'_2 C'_1`):: - sage: Cp._decompose_into_generators(W([2,1])) # optional - coxeter3 + sage: Cp.decompose_into_generators(W([2,1])) # optional - coxeter3 {(2, 1): 1} In more general situations the sum is a polynomial (e.g., `C'_{121}=C'_1 C'_2 C'_1 - C'_1)`:: - sage: Cp._decompose_into_generators(W([1,2,1])) # optional - coxeter3 + sage: Cp.decompose_into_generators(W([1,2,1])) # optional - coxeter3 {(1,): -1, (1, 2, 1): 1} - sage: Cp._decompose_into_generators(W([1,2,3,1,2])) # optional - coxeter3 + sage: Cp.decompose_into_generators(W([1,2,3,1,2])) # optional - coxeter3 {(1,): 1, (1, 2, 1): -1, (1, 2, 1, 3, 2): 1, (1, 3, 2): -1} """ # l(y) = 0 or 1 @@ -2303,10 +2303,10 @@ def _decompose_into_generators(self, u): sum_term += self.base_ring()(v.mu_coefficient(w)) * self.monomial(v_elt) # recursion: decompose C'_s * C'_w and the lower order terms - result = {(s,) + gens: coeff for (gens, coeff) in self._decompose_into_generators(w).items()} + result = {(s,) + gens: coeff for (gens, coeff) in self.decompose_into_generators(w).items()} for (z, c1) in sum_term: # Subtract off each term from sum_term. - for (gens, c2) in self._decompose_into_generators(z).items(): + for (gens, c2) in self.decompose_into_generators(z).items(): result[gens] = result.get(gens, 0) - c1*c2 return result From 6dbd2e932db732806a2a599965d9591712dea16f Mon Sep 17 00:00:00 2001 From: Chase Meadors Date: Sat, 14 Aug 2021 10:37:50 -0600 Subject: [PATCH 093/359] Fix doctest When not using implementation=coxeter3, the reduced word convention is different. --- src/sage/algebras/iwahori_hecke_algebra.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sage/algebras/iwahori_hecke_algebra.py b/src/sage/algebras/iwahori_hecke_algebra.py index b268b468d0e..c6628f341f4 100644 --- a/src/sage/algebras/iwahori_hecke_algebra.py +++ b/src/sage/algebras/iwahori_hecke_algebra.py @@ -1946,9 +1946,9 @@ class Cp(_KLHeckeBasis): sage: H = IwahoriHeckeAlgebra('A9', v**2) # optional - coxeter3 sage: Cp = H.Cp() # optional - coxeter3 sage: Cp[1,2,1,8,9,8]*Cp[1,2,3,7,8,9] # optional - coxeter3 - (v^-2+2+v^2)*Cp[1,2,1,3,7,8,7,9,8,7] - + (v^-2+2+v^2)*Cp[1,2,1,3,8,9,8,7] - + (v^-3+3*v^-1+3*v+v^3)*Cp[1,2,1,3,8,9,8] + (v^-2+2+v^2)*Cp[7,8,9,7,8,7,1,2,3,1] + + (v^-2+2+v^2)*Cp[8,9,8,7,1,2,3,1] + + (v^-3+3*v^-1+3*v+v^3)*Cp[8,9,8,1,2,3,1] To use ``coxeter3`` for product computations most efficiently, we recommend creating the Iwahori-Hecke algebra from a Coxeter group From a785b1c45aaa0b1e0c5064506ebebe38095b65bc Mon Sep 17 00:00:00 2001 From: Chase Meadors Date: Sat, 14 Aug 2021 11:14:40 -0600 Subject: [PATCH 094/359] Add function to compute all KL cells to Coxeter groups --- src/sage/categories/coxeter_groups.py | 52 +++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/src/sage/categories/coxeter_groups.py b/src/sage/categories/coxeter_groups.py index 559316ad601..b4bc3c0f50d 100644 --- a/src/sage/categories/coxeter_groups.py +++ b/src/sage/categories/coxeter_groups.py @@ -689,6 +689,58 @@ def simple_projection(self, i, side='right', length_increasing=True): return lambda x: x.apply_simple_projection(i, side=side, length_increasing=length_increasing) + def kazhdan_lusztig_cells(self, side='left'): + r""" + Compute the left, right, or two-sided Kazhdan-Lusztig cells of + ``self`` by using :func:`ElementMethods.kazhdan_lusztig_cell()`. As + detailed there, this function will be much more efficient if the + package ``coxeter3`` is installed, due to the method of computing + products in the `C^{\prime}` basis of the Iwahori--Hecke algebra. + + EXAMPLES:: + + sage: from sage.doctest.fixtures import reproducible_repr # optional - coxeter3 + sage: W = CoxeterGroup('A3') # optional - coxeter3 + sage: [len(c) for c in W.kazhdan_lusztig_cells()] # optional - coxeter3 + [3, 3, 2, 1, 3, 3, 3, 1, 3, 2] + sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 + sage: print(reproducible_repr(W.kazhdan_lusztig_cells())) # optional - coxeter3 + set([frozenset([[1, 2, 1, 3, 2, 1]]), + frozenset([[1, 2, 1, 3, 2], [1, 2, 3, 2], [2, 3, 2]]), + frozenset([[1, 2, 1, 3], [1, 2, 3, 2, 1], [2, 3, 2, 1]]), + frozenset([[1, 2, 1], [1, 3, 2, 1], [2, 1, 3, 2, 1]]), + frozenset([[1, 2, 3], [2, 3], [3]]), + frozenset([[1, 2], [2], [3, 2]]), + frozenset([[1, 3, 2], [2, 1, 3, 2]]), + frozenset([[1, 3], [2, 1, 3]]), + frozenset([[1], [2, 1], [3, 2, 1]]), + frozenset([[]])]) + sage: W = CoxeterGroup('A4', implementation='coxeter3') # optional - coxeter3 + sage: [len(c) for c in W.kazhdan_lusztig_cells()] # long time (3 seconds) # optional - coxeter3 + [5, 4, 4, 5, 5, 6, 4, 6, 4, 5, 5, 4, 1, 5, 6, 4, 5, 6, 4, 5, 4, 6, 6, 5, 5, 1] + + TESTS:: + + sage: W = CoxeterGroup(['A', 2, 1]) + sage: W.kazhdan_lusztig_cells() + Traceback (most recent call last): + ... + ValueError: the Coxeter group must be finite to compute Kazhdan--Lusztig cells + """ + if not self.coxeter_type().is_finite(): + raise ValueError('the Coxeter group must be finite to compute Kazhdan--Lusztig cells') + + # The identity is its own left-, right-, and two-sided- cell. + identity = frozenset([self.one()]) + cells = {identity} + + for w in self: + if not any(w in c for c in cells): + cell = w.kazhdan_lusztig_cell(side=side) + cells.add(frozenset(cell)) + + return cells + @cached_method def simple_projections(self, side='right', length_increasing=True): r""" From f5706152df1f3545dc265ab6236f6b7ebdbdd263 Mon Sep 17 00:00:00 2001 From: Chase Meadors Date: Sat, 14 Aug 2021 13:54:40 -0600 Subject: [PATCH 095/359] Tweak doctests for KL cell computation methods --- src/sage/categories/coxeter_groups.py | 97 ++++++++++++++++----------- 1 file changed, 56 insertions(+), 41 deletions(-) diff --git a/src/sage/categories/coxeter_groups.py b/src/sage/categories/coxeter_groups.py index b4bc3c0f50d..a87cee06315 100644 --- a/src/sage/categories/coxeter_groups.py +++ b/src/sage/categories/coxeter_groups.py @@ -692,17 +692,15 @@ def simple_projection(self, i, side='right', length_increasing=True): def kazhdan_lusztig_cells(self, side='left'): r""" Compute the left, right, or two-sided Kazhdan-Lusztig cells of - ``self`` by using :func:`ElementMethods.kazhdan_lusztig_cell()`. As - detailed there, this function will be much more efficient if the + ``self`` by using + :func:`kazhdan_lusztig_cell()`. + As detailed there, this function will be much more efficient if the package ``coxeter3`` is installed, due to the method of computing products in the `C^{\prime}` basis of the Iwahori--Hecke algebra. EXAMPLES:: sage: from sage.doctest.fixtures import reproducible_repr # optional - coxeter3 - sage: W = CoxeterGroup('A3') # optional - coxeter3 - sage: [len(c) for c in W.kazhdan_lusztig_cells()] # optional - coxeter3 - [3, 3, 2, 1, 3, 3, 3, 1, 3, 2] sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 sage: print(reproducible_repr(W.kazhdan_lusztig_cells())) # optional - coxeter3 set([frozenset([[1, 2, 1, 3, 2, 1]]), @@ -715,9 +713,16 @@ def kazhdan_lusztig_cells(self, side='left'): frozenset([[1, 3], [2, 1, 3]]), frozenset([[1], [2, 1], [3, 2, 1]]), frozenset([[]])]) - sage: W = CoxeterGroup('A4', implementation='coxeter3') # optional - coxeter3 - sage: [len(c) for c in W.kazhdan_lusztig_cells()] # long time (3 seconds) # optional - coxeter3 - [5, 4, 4, 5, 5, 6, 4, 6, 4, 5, 5, 4, 1, 5, 6, 4, 5, 6, 4, 5, 4, 6, 6, 5, 5, 1] + sage: W = CoxeterGroup('B4', implementation='coxeter3') # optional - coxeter3 + sage: b4_cells = W.kazhdan_lusztig_cells() # long time (45 seconds) # optional - coxeter3 + sage: len(b4_cells) # optional - coxeter3 + 50 + sage: print(reproducible_repr(b4_cells)) # optional - coxeter3 + set([frozenset([[1, 2, 3, 4, 3, 2, 1], [1], [2, 1], [2, 3, 4, 3, 2, 1], [3, 2, 1], [3, 4, 3, 2, 1], [4, 3, 2, 1]]), + frozenset([[1, 2, 3, 4, 3, 2], [1, 2], [2, 3, 4, 3, 2], [2], [3, 2], [3, 4, 3, 2], [4, 3, 2]]), + frozenset([[1, 2, 3, 4, 3], [1, 2, 3], [2, 3, 4, 3], [2, 3], [3, 4, 3], [3], [4, 3]]), + frozenset([[1, 2, 3, 4], [2, 3, 4], [3, 4], [4, 3, 4], [4]]), + ... TESTS:: @@ -2770,45 +2775,55 @@ def kazhdan_lusztig_cell(self, side='left'): EXAMPLES: - Compute some cells in type `B_3`:: + Some simple computations in type `A_3`; we use two different Coxeter + group implementations:: - sage: W = CoxeterGroup('B3', implementation='coxeter3') # optional - coxeter3 + sage: W = CoxeterGroup('A3') # optional - coxeter3 + sage: s1,s2,s3 = W.simple_reflections() # optional - coxeter3 + sage: s1.kazhdan_lusztig_cell() # optional - coxeter3 + {[-1 1 0] + [-1 0 1] + [-1 0 0], + [-1 1 0] + [-1 0 1] + [ 0 0 1], + [-1 1 0] + [ 0 1 0] + [ 0 0 1]} + sage: W = CoxeterGroup('A3', implementation='permutation') # optional - coxeter3 sage: s1,s2,s3 = W.simple_reflections() # optional - coxeter3 - sage: (s1*s2*s1).kazhdan_lusztig_cell() # optional - coxeter3 - {[2, 1, 2], [2, 3, 2, 1, 2], [3, 2, 1, 2]} - sage: (s2*s3*s2).kazhdan_lusztig_cell() # optional - coxeter3 - {[1, 2], [1, 2, 3, 2], [2], [2, 3, 2], [3, 2]} - sage: s3.kazhdan_lusztig_cell() # optional - coxeter3 - {[1, 2, 3], [2, 3], [3], [3, 2, 3]} - sage: s3.kazhdan_lusztig_cell('right') # optional - coxeter3 - {[3], [3, 2], [3, 2, 1], [3, 2, 3]} - sage: s3.kazhdan_lusztig_cell('two-sided') # optional - coxeter3 - {[1], [1, 2], [1, 2, 3], [1, 2, 3, 2], [1, 2, 3, 2, 1], [2], [2, 1], - [2, 3], [2, 3, 2], [2, 3, 2, 1], [3], [3, 2], [3, 2, 1], [3, 2, 3]} - - Some slightly longer computations in type `B_4`:: + sage: s1.kazhdan_lusztig_cell() # optional - coxeter3 + {(1,2,3,12)(4,5,10,11)(6,7,8,9), + (1,2,10)(3,6,5)(4,7,8)(9,12,11), + (1,7)(2,4)(5,6)(8,10)(11,12)} + sage: s1.kazhdan_lusztig_cell(side='right') # optional - coxeter3 + {(1,7)(2,4)(5,6)(8,10)(11,12), + (1,10,2)(3,5,6)(4,8,7)(9,11,12), + (1,12,3,2)(4,11,10,5)(6,9,8,7)} + + Some slightly longer computations in type `B_4`, working directly + with reduced words using the ``coxeter3`` implementation:: sage: W = CoxeterGroup('B4', implementation='coxeter3') # optional - coxeter3 sage: s1,s2,s3,s4 = W.simple_reflections() # optional - coxeter3 - sage: s1.kazhdan_lusztig_cell() # long time (4 seconds) # optional - coxeter3 + sage: s1.kazhdan_lusztig_cell(side='right') # long time (4 seconds) # optional - coxeter3 {[1], - [1, 2, 3, 4, 3, 2, 1], - [2, 1], - [2, 3, 4, 3, 2, 1], - [3, 2, 1], - [3, 4, 3, 2, 1], - [4, 3, 2, 1]} - sage: (s4*s2*s3*s4).kazhdan_lusztig_cell() # long time (2 seconds) # optional - coxeter3 - {[2, 3, 4, 1, 2, 3, 4], - [3, 4, 1, 2, 3, 4], - [3, 4, 2, 3, 4], - [3, 4, 2, 3, 4, 1, 2, 3, 4], - [4, 1, 2, 3, 4], - [4, 2, 3, 4], - [4, 2, 3, 4, 1, 2, 3, 4], - [4, 3, 4, 1, 2, 3, 4], - [4, 3, 4, 2, 3, 4], - [4, 3, 4, 2, 3, 4, 1, 2, 3, 4]} + [1, 2], + [1, 2, 3], + [1, 2, 3, 4], + [1, 2, 3, 4, 3], + [1, 2, 3, 4, 3, 2], + [1, 2, 3, 4, 3, 2, 1]} + sage: (s4*s2*s3*s4).kazhdan_lusztig_cell(side='two-sided') # long time (8 seconds) # optional - coxeter3 + {[2, 3, 1], + [2, 3, 1, 2], + [2, 3, 4, 1], + [2, 3, 4, 1, 2], + [2, 3, 4, 1, 2, 3], + [2, 3, 4, 1, 2, 3, 4], + [2, 3, 4, 3, 1], + [2, 3, 4, 3, 1, 2], + ... """ from sage.algebras.iwahori_hecke_algebra import IwahoriHeckeAlgebra from sage.rings.polynomial.laurent_polynomial_ring import LaurentPolynomialRing From 0137c82b840cc3a7f7fceaa28cd27875242bc11a Mon Sep 17 00:00:00 2001 From: Tianyuan Xu Date: Sat, 14 Aug 2021 14:56:08 -0600 Subject: [PATCH 096/359] doc string changes, more examples --- src/sage/categories/coxeter_groups.py | 82 +++++++++++++++++---------- 1 file changed, 53 insertions(+), 29 deletions(-) diff --git a/src/sage/categories/coxeter_groups.py b/src/sage/categories/coxeter_groups.py index a87cee06315..e4cc7094cb0 100644 --- a/src/sage/categories/coxeter_groups.py +++ b/src/sage/categories/coxeter_groups.py @@ -692,11 +692,12 @@ def simple_projection(self, i, side='right', length_increasing=True): def kazhdan_lusztig_cells(self, side='left'): r""" Compute the left, right, or two-sided Kazhdan-Lusztig cells of - ``self`` by using + ``self`` if ``self`` is finite. + + The cells are computed by using :func:`kazhdan_lusztig_cell()`. - As detailed there, this function will be much more efficient if the - package ``coxeter3`` is installed, due to the method of computing - products in the `C^{\prime}` basis of the Iwahori--Hecke algebra. + As detailed there, installation of the optional package ``coxeter3`` is + strongly recommended (though not required) before using this function. EXAMPLES:: @@ -713,6 +714,11 @@ def kazhdan_lusztig_cells(self, side='left'): frozenset([[1, 3], [2, 1, 3]]), frozenset([[1], [2, 1], [3, 2, 1]]), frozenset([[]])]) + + TODO: do a permutation implementation of A3 and compute its + cells (so that people know that it's ok to not use the coxeter3 + implementation) + sage: W = CoxeterGroup('B4', implementation='coxeter3') # optional - coxeter3 sage: b4_cells = W.kazhdan_lusztig_cells() # long time (45 seconds) # optional - coxeter3 sage: len(b4_cells) # optional - coxeter3 @@ -2747,24 +2753,26 @@ def upper_covers(self, side='right', index_set=None): def kazhdan_lusztig_cell(self, side='left'): r""" Compute the left, right, or two-sided Kazhdan-Lusztig cell - containing the element ``self``. Computes left cells by default; use - the optional argument ``side`` to specify right or two-sided cells. - - Two elements `x,y` of a Coxeter group `W` are said lie in the same - left Kazhdan-Lusztig cell if there exist sequences `x=w_1, w_2, ..., - w_k=y` and `y=u_1, u_2, ..., u_l=x` such that for all `1 \leq i < k` - and all `1 \leq j < l`, there exist some Coxeter generators `s,t` - for which `C'_{w_{i+1}}` appears in `C'_sC'_{w_i}` and - `C'_{u_{j+1}}` appears in `C'_sC'_{u_j}` in the Hecke algebra of the - Coxeter group, where `C'` denotes the Kazhdan-Lusztig - `C^{\prime}`-basis. Right and two-sided Kazhdan-Lusztig cells of `W` - are defined similarly. + containing the element ``self`` depending on the specified + ``side``. + + Let `C'` denote the Kazhdan-Lusztig `C^{\prime}`-basis of the + Iwahori-Hecke algebra `H` of a Coxeter system `(W,S)`. Two elements + `x,y` of the Coxeter group `W` are said to lie in the same left + Kazhdan-Lusztig cell if there exist sequences `x=w_1, w_2, ..., + w_k=y` and `y=u_1, u_2, ..., u_l=x` such that for all `1 \leq i < + k` and all `1 \leq j < l`, there exist some Coxeter generators `s,t + \in S` for which `C'_{w_{i+1}}` appears in `C'_sC'_{w_i}` and + `C'_{u_{j+1}}` appears in `C'_sC'_{u_j}` in `H`. Right and + two-sided Kazhdan-Lusztig cells of `W` are defined similarly; see + [Lus2013]_. In this function, we compute products in the `C^{\prime}` basis by - using :class:`IwahoriHeckeAlgebra.Cp`. To use the direct algorithm - for computing such products detailed therein, the package - ``coxeter3`` must be installed; otherwise, this method will most - likely be computationally infeasible. + using :class:`IwahoriHeckeAlgebra.Cp`. As mentioned in that class, + installing the optional package ``coxeter3`` is strongly + recommended (though not required) before using this function, + because the package speeds up product computations that are + sometimes computationally infeasible without it. INPUT: @@ -2775,8 +2783,13 @@ def kazhdan_lusztig_cell(self, side='left'): EXAMPLES: - Some simple computations in type `A_3`; we use two different Coxeter - group implementations:: + We compute the left cell of the generator `s_1` in type `A_3` in + three different implementations of the Coxeter group. Note that the + choice of implementation affects the representation of elements in + the output cell but not the method used for the cell computation. + In particular, the cell computation uses the optional package + ``coxeter3`` in the background as long as it is installed, even in + the default (matrix) and 'permutation' implementations:: sage: W = CoxeterGroup('A3') # optional - coxeter3 sage: s1,s2,s3 = W.simple_reflections() # optional - coxeter3 @@ -2790,19 +2803,30 @@ def kazhdan_lusztig_cell(self, side='left'): [-1 1 0] [ 0 1 0] [ 0 0 1]} + sage: W = CoxeterGroup('A3', implementation='permutation') # optional - coxeter3 sage: s1,s2,s3 = W.simple_reflections() # optional - coxeter3 sage: s1.kazhdan_lusztig_cell() # optional - coxeter3 {(1,2,3,12)(4,5,10,11)(6,7,8,9), (1,2,10)(3,6,5)(4,7,8)(9,12,11), (1,7)(2,4)(5,6)(8,10)(11,12)} - sage: s1.kazhdan_lusztig_cell(side='right') # optional - coxeter3 - {(1,7)(2,4)(5,6)(8,10)(11,12), - (1,10,2)(3,5,6)(4,8,7)(9,11,12), - (1,12,3,2)(4,11,10,5)(6,9,8,7)} - Some slightly longer computations in type `B_4`, working directly - with reduced words using the ``coxeter3`` implementation:: + sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 + sage: s1,s2,s3 = W.simple_reflections() # optional - coxeter3 + sage: s1.kazhdan_lusztig_cell() # optional - coxeter3 + TODO: add output + + Next, we compute a right cell and a two-sided cell in `A_3`:: + + sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 + sage: s1,s2,s3 = W.simple_reflections() # optional - coxeter3 + sage: w = s1*s3 + sage: w.kazhdan_lusztig_cell(side='right') # optional - coxeter3 + TODO: add output + sage: w.kazhdan_lusztig_cell(side='two-sided') # optional - coxeter3 + TODO: add output + + Some slightly longer computations in `B_4`:: sage: W = CoxeterGroup('B4', implementation='coxeter3') # optional - coxeter3 sage: s1,s2,s3,s4 = W.simple_reflections() # optional - coxeter3 @@ -2858,4 +2882,4 @@ def kazhdan_lusztig_cell(self, side='left'): queue.appendleft(y) g = DiGraph([list(vertices), list(edges)]) - return set(g.strongly_connected_component_containing_vertex(w)) \ No newline at end of file + return set(g.strongly_connected_component_containing_vertex(w)) From 35308531866b23360a29dbbd09d7bb02d6973c0c Mon Sep 17 00:00:00 2001 From: Chase Meadors Date: Sat, 14 Aug 2021 17:09:39 -0600 Subject: [PATCH 097/359] Complete docstrings --- src/sage/categories/coxeter_groups.py | 85 ++++++++++++++++----------- 1 file changed, 50 insertions(+), 35 deletions(-) diff --git a/src/sage/categories/coxeter_groups.py b/src/sage/categories/coxeter_groups.py index e4cc7094cb0..12e09797a38 100644 --- a/src/sage/categories/coxeter_groups.py +++ b/src/sage/categories/coxeter_groups.py @@ -693,13 +693,16 @@ def kazhdan_lusztig_cells(self, side='left'): r""" Compute the left, right, or two-sided Kazhdan-Lusztig cells of ``self`` if ``self`` is finite. - + The cells are computed by using :func:`kazhdan_lusztig_cell()`. - As detailed there, installation of the optional package ``coxeter3`` is - strongly recommended (though not required) before using this function. + As detailed there, installation of the optional package ``coxeter3`` + is strongly recommended (though not required) before using this + function. - EXAMPLES:: + EXAMPLES: + + Compute the left cells in `A_3`:: sage: from sage.doctest.fixtures import reproducible_repr # optional - coxeter3 sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 @@ -715,9 +718,22 @@ def kazhdan_lusztig_cells(self, side='left'): frozenset([[1], [2, 1], [3, 2, 1]]), frozenset([[]])]) - TODO: do a permutation implementation of A3 and compute its - cells (so that people know that it's ok to not use the coxeter3 - implementation) + Note that the choice of implementation affects the representation of + elements in the output cell but not the method used for the cell + computation. In particular, the cell computation uses the optional + package ``coxeter3`` in the background as long as it is installed, + even in the default (matrix) and 'permutation' implementations:: + + sage: W = CoxeterGroup('A3', implementation='permutation') # optional - coxeter3 + sage: print(reproducible_repr(W.kazhdan_lusztig_cells())) # optional - coxeter3 + set([frozenset([()]), + frozenset([(1,10,2)(3,5,6)(4,8,7)(9,11,12), (1,4)(2,8)(3,5)(7,10)(9,11), (1,4,6)(2,3,11)(5,8,9)(7,10,12)]), + frozenset([(1,10,9,5)(2,6,8,12)(3,11,7,4), (1,3)(2,12)(4,10)(5,11)(6,8)(7,9)]), + frozenset([(1,11)(3,10)(4,9)(5,7)(6,12), (1,11,8)(2,7,5)(3,4,12)(6,9,10), (1,5,12)(2,9,4)(3,10,8)(6,7,11)]), + ... + frozenset([(1,9)(2,8)(3,7)(4,11)(5,10)(6,12)])]) + + Computing the left cells in `B_4` takes about 45 seconds:: sage: W = CoxeterGroup('B4', implementation='coxeter3') # optional - coxeter3 sage: b4_cells = W.kazhdan_lusztig_cells() # long time (45 seconds) # optional - coxeter3 @@ -729,6 +745,7 @@ def kazhdan_lusztig_cells(self, side='left'): frozenset([[1, 2, 3, 4, 3], [1, 2, 3], [2, 3, 4, 3], [2, 3], [3, 4, 3], [3], [4, 3]]), frozenset([[1, 2, 3, 4], [2, 3, 4], [3, 4], [4, 3, 4], [4]]), ... + frozenset([[]])]) TESTS:: @@ -740,7 +757,7 @@ def kazhdan_lusztig_cells(self, side='left'): """ if not self.coxeter_type().is_finite(): raise ValueError('the Coxeter group must be finite to compute Kazhdan--Lusztig cells') - + # The identity is its own left-, right-, and two-sided- cell. identity = frozenset([self.one()]) cells = {identity} @@ -749,7 +766,7 @@ def kazhdan_lusztig_cells(self, side='left'): if not any(w in c for c in cells): cell = w.kazhdan_lusztig_cell(side=side) cells.add(frozenset(cell)) - + return cells @cached_method @@ -817,7 +834,7 @@ def sign_representation(self, base_ring=None, side="twosided"): sage: W = WeylGroup(["A", 1, 1]) sage: W.sign_representation() Sign representation of Weyl Group of type ['A', 1, 1] (as a matrix group acting on the root space) over Integer Ring - + """ if base_ring is None: from sage.rings.integer_ring import ZZ @@ -2753,26 +2770,25 @@ def upper_covers(self, side='right', index_set=None): def kazhdan_lusztig_cell(self, side='left'): r""" Compute the left, right, or two-sided Kazhdan-Lusztig cell - containing the element ``self`` depending on the specified - ``side``. + containing the element ``self`` depending on the specified ``side``. Let `C'` denote the Kazhdan-Lusztig `C^{\prime}`-basis of the Iwahori-Hecke algebra `H` of a Coxeter system `(W,S)`. Two elements `x,y` of the Coxeter group `W` are said to lie in the same left Kazhdan-Lusztig cell if there exist sequences `x=w_1, w_2, ..., - w_k=y` and `y=u_1, u_2, ..., u_l=x` such that for all `1 \leq i < - k` and all `1 \leq j < l`, there exist some Coxeter generators `s,t - \in S` for which `C'_{w_{i+1}}` appears in `C'_sC'_{w_i}` and + w_k=y` and `y=u_1, u_2, ..., u_l=x` such that for all `1 \leq i < k` + and all `1 \leq j < l`, there exist some Coxeter generators `s,t \in + S` for which `C'_{w_{i+1}}` appears in `C'_sC'_{w_i}` and `C'_{u_{j+1}}` appears in `C'_sC'_{u_j}` in `H`. Right and two-sided Kazhdan-Lusztig cells of `W` are defined similarly; see [Lus2013]_. In this function, we compute products in the `C^{\prime}` basis by using :class:`IwahoriHeckeAlgebra.Cp`. As mentioned in that class, - installing the optional package ``coxeter3`` is strongly - recommended (though not required) before using this function, - because the package speeds up product computations that are - sometimes computationally infeasible without it. + installing the optional package ``coxeter3`` is strongly recommended + (though not required) before using this function, because the + package speeds up product computations that are sometimes + computationally infeasible without it. INPUT: @@ -2786,10 +2802,10 @@ def kazhdan_lusztig_cell(self, side='left'): We compute the left cell of the generator `s_1` in type `A_3` in three different implementations of the Coxeter group. Note that the choice of implementation affects the representation of elements in - the output cell but not the method used for the cell computation. - In particular, the cell computation uses the optional package + the output cell but not the method used for the cell computation. In + particular, the cell computation uses the optional package ``coxeter3`` in the background as long as it is installed, even in - the default (matrix) and 'permutation' implementations:: + the default (matrix) and 'permutation' implementations:: sage: W = CoxeterGroup('A3') # optional - coxeter3 sage: s1,s2,s3 = W.simple_reflections() # optional - coxeter3 @@ -2803,28 +2819,26 @@ def kazhdan_lusztig_cell(self, side='left'): [-1 1 0] [ 0 1 0] [ 0 0 1]} - sage: W = CoxeterGroup('A3', implementation='permutation') # optional - coxeter3 sage: s1,s2,s3 = W.simple_reflections() # optional - coxeter3 sage: s1.kazhdan_lusztig_cell() # optional - coxeter3 {(1,2,3,12)(4,5,10,11)(6,7,8,9), (1,2,10)(3,6,5)(4,7,8)(9,12,11), (1,7)(2,4)(5,6)(8,10)(11,12)} - - sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 - sage: s1,s2,s3 = W.simple_reflections() # optional - coxeter3 - sage: s1.kazhdan_lusztig_cell() # optional - coxeter3 - TODO: add output + sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 + sage: s1,s2,s3 = W.simple_reflections() # optional - coxeter3 + sage: s1.kazhdan_lusztig_cell() # optional - coxeter3 + {[1], [2, 1], [3, 2, 1]} Next, we compute a right cell and a two-sided cell in `A_3`:: - - sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 - sage: s1,s2,s3 = W.simple_reflections() # optional - coxeter3 + + sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 + sage: s1,s2,s3 = W.simple_reflections() # optional - coxeter3 sage: w = s1*s3 - sage: w.kazhdan_lusztig_cell(side='right') # optional - coxeter3 - TODO: add output - sage: w.kazhdan_lusztig_cell(side='two-sided') # optional - coxeter3 - TODO: add output + sage: w.kazhdan_lusztig_cell(side='right') # optional - coxeter3 + {[1, 3], [1, 3, 2]} + sage: w.kazhdan_lusztig_cell(side='two-sided') # optional - coxeter3 + {[1, 3], [1, 3, 2], [2, 1, 3], [2, 1, 3, 2]} Some slightly longer computations in `B_4`:: @@ -2848,6 +2862,7 @@ def kazhdan_lusztig_cell(self, side='left'): [2, 3, 4, 3, 1], [2, 3, 4, 3, 1, 2], ... + [4, 3, 4, 2, 3, 4, 1, 2, 3, 4]} """ from sage.algebras.iwahori_hecke_algebra import IwahoriHeckeAlgebra from sage.rings.polynomial.laurent_polynomial_ring import LaurentPolynomialRing From 7a73b82edb3ad184955829a73ec66ba74c7a9724 Mon Sep 17 00:00:00 2001 From: Chase Meadors Date: Sat, 14 Aug 2021 17:14:13 -0600 Subject: [PATCH 098/359] Document 'side' arguments --- src/sage/categories/coxeter_groups.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/sage/categories/coxeter_groups.py b/src/sage/categories/coxeter_groups.py index 12e09797a38..12b4cfd1724 100644 --- a/src/sage/categories/coxeter_groups.py +++ b/src/sage/categories/coxeter_groups.py @@ -700,6 +700,11 @@ def kazhdan_lusztig_cells(self, side='left'): is strongly recommended (though not required) before using this function. + INPUT: + + - ``side`` -- ``'left'``, ``'right'``, or ``'two-sided'`` (default: + ``'left'``) + EXAMPLES: Compute the left cells in `A_3`:: @@ -2794,8 +2799,8 @@ def kazhdan_lusztig_cell(self, side='left'): - ``w`` -- an element of self. - - ``side`` -- string (default: ``'left'``); one of 'left', 'right', - or 'two-sided', corresponding to the kind of cell to compute. + - ``side`` -- ``'left'``, ``'right'``, or ``'two-sided'`` (default: + ``'left'``), corresponding to the kind of cell to compute. EXAMPLES: From 1070fd42ae2edd4d13c701bb976f42c3c9f9814f Mon Sep 17 00:00:00 2001 From: Tianyuan Xu Date: Sat, 14 Aug 2021 17:43:59 -0600 Subject: [PATCH 099/359] doc string changes to cells function --- src/sage/categories/coxeter_groups.py | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/sage/categories/coxeter_groups.py b/src/sage/categories/coxeter_groups.py index 12b4cfd1724..47e533dce90 100644 --- a/src/sage/categories/coxeter_groups.py +++ b/src/sage/categories/coxeter_groups.py @@ -707,7 +707,15 @@ def kazhdan_lusztig_cells(self, side='left'): EXAMPLES: - Compute the left cells in `A_3`:: + We compute the left cells in the Coxeter group of type `A_3` below. + Note that each Coxeter group may be created with multiple + implementations, namely, 'reflection' (default), 'permutation', + 'matrix', or 'coxeter3'. The choice of implementation affects the + representation of elements in the output cells but not the method + used for the cell computation. In particular, the cell computation + uses the optional package ``coxeter3`` in the background as long as + the package is installed, even if the group is not created with the + 'coxeter3' implementation. sage: from sage.doctest.fixtures import reproducible_repr # optional - coxeter3 sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 @@ -722,13 +730,7 @@ def kazhdan_lusztig_cells(self, side='left'): frozenset([[1, 3], [2, 1, 3]]), frozenset([[1], [2, 1], [3, 2, 1]]), frozenset([[]])]) - - Note that the choice of implementation affects the representation of - elements in the output cell but not the method used for the cell - computation. In particular, the cell computation uses the optional - package ``coxeter3`` in the background as long as it is installed, - even in the default (matrix) and 'permutation' implementations:: - + sage: W = CoxeterGroup('A3', implementation='permutation') # optional - coxeter3 sage: print(reproducible_repr(W.kazhdan_lusztig_cells())) # optional - coxeter3 set([frozenset([()]), @@ -2809,8 +2811,8 @@ def kazhdan_lusztig_cell(self, side='left'): choice of implementation affects the representation of elements in the output cell but not the method used for the cell computation. In particular, the cell computation uses the optional package - ``coxeter3`` in the background as long as it is installed, even in - the default (matrix) and 'permutation' implementations:: + ``coxeter3`` in the background as long as the package is installed, even in + the default ('reflection') and 'permutation' implementations:: sage: W = CoxeterGroup('A3') # optional - coxeter3 sage: s1,s2,s3 = W.simple_reflections() # optional - coxeter3 From 8a3d7593ca30b6694cd15711bc88afa46468ebc4 Mon Sep 17 00:00:00 2001 From: Chase Meadors Date: Sat, 14 Aug 2021 17:46:26 -0600 Subject: [PATCH 100/359] Format docstrings --- src/sage/categories/coxeter_groups.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sage/categories/coxeter_groups.py b/src/sage/categories/coxeter_groups.py index 47e533dce90..b1c3aab33fb 100644 --- a/src/sage/categories/coxeter_groups.py +++ b/src/sage/categories/coxeter_groups.py @@ -730,7 +730,6 @@ def kazhdan_lusztig_cells(self, side='left'): frozenset([[1, 3], [2, 1, 3]]), frozenset([[1], [2, 1], [3, 2, 1]]), frozenset([[]])]) - sage: W = CoxeterGroup('A3', implementation='permutation') # optional - coxeter3 sage: print(reproducible_repr(W.kazhdan_lusztig_cells())) # optional - coxeter3 set([frozenset([()]), @@ -2811,8 +2810,9 @@ def kazhdan_lusztig_cell(self, side='left'): choice of implementation affects the representation of elements in the output cell but not the method used for the cell computation. In particular, the cell computation uses the optional package - ``coxeter3`` in the background as long as the package is installed, even in - the default ('reflection') and 'permutation' implementations:: + ``coxeter3`` in the background as long as the package is installed, + even in the default ('reflection') and 'permutation' + implementations:: sage: W = CoxeterGroup('A3') # optional - coxeter3 sage: s1,s2,s3 = W.simple_reflections() # optional - coxeter3 From f0fb7e245bb0594bfccf27b50a62807d459f6ccd Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Mon, 16 Aug 2021 10:36:16 +1000 Subject: [PATCH 101/359] Adding back build/pkgs/sage_sws2rst/src file. --- build/pkgs/sage_sws2rst/src | 1 + 1 file changed, 1 insertion(+) create mode 120000 build/pkgs/sage_sws2rst/src diff --git a/build/pkgs/sage_sws2rst/src b/build/pkgs/sage_sws2rst/src new file mode 120000 index 00000000000..2de26d80e1e --- /dev/null +++ b/build/pkgs/sage_sws2rst/src @@ -0,0 +1 @@ +../../../pkgs/sage-sws2rst \ No newline at end of file From 67c7b3ab302e8d1db3091fda70f7153695020697 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Mon, 16 Aug 2021 11:27:48 +1000 Subject: [PATCH 102/359] Reviewer changes to improve speed and other various doc tweaks. --- src/sage/algebras/iwahori_hecke_algebra.py | 228 +++++++++++---------- src/sage/categories/coxeter_groups.py | 149 +++++++------- 2 files changed, 198 insertions(+), 179 deletions(-) diff --git a/src/sage/algebras/iwahori_hecke_algebra.py b/src/sage/algebras/iwahori_hecke_algebra.py index c6628f341f4..4e64e3bfe90 100644 --- a/src/sage/algebras/iwahori_hecke_algebra.py +++ b/src/sage/algebras/iwahori_hecke_algebra.py @@ -1862,9 +1862,9 @@ class Cp(_KLHeckeBasis): .. MATH:: \begin{aligned} - \overline{ C^{\prime}_w } &= C^{\prime}_w\\ + \overline{ C^{\prime}_w } &= C^{\prime}_w, \\ C^{\prime}_w &= q^{-\ell(w)/2} - \sum_{v \leq w} P_{v,w}(q) T_v + \sum_{v \leq w} P_{v,w}(q) T_v, \end{aligned} where `\leq` is the Bruhat order on the underlying Coxeter group and @@ -1891,8 +1891,8 @@ class Cp(_KLHeckeBasis): calculate certain `\mu`-coefficients quickly. If the above conditions are not all met, the function computes such products indirectly, by converting elements to the `T`-basis, computing products there, and - converting back. The indirect method can be prohibitively slow for more - complex calculations; the direct method is faster. + converting back. The indirect method can be prohibitively slow for + more complex calculations; the direct method is faster. EXAMPLES:: @@ -1984,44 +1984,42 @@ def __init__(self, IHAlgebra, prefix=None): r""" TESTS:: - sage: R = LaurentPolynomialRing(QQ, 'v') # optional - coxeter3 - sage: v = R.gen(0) # optional - coxeter3 - sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 - sage: H = IwahoriHeckeAlgebra(W, v**2) # optional - coxeter3 - sage: Cp = H.Cp() # optional - coxeter3 - sage: Cp.delta == v + ~v # optional - coxeter3 + sage: R. = LaurentPolynomialRing(QQ) # optional - coxeter3 + sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 + sage: H = IwahoriHeckeAlgebra(W, v**2) # optional - coxeter3 + sage: Cp = H.Cp() # optional - coxeter3 + sage: Cp._delta == v + ~v # optional - coxeter3 True - sage: Cp._W_Coxeter3 == H._W # optional - coxeter3 + sage: Cp._W_Coxeter3 == H._W # optional - coxeter3 True - sage: H = IwahoriHeckeAlgebra(W, QQ(1)) # optional - coxeter3 - sage: Cp = H.Cp() # optional - coxeter3 - sage: Cp.delta == None # optional - coxeter3 + sage: H = IwahoriHeckeAlgebra(W, QQ(1)) # optional - coxeter3 + sage: Cp = H.Cp() # optional - coxeter3 + sage: Cp._W_Coxeter3 is None # optional - coxeter3 True """ super().__init__(IHAlgebra, prefix) - self.delta = None self._W_Coxeter3 = None # See if we meet the conditions to use the direct product_on_basis algorithm. - # If we do, both of these will be non-None. - + # To use v + ~v as the value delta, we need the standard or + # normalized presentations of the Hecke algebra. v = IHAlgebra.base_ring().gen(0) parameters = {IHAlgebra.q1(), IHAlgebra.q2()} - if v != IHAlgebra.base_ring().one() and (parameters == {v**2, -1} or parameters == {v, -1/v}): - # The following quantity delta is used in product computations. - # To use v+~v as its value we need the standard or normalized presentations of the Hecke algebra. - self.delta = v + ~v + if v == IHAlgebra.base_ring().one() or (parameters != {v**2, -1} and parameters != {v, -1/v}): + return - # check if products can be computed directly using ``coxeter3``: + # check if products can be computed directly using ``coxeter3`` try: from sage.libs.coxeter3.coxeter_group import CoxeterGroup as Coxeter3Group - if isinstance(IHAlgebra._W, Coxeter3Group): - self._W_Coxeter3 = IHAlgebra._W - else: - self._W_Coxeter3 = CoxeterGroup(IHAlgebra._W.coxeter_type(), implementation='coxeter3') except ImportError: - pass + return + + self._delta = v + ~v + if isinstance(IHAlgebra._W, Coxeter3Group): + self._W_Coxeter3 = IHAlgebra._W + else: + self._W_Coxeter3 = CoxeterGroup(IHAlgebra._W.coxeter_type(), implementation='coxeter3') def hash_involution_on_basis(self, w): r""" @@ -2046,8 +2044,8 @@ def hash_involution_on_basis(self, w): def product_on_basis(self, w1, w2): r""" - Return the expansion of `C^{\prime}_{w_1} \cdot C^{\prime}_{w_2}` in - the `C^{\prime}`-basis. + Return the expansion of `C^{\prime}_{w_1} \cdot C^{\prime}_{w_2}` + in the `C^{\prime}`-basis. If ``coxeter3`` is installed and the Iwahori--Hecke algebra is in the standard or normalized presentation, the product is computed @@ -2065,15 +2063,17 @@ def product_on_basis(self, w1, w2): .. MATH:: C^{\prime}_s \cdot C^{\prime}_w = \begin{cases} - (q+q^{-1})C^{\prime}_{w}, & \text{if } \ell(sw) = \ell(w)-1,\\ - C^{\prime}_{sw}+\sum_{v\leq w, sv \leq v} \mu(v,w)C^{\prime}_v, - & \text{if } \ell(sw) = \ell(w)+1. - \end{cases} + (q+q^{-1})C^{\prime}_{w}, & \text{if } \ell(sw) = \ell(w)-1,\\ + C^{\prime}_{sw}+\sum_{v\leq w, sv \leq v} \mu(v,w)C^{\prime}_v, + & \text{if } \ell(sw) = \ell(w)+1. + \end{cases} + + \qquad\qquad C^{\prime}_w \cdot C^{\prime}_s = \begin{cases} - (q+q^{-1})C^{\prime}_{w}, & \text{if } \ell(ws) = \ell(w)-1,\\ - C^{\prime}_{ws}+\sum_{v\leq w, vs \leq v} \mu(v,w)C^{\prime}_v, - & \text{if } \ell(ws) = \ell(w)+1. + (q+q^{-1})C^{\prime}_{w}, & \text{if } \ell(ws) = \ell(w)-1,\\ + C^{\prime}_{ws}+\sum_{v\leq w, vs \leq v} \mu(v,w)C^{\prime}_v, + & \text{if } \ell(ws) = \ell(w)+1. \end{cases} In the above, `\leq` is the Bruhat order on the Coxeter group and @@ -2082,15 +2082,15 @@ def product_on_basis(self, w1, w2): method designates the computation of the `\mu`-coefficients to Sage's interface to Fokko du Cloux's ``coxeter3`` package, which is why the method requires the creation of the Coxeter group using the - 'coxeter3' implementation. + ``'coxeter3'`` implementation. ALGORITHM: The direct algorithm for computing `C^{\prime}_x \cdot C^{\prime}_y` runs in two steps as follows. - If `\ell(x) \leq \ell(y)`, we first decompose `C^{\prime}_x` into a - polynomial in the generators `C^{\prime}_s (s\in S)` and then + If `\ell(x) \leq \ell(y)`, we first decompose `C^{\prime}_x` into + a polynomial in the generators `C^{\prime}_s (s\in S)` and then multiply that polynomial with `C^{\prime}_y`. If `\ell(x) > \ell(y)`, we decompose `C^{\prime}_y` into a polynomial in `C^{\prime}_s (s\in S)` and multiply that polynomial with @@ -2103,7 +2103,8 @@ def product_on_basis(self, w1, w2): .. MATH:: - C^{\prime}_u = C^{\prime}_s \cdot C^{\prime}_{w} - \sum_{v\le u; sv< v} \mu(v,w) C^{\prime}_v + C^{\prime}_u = C^{\prime}_s \cdot C^{\prime}_{w} + - \sum_{v \le u; sv < v} \mu(v,w) C^{\prime}_v by the earlier formulas, where the element `w` and all elements `v`'s on the right side are lower than `u` in the Bruhat order; @@ -2116,7 +2117,8 @@ def product_on_basis(self, w1, w2): .. MATH:: - C^{\prime}_{121} = C^{\prime}_1 C^{\prime}_2 C^{\prime}_1 - C^{\prime}_1. + C^{\prime}_{121} = C^{\prime}_1 C^{\prime}_2 C^{\prime}_1 + - C^{\prime}_1. We note that the base cases `\ell(x)=1` or `\ell(x)=0` of the above induction occur when `x` is itself a Coxeter generator `s` or the @@ -2134,14 +2136,14 @@ def product_on_basis(self, w1, w2): sage: Cp.product_on_basis(W([1,2,1]), W([3,1,2])) # optional - coxeter3 (v^-1+v)*Cp[1,2,1,3,2] + (v^-1+v)*Cp[1,2,1] """ - if self.delta is None or self._W_Coxeter3 is None: + if self._W_Coxeter3 is None: # We do not meet the conditions to use the direct product # algorithm; fall back to conversion to/from the T-basis. return super().product_on_basis(w1, w2) # If self._W_Coxeter3 is not the underlying Coxeter group, we need # to convert elements first for this algorithm. - if (self._W_Coxeter3 != self.realization_of()._W): + if self._W_Coxeter3 != self.realization_of()._W: w1 = self._W_Coxeter3.from_reduced_word(w1.reduced_word()) w2 = self._W_Coxeter3.from_reduced_word(w2.reduced_word()) @@ -2149,99 +2151,103 @@ def product_on_basis(self, w1, w2): # generators C'_{s}. if len(w1) <= len(w2): side = 'left' - gen_expression = self.decompose_into_generators(w1) + gen_expression = self._decompose_into_generators(w1) other_element = self.monomial(w2) else: side = 'right' - gen_expression = self.decompose_into_generators(w2) + gen_expression = self._decompose_into_generators(w2) other_element = self.monomial(w1) - result = self(0) + # Multiplication: multiply the generators in each term of the above # polynomial onto other_element and add that summand onto result. + result = self.zero() for (p, coeff) in gen_expression.items(): summand = coeff * other_element - p_list = list(p) if side == 'right' else list(p)[::-1] - for s in p_list: - summand = self.product_with_generator(s, summand, side) + if side == 'right': + for s in p: + summand = self._product_with_generator(s, summand, side) + else: + for s in reversed(p): + summand = self._product_with_generator(s, summand, side) result += summand # Again, if self._W_Coxeter3 is not the underlying Coxeter group, # we need to convert the result. Specifically, make sure basis # elements appearing therein are actually indexed by elements of # the original underlying Coxeter group. - - if (self._W_Coxeter3 != self.realization_of()._W): + if self._W_Coxeter3 != self.realization_of()._W: _W = self.realization_of()._W - result = self.linear_combination((self(_W.from_reduced_word(w.reduced_word())), c) for (w, c) in result) + result = self._from_dict({_W.from_reduced_word(w.reduced_word()): c + for (w, c) in result}, remove_zeros=False) return result - def product_with_generator_on_basis(self, s, w, side='left'): + def _product_with_generator_on_basis(self, s, w, side='left'): r""" Compute the product of `C^{\prime}_s` and `C^{\prime}_w`, putting `C^{\prime}_s` on the given ``side``. INPUT: - - ``s`` -- integer in self.index_set() - - - ``w`` -- a word in self.coxeter_group() - + - ``s`` -- integer in ``self.index_set()`` + - ``w`` -- a word in ``self.coxeter_group()`` - ``side`` -- string; ``'left'`` or ``'right'`` EXAMPLES:: - sage: R. = LaurentPolynomialRing(ZZ, 'v') # optional - coxeter3 - sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 - sage: H = IwahoriHeckeAlgebra(W, v**2); Cp=H.Cp() # optional - coxeter3 - sage: Cp.product_with_generator_on_basis(1, W([2,1]), 'left') # optional - coxeter3 + sage: R. = LaurentPolynomialRing(ZZ, 'v') # optional - coxeter3 + sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 + sage: H = IwahoriHeckeAlgebra(W, v**2); Cp = H.Cp() # optional - coxeter3 + sage: Cp._product_with_generator_on_basis(1, W([2,1]), 'left') # optional - coxeter3 Cp[1,2,1] + Cp[1] - sage: Cp.product_with_generator_on_basis(1, W([2,1]), 'right') # optional - coxeter3 + sage: Cp._product_with_generator_on_basis(1, W([2,1]), 'right') # optional - coxeter3 (v^-1+v)*Cp[2,1] - sage: Cp.product_with_generator_on_basis(2, W([1,3,2,1,3]), 'right') # optional - coxeter3 + sage: Cp._product_with_generator_on_basis(2, W([1,3,2,1,3]), 'right') # optional - coxeter3 Cp[1,2,1,3,2,1] + Cp[1,2,3,2] + Cp[1,3,2,1] """ # use the product formula described in the class' documentation if w.has_descent(s, side=side): - return self.delta * self.monomial(w) - else: - element = self(0) - between = self._W_Coxeter3.bruhat_interval([], w) - for x in between: - # Get (coxeter3-implemented) group element corresponding to x - x_elt = self._W_Coxeter3(x) - if x_elt.has_descent(s, side=side): - # Compute mu-coefficient via coxeter3 - element += x.mu_coefficient(w) * self.monomial(x_elt) - longer_word = self._W_Coxeter3([s]) * w if side == 'left' else w * self._W_Coxeter3([s]) - return self.monomial(longer_word) + element - - def product_with_generator(self, s, x, side='left'): + return self._from_dict({w: self._delta}, remove_zeros=False) + + element = {} + between = self._W_Coxeter3.bruhat_interval([], w) + R = self.base_ring() + for x in between: + # Get (coxeter3-implemented) group element corresponding to x + x_elt = self._W_Coxeter3(x) + if x_elt.has_descent(s, side=side): + # Compute mu-coefficient via coxeter3 + coeff = R(x.mu_coefficient(w)) + if coeff: + element[x_elt] = coeff + longer_word = self._W_Coxeter3([s]) * w if side == 'left' else w * self._W_Coxeter3([s]) + element[longer_word] = R.one() + return self._from_dict(element, remove_zeros=False) + + def _product_with_generator(self, s, x, side='left'): r""" - Compute the product of `C^{\prime}_s` with any linear combination of - `C^{\prime}`-basis elements. + Compute the product of `C^{\prime}_s` with any linear + combination of `C^{\prime}`-basis elements. INPUT: - - ``s`` -- integer in self.index_set() - - - ``x`` -- any element of self - + - ``s`` -- integer in ``self.index_set()`` + - ``x`` -- any element of ``self`` - ``side`` -- string; ``'left'`` or ``'right'`` EXAMPLES:: sage: R. = LaurentPolynomialRing(ZZ, 'v') # optional - coxeter3 sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 - sage: H = IwahoriHeckeAlgebra(W, v**2); Cp=H.Cp() # optional - coxeter3 - sage: Cp.product_with_generator(1, Cp[1]+Cp[2], 'left') # optional - coxeter3 + sage: H = IwahoriHeckeAlgebra(W, v**2); Cp = H.Cp() # optional - coxeter3 + sage: Cp._product_with_generator(1, Cp[1]+Cp[2], 'left') # optional - coxeter3 Cp[1,2] + (v^-1+v)*Cp[1] - sage: Cp.product_with_generator(1, Cp[1]+Cp[2], 'right') # optional - coxeter3 + sage: Cp._product_with_generator(1, Cp[1]+Cp[2], 'right') # optional - coxeter3 Cp[2,1] + (v^-1+v)*Cp[1] """ - return self.linear_combination((self.product_with_generator_on_basis(s, w, side), coeff) for (w, coeff) in x) + return self.linear_combination((self._product_with_generator_on_basis(s, w, side), coeff) for (w, coeff) in x) - def decompose_into_generators(self, u): + def _decompose_into_generators(self, u): r""" Decompose `C^{\prime}_u` into a polynomial in the KL generators `C^{\prime}_s`; see the ALGORITHM section of @@ -2250,40 +2256,38 @@ def decompose_into_generators(self, u): OUTPUT: A dictionary keyed by tuples with integer values. Each entry - represents a term, where the tuple represents a monomial term in the - KL generators and the value represents the coefficient of that term. - For example, an item `(1,2): 3` stands for `3 \cdot - C^{\prime}_1C^{\prime}_2`. + represents a term, where the tuple represents a monomial term + in the KL generators and the value represents the coefficient + of that term. For example, an item `(1,2): 3` stands for + `3 \cdot C^{\prime}_1 C^{\prime}_2`. - EXAMPLES: - - :: + EXAMPLES:: - sage: R. = LaurentPolynomialRing(ZZ, 'v') # optional - coxeter3 - sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 - sage: H = IwahoriHeckeAlgebra(W, v**2); Cp=H.Cp() # optional - coxeter3 + sage: R. = LaurentPolynomialRing(ZZ, 'v') # optional - coxeter3 + sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 + sage: H = IwahoriHeckeAlgebra(W, v**2); Cp=H.Cp() # optional - coxeter3 When `u` is itself a generator `s`, the decomposition is trivial:: - sage: Cp.decompose_into_generators(W([1])) # optional - coxeter3 + sage: Cp._decompose_into_generators(W([1])) # optional - coxeter3 {(1,): 1} Another example, where `C^{\prime}_u` happens to be a monomial (e.g., `C'_{21} = C'_2 C'_1`):: - sage: Cp.decompose_into_generators(W([2,1])) # optional - coxeter3 + sage: Cp._decompose_into_generators(W([2,1])) # optional - coxeter3 {(2, 1): 1} In more general situations the sum is a polynomial (e.g., - `C'_{121}=C'_1 C'_2 C'_1 - C'_1)`:: + `C'_{121} = C'_1 C'_2 C'_1 - C'_1)`:: - sage: Cp.decompose_into_generators(W([1,2,1])) # optional - coxeter3 + sage: Cp._decompose_into_generators(W([1,2,1])) # optional - coxeter3 {(1,): -1, (1, 2, 1): 1} - sage: Cp.decompose_into_generators(W([1,2,3,1,2])) # optional - coxeter3 + sage: Cp._decompose_into_generators(W([1,2,3,1,2])) # optional - coxeter3 {(1,): 1, (1, 2, 1): -1, (1, 2, 1, 3, 2): 1, (1, 3, 2): -1} """ # l(y) = 0 or 1 - if len(u) == 0: + if not u: return {(): 1} if len(u) == 1: return {(u[0],): 1} @@ -2293,21 +2297,25 @@ def decompose_into_generators(self, u): w = u[1:] # so CpC_s * CpC_w = CpC_u + lower order terms # get the lower order terms ("sum_term") - sum_term = self(0) + sum_term = {} between = self._W_Coxeter3.bruhat_interval([], w) + R = self.base_ring() for v in between: # Get (coxeter3-implemented) group element corresponding to v v_elt = self._W_Coxeter3(v) if v_elt.has_left_descent(s): # Compute mu-coefficient via coxeter3 - sum_term += self.base_ring()(v.mu_coefficient(w)) * self.monomial(v_elt) + coeff = R(v.mu_coefficient(w)) + if coeff: + sum_term[v_elt] = coeff # recursion: decompose C'_s * C'_w and the lower order terms - result = {(s,) + gens: coeff for (gens, coeff) in self.decompose_into_generators(w).items()} - for (z, c1) in sum_term: + result = {(s,) + gens: coeff for (gens, coeff) in self._decompose_into_generators(w).items()} + zero = R.zero() + for (z, c1) in sum_term.items(): # Subtract off each term from sum_term. - for (gens, c2) in self.decompose_into_generators(z).items(): - result[gens] = result.get(gens, 0) - c1*c2 + for (gens, c2) in self._decompose_into_generators(z).items(): + result[gens] = result.get(gens, zero) - c1 * c2 return result diff --git a/src/sage/categories/coxeter_groups.py b/src/sage/categories/coxeter_groups.py index b1c3aab33fb..19be6f43df2 100644 --- a/src/sage/categories/coxeter_groups.py +++ b/src/sage/categories/coxeter_groups.py @@ -694,16 +694,16 @@ def kazhdan_lusztig_cells(self, side='left'): Compute the left, right, or two-sided Kazhdan-Lusztig cells of ``self`` if ``self`` is finite. - The cells are computed by using - :func:`kazhdan_lusztig_cell()`. + The cells are computed by using :func:`kazhdan_lusztig_cell() + `. + As detailed there, installation of the optional package ``coxeter3`` - is strongly recommended (though not required) before using this - function. + is recommended (though not required) before using this function. INPUT: - - ``side`` -- ``'left'``, ``'right'``, or ``'two-sided'`` (default: - ``'left'``) + - ``side`` -- (default: ``'left'``) either ``'left'``, + ``'right'``, or ``'two-sided'`` EXAMPLES: @@ -717,41 +717,60 @@ def kazhdan_lusztig_cells(self, side='left'): the package is installed, even if the group is not created with the 'coxeter3' implementation. - sage: from sage.doctest.fixtures import reproducible_repr # optional - coxeter3 - sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 - sage: print(reproducible_repr(W.kazhdan_lusztig_cells())) # optional - coxeter3 - set([frozenset([[1, 2, 1, 3, 2, 1]]), - frozenset([[1, 2, 1, 3, 2], [1, 2, 3, 2], [2, 3, 2]]), - frozenset([[1, 2, 1, 3], [1, 2, 3, 2, 1], [2, 3, 2, 1]]), - frozenset([[1, 2, 1], [1, 3, 2, 1], [2, 1, 3, 2, 1]]), - frozenset([[1, 2, 3], [2, 3], [3]]), - frozenset([[1, 2], [2], [3, 2]]), - frozenset([[1, 3, 2], [2, 1, 3, 2]]), - frozenset([[1, 3], [2, 1, 3]]), - frozenset([[1], [2, 1], [3, 2, 1]]), - frozenset([[]])]) - sage: W = CoxeterGroup('A3', implementation='permutation') # optional - coxeter3 - sage: print(reproducible_repr(W.kazhdan_lusztig_cells())) # optional - coxeter3 - set([frozenset([()]), - frozenset([(1,10,2)(3,5,6)(4,8,7)(9,11,12), (1,4)(2,8)(3,5)(7,10)(9,11), (1,4,6)(2,3,11)(5,8,9)(7,10,12)]), - frozenset([(1,10,9,5)(2,6,8,12)(3,11,7,4), (1,3)(2,12)(4,10)(5,11)(6,8)(7,9)]), - frozenset([(1,11)(3,10)(4,9)(5,7)(6,12), (1,11,8)(2,7,5)(3,4,12)(6,9,10), (1,5,12)(2,9,4)(3,10,8)(6,7,11)]), - ... - frozenset([(1,9)(2,8)(3,7)(4,11)(5,10)(6,12)])]) + :: + + sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 + sage: KL_cells = W.kazhdan_lusztig_cells() # optional - coxeter3 + sage: set([tuple(sorted(C)) for C in KL_cells]) # optional - coxeter3 + {([],), + ([1], [2, 1], [3, 2, 1]), + ([1, 2], [2], [3, 2]), + ([1, 2, 1], [1, 3, 2, 1], [2, 1, 3, 2, 1]), + ([1, 2, 1, 3], [1, 2, 3, 2, 1], [2, 3, 2, 1]), + ([1, 2, 1, 3, 2], [1, 2, 3, 2], [2, 3, 2]), + ([1, 2, 1, 3, 2, 1],), + ([1, 2, 3], [2, 3], [3]), + ([1, 3], [2, 1, 3]), + ([1, 3, 2], [2, 1, 3, 2])} + sage: len(KL_cells) + 10 - Computing the left cells in `B_4` takes about 45 seconds:: + sage: W = CoxeterGroup('A3', implementation='permutation') # optional - coxeter3 + sage: len(W.kazhdan_lusztig_cells()) # optional - coxeter3 + 10 - sage: W = CoxeterGroup('B4', implementation='coxeter3') # optional - coxeter3 - sage: b4_cells = W.kazhdan_lusztig_cells() # long time (45 seconds) # optional - coxeter3 - sage: len(b4_cells) # optional - coxeter3 - 50 - sage: print(reproducible_repr(b4_cells)) # optional - coxeter3 - set([frozenset([[1, 2, 3, 4, 3, 2, 1], [1], [2, 1], [2, 3, 4, 3, 2, 1], [3, 2, 1], [3, 4, 3, 2, 1], [4, 3, 2, 1]]), - frozenset([[1, 2, 3, 4, 3, 2], [1, 2], [2, 3, 4, 3, 2], [2], [3, 2], [3, 4, 3, 2], [4, 3, 2]]), - frozenset([[1, 2, 3, 4, 3], [1, 2, 3], [2, 3, 4, 3], [2, 3], [3, 4, 3], [3], [4, 3]]), - frozenset([[1, 2, 3, 4], [2, 3, 4], [3, 4], [4, 3, 4], [4]]), - ... - frozenset([[]])]) + Computing the two sided cells in `B_3`:: + + sage: W = CoxeterGroup('B3', implementation='coxeter3') # optional - coxeter3 + sage: b3_cells = W.kazhdan_lusztig_cells('two-sided') # optional - coxeter3 + sage: len(b3_cells) # optional - coxeter3 + 6 + sage: set([tuple(sorted(C)) for C in W.kazhdan_lusztig_cells()]) # optional - coxeter3 + {([],), + ([1], [1, 2, 3, 2, 1], [2, 1], [2, 3, 2, 1], [3, 2, 1]), + ([1, 2], [1, 2, 3, 2], [2], [2, 3, 2], [3, 2]), + ([1, 2, 3], [2, 3], [3], [3, 2, 3]), + ([2, 1, 2], [2, 3, 2, 1, 2], [3, 2, 1, 2]), + ([2, 1, 2, 3], [2, 3, 2, 1, 2, 3], [3, 2, 1, 2, 3]), + ([2, 1, 2, 3, 2], [2, 3, 2, 1, 2, 3, 2], [3, 2, 1, 2, 3, 2]), + ([2, 1, 2, 3, 2, 1], + [2, 3, 2, 1, 2, 3, 2, 1], + [3, 2, 1, 2, 3, 2, 1], + [3, 2, 3, 2, 1, 2]), + ([2, 3, 1], [3, 1], [3, 2, 3, 1]), + ([2, 3, 1, 2], [3, 1, 2], [3, 2, 3, 1, 2]), + ([2, 3, 1, 2, 3], [3, 1, 2, 3], [3, 2, 3, 1, 2, 3]), + ([2, 3, 1, 2, 3, 2], + [3, 1, 2, 3, 2], + [3, 2, 3, 1, 2, 3, 2], + [3, 2, 3, 2], + [3, 2, 3, 2, 1, 2, 3, 2]), + ([2, 3, 1, 2, 3, 2, 1], + [3, 1, 2, 3, 2, 1], + [3, 2, 3, 1, 2, 3, 2, 1], + [3, 2, 3, 2, 1], + [3, 2, 3, 2, 1, 2, 3]), + ([3, 2, 3, 2, 1, 2, 3, 2, 1],)} TESTS:: @@ -2781,13 +2800,13 @@ def kazhdan_lusztig_cell(self, side='left'): Let `C'` denote the Kazhdan-Lusztig `C^{\prime}`-basis of the Iwahori-Hecke algebra `H` of a Coxeter system `(W,S)`. Two elements `x,y` of the Coxeter group `W` are said to lie in the same left - Kazhdan-Lusztig cell if there exist sequences `x=w_1, w_2, ..., - w_k=y` and `y=u_1, u_2, ..., u_l=x` such that for all `1 \leq i < k` - and all `1 \leq j < l`, there exist some Coxeter generators `s,t \in - S` for which `C'_{w_{i+1}}` appears in `C'_sC'_{w_i}` and - `C'_{u_{j+1}}` appears in `C'_sC'_{u_j}` in `H`. Right and - two-sided Kazhdan-Lusztig cells of `W` are defined similarly; see - [Lus2013]_. + Kazhdan-Lusztig cell if there exist sequences `x = w_1, w_2, \ldots, + w_k = y` and `y = u_1, u_2, \ldots, u_l = x` such that for all + `1 \leq i < k` and all `1 \leq j < l`, there exist some Coxeter + generators `s,t \in S` for which `C'_{w_{i+1}}` appears in + `C'_s C'_{w_i}` and `C'_{u_{j+1}}` appears in `C'_s C'_{u_j}` + in `H`. Right and two-sided Kazhdan-Lusztig cells of `W` are + defined similarly; see [Lus2013]_. In this function, we compute products in the `C^{\prime}` basis by using :class:`IwahoriHeckeAlgebra.Cp`. As mentioned in that class, @@ -2798,10 +2817,10 @@ def kazhdan_lusztig_cell(self, side='left'): INPUT: - - ``w`` -- an element of self. + - ``w`` -- an element of ``self`` - - ``side`` -- ``'left'``, ``'right'``, or ``'two-sided'`` (default: - ``'left'``), corresponding to the kind of cell to compute. + - ``side`` -- (default: ``'left'``) the kind of cell to compute; + must be either ``'left'``, ``'right'``, or ``'two-sided'`` EXAMPLES: @@ -2811,40 +2830,31 @@ def kazhdan_lusztig_cell(self, side='left'): the output cell but not the method used for the cell computation. In particular, the cell computation uses the optional package ``coxeter3`` in the background as long as the package is installed, - even in the default ('reflection') and 'permutation' - implementations:: + even in the different implementations implementations:: - sage: W = CoxeterGroup('A3') # optional - coxeter3 + sage: W = WeylGroup('A3', prefix='s') # optional - coxeter3 sage: s1,s2,s3 = W.simple_reflections() # optional - coxeter3 sage: s1.kazhdan_lusztig_cell() # optional - coxeter3 - {[-1 1 0] - [-1 0 1] - [-1 0 0], - [-1 1 0] - [-1 0 1] - [ 0 0 1], - [-1 1 0] - [ 0 1 0] - [ 0 0 1]} + {s3*s2*s1, s2*s1, s1} sage: W = CoxeterGroup('A3', implementation='permutation') # optional - coxeter3 sage: s1,s2,s3 = W.simple_reflections() # optional - coxeter3 sage: s1.kazhdan_lusztig_cell() # optional - coxeter3 {(1,2,3,12)(4,5,10,11)(6,7,8,9), (1,2,10)(3,6,5)(4,7,8)(9,12,11), (1,7)(2,4)(5,6)(8,10)(11,12)} - sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 - sage: s1,s2,s3 = W.simple_reflections() # optional - coxeter3 - sage: s1.kazhdan_lusztig_cell() # optional - coxeter3 + sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 + sage: s1,s2,s3 = W.simple_reflections() # optional - coxeter3 + sage: s1.kazhdan_lusztig_cell() # optional - coxeter3 {[1], [2, 1], [3, 2, 1]} Next, we compute a right cell and a two-sided cell in `A_3`:: - sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 - sage: s1,s2,s3 = W.simple_reflections() # optional - coxeter3 + sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 + sage: s1,s2,s3 = W.simple_reflections() # optional - coxeter3 sage: w = s1*s3 - sage: w.kazhdan_lusztig_cell(side='right') # optional - coxeter3 + sage: w.kazhdan_lusztig_cell(side='right') # optional - coxeter3 {[1, 3], [1, 3, 2]} - sage: w.kazhdan_lusztig_cell(side='two-sided') # optional - coxeter3 + sage: w.kazhdan_lusztig_cell(side='two-sided') # optional - coxeter3 {[1, 3], [1, 3, 2], [2, 1, 3], [2, 1, 3, 2]} Some slightly longer computations in `B_4`:: @@ -2868,7 +2878,7 @@ def kazhdan_lusztig_cell(self, side='left'): [2, 3, 4, 1, 2, 3, 4], [2, 3, 4, 3, 1], [2, 3, 4, 3, 1, 2], - ... + ... [4, 3, 4, 2, 3, 4, 1, 2, 3, 4]} """ from sage.algebras.iwahori_hecke_algebra import IwahoriHeckeAlgebra @@ -2905,3 +2915,4 @@ def kazhdan_lusztig_cell(self, side='left'): g = DiGraph([list(vertices), list(edges)]) return set(g.strongly_connected_component_containing_vertex(w)) + From 3cff1f67b580ef0e24f12a8a48c735f2050d20be Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Mon, 16 Aug 2021 11:46:44 +1000 Subject: [PATCH 103/359] More reviewer changes to make tests and all test pass when coxeter3 is not installed. --- src/sage/algebras/iwahori_hecke_algebra.py | 1 - src/sage/categories/coxeter_groups.py | 82 +++++++++++++++------- 2 files changed, 56 insertions(+), 27 deletions(-) diff --git a/src/sage/algebras/iwahori_hecke_algebra.py b/src/sage/algebras/iwahori_hecke_algebra.py index 4e64e3bfe90..37bc7a2c789 100644 --- a/src/sage/algebras/iwahori_hecke_algebra.py +++ b/src/sage/algebras/iwahori_hecke_algebra.py @@ -37,7 +37,6 @@ from sage.combinat.root_system.coxeter_group import CoxeterGroup from sage.combinat.family import Family from sage.combinat.free_module import CombinatorialFreeModule -from sage.libs.coxeter3.coxeter_group import CoxeterGroup as Coxeter3Group def normalized_laurent_polynomial(R, p): diff --git a/src/sage/categories/coxeter_groups.py b/src/sage/categories/coxeter_groups.py index 19be6f43df2..a2fc2dda186 100644 --- a/src/sage/categories/coxeter_groups.py +++ b/src/sage/categories/coxeter_groups.py @@ -698,7 +698,8 @@ def kazhdan_lusztig_cells(self, side='left'): `. As detailed there, installation of the optional package ``coxeter3`` - is recommended (though not required) before using this function. + is recommended (though not required) before using this function + as it speeds up the computation. INPUT: @@ -707,21 +708,48 @@ def kazhdan_lusztig_cells(self, side='left'): EXAMPLES: - We compute the left cells in the Coxeter group of type `A_3` below. - Note that each Coxeter group may be created with multiple + We compute the right cells in the Coxeter group of type `A_2` + below. Note that each Coxeter group may be created with multiple implementations, namely, 'reflection' (default), 'permutation', 'matrix', or 'coxeter3'. The choice of implementation affects the representation of elements in the output cells but not the method - used for the cell computation. In particular, the cell computation - uses the optional package ``coxeter3`` in the background as long as - the package is installed, even if the group is not created with the - 'coxeter3' implementation. + used for the cell computation. + + sage: W = CoxeterGroup('A2') + sage: KL_cells = W.kazhdan_lusztig_cells(side='right') + sage: set([tuple(sorted(C, key=lambda w: w.reduced_word())) + ....: for C in KL_cells]) + {( + [-1 1] [ 0 -1] + [ 0 1], [ 1 -1] + ), + ( + [ 0 -1] + [-1 0] + ), + ( + [1 0] + [0 1] + ), + ( + [ 1 0] [-1 1] + [ 1 -1], [-1 0] + )} + sage: len(KL_cells) + 4 - :: + sage: W = CoxeterGroup('A2', implementation='permutation') + sage: len(W.kazhdan_lusztig_cells(side='right')) + 4 - sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 - sage: KL_cells = W.kazhdan_lusztig_cells() # optional - coxeter3 - sage: set([tuple(sorted(C)) for C in KL_cells]) # optional - coxeter3 + We compute the left cells in the Coxeter group of type `A_3` + below. If the optional package ``coxeter3`` is installed, it + runs in the background even if the group is not created with + the ``'coxeter3'`` implementation. :: + + sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 + sage: KL_cells = W.kazhdan_lusztig_cells() # optional - coxeter3 + sage: set([tuple(sorted(C)) for C in KL_cells]) # optional - coxeter3 {([],), ([1], [2, 1], [3, 2, 1]), ([1, 2], [2], [3, 2]), @@ -732,7 +760,7 @@ def kazhdan_lusztig_cells(self, side='left'): ([1, 2, 3], [2, 3], [3]), ([1, 3], [2, 1, 3]), ([1, 3, 2], [2, 1, 3, 2])} - sage: len(KL_cells) + sage: len(KL_cells) # optional - coxeter3 10 sage: W = CoxeterGroup('A3', implementation='permutation') # optional - coxeter3 @@ -2810,8 +2838,8 @@ def kazhdan_lusztig_cell(self, side='left'): In this function, we compute products in the `C^{\prime}` basis by using :class:`IwahoriHeckeAlgebra.Cp`. As mentioned in that class, - installing the optional package ``coxeter3`` is strongly recommended - (though not required) before using this function, because the + installing the optional package ``coxeter3`` is recommended + (though not required) before using this function because the package speeds up product computations that are sometimes computationally infeasible without it. @@ -2827,21 +2855,23 @@ def kazhdan_lusztig_cell(self, side='left'): We compute the left cell of the generator `s_1` in type `A_3` in three different implementations of the Coxeter group. Note that the choice of implementation affects the representation of elements in - the output cell but not the method used for the cell computation. In - particular, the cell computation uses the optional package - ``coxeter3`` in the background as long as the package is installed, - even in the different implementations implementations:: + the output cell but not the method used for the cell computation. - sage: W = WeylGroup('A3', prefix='s') # optional - coxeter3 - sage: s1,s2,s3 = W.simple_reflections() # optional - coxeter3 - sage: s1.kazhdan_lusztig_cell() # optional - coxeter3 - {s3*s2*s1, s2*s1, s1} - sage: W = CoxeterGroup('A3', implementation='permutation') # optional - coxeter3 - sage: s1,s2,s3 = W.simple_reflections() # optional - coxeter3 - sage: s1.kazhdan_lusztig_cell() # optional - coxeter3 + sage: W = CoxeterGroup('A3', implementation='permutation') + sage: s1,s2,s3 = W.simple_reflections() + sage: s1.kazhdan_lusztig_cell() {(1,2,3,12)(4,5,10,11)(6,7,8,9), (1,2,10)(3,6,5)(4,7,8)(9,12,11), (1,7)(2,4)(5,6)(8,10)(11,12)} + + The cell computation uses the optional package ``coxeter3`` in + the background if available to speed up the computation, + even in the different implementations implementations:: + + sage: W = WeylGroup('A3', prefix='s') # optional - coxeter3 + sage: s1,s2,s3 = W.simple_reflections() # optional - coxeter3 + sage: s1.kazhdan_lusztig_cell() # optional - coxeter3 + {s3*s2*s1, s2*s1, s1} sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 sage: s1,s2,s3 = W.simple_reflections() # optional - coxeter3 sage: s1.kazhdan_lusztig_cell() # optional - coxeter3 @@ -2851,7 +2881,7 @@ def kazhdan_lusztig_cell(self, side='left'): sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 sage: s1,s2,s3 = W.simple_reflections() # optional - coxeter3 - sage: w = s1*s3 + sage: w = s1 * s3 # optional - coxeter3 sage: w.kazhdan_lusztig_cell(side='right') # optional - coxeter3 {[1, 3], [1, 3, 2]} sage: w.kazhdan_lusztig_cell(side='two-sided') # optional - coxeter3 From 901699badeb305cdfbbfd52cc8427a3ea53512b8 Mon Sep 17 00:00:00 2001 From: Chase Meadors Date: Mon, 16 Aug 2021 17:24:30 -0600 Subject: [PATCH 104/359] Fix kazhdan_lusztig_cell[s] documentation --- src/sage/categories/coxeter_groups.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sage/categories/coxeter_groups.py b/src/sage/categories/coxeter_groups.py index a2fc2dda186..70a20541ed7 100644 --- a/src/sage/categories/coxeter_groups.py +++ b/src/sage/categories/coxeter_groups.py @@ -713,7 +713,7 @@ def kazhdan_lusztig_cells(self, side='left'): implementations, namely, 'reflection' (default), 'permutation', 'matrix', or 'coxeter3'. The choice of implementation affects the representation of elements in the output cells but not the method - used for the cell computation. + used for the cell computation:: sage: W = CoxeterGroup('A2') sage: KL_cells = W.kazhdan_lusztig_cells(side='right') @@ -745,7 +745,7 @@ def kazhdan_lusztig_cells(self, side='left'): We compute the left cells in the Coxeter group of type `A_3` below. If the optional package ``coxeter3`` is installed, it runs in the background even if the group is not created with - the ``'coxeter3'`` implementation. :: + the ``'coxeter3'`` implementation:: sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 sage: KL_cells = W.kazhdan_lusztig_cells() # optional - coxeter3 @@ -2855,7 +2855,7 @@ def kazhdan_lusztig_cell(self, side='left'): We compute the left cell of the generator `s_1` in type `A_3` in three different implementations of the Coxeter group. Note that the choice of implementation affects the representation of elements in - the output cell but not the method used for the cell computation. + the output cell but not the method used for the cell computation:: sage: W = CoxeterGroup('A3', implementation='permutation') sage: s1,s2,s3 = W.simple_reflections() From 475e60598370ccf3196f13b2a7f9722fcc69e56c Mon Sep 17 00:00:00 2001 From: dcoudert Date: Sun, 5 Sep 2021 12:01:45 +0200 Subject: [PATCH 105/359] trac #17537: geodesic closure in Cython --- src/sage/graphs/convexity_properties.pyx | 203 ++++++++++++++++++++++- src/sage/graphs/graph.py | 4 +- 2 files changed, 201 insertions(+), 6 deletions(-) diff --git a/src/sage/graphs/convexity_properties.pyx b/src/sage/graphs/convexity_properties.pyx index 3fea9e872d1..ca73f4b21e2 100644 --- a/src/sage/graphs/convexity_properties.pyx +++ b/src/sage/graphs/convexity_properties.pyx @@ -1,3 +1,4 @@ +# cython: binding=True r""" Convexity properties of graphs @@ -11,6 +12,7 @@ the following methods: :meth:`ConvexityProperties.hull` | Return the convex hull of a set of vertices :meth:`ConvexityProperties.hull_number` | Compute the hull number of a graph and a corresponding generating set + :meth:`geodetic_closure`| Return the geodetic closure of a set of vertices These methods can be used through the :class:`ConvexityProperties` object returned by :meth:`Graph.convexity_properties`. @@ -23,12 +25,16 @@ Methods ------- """ -############################################################################## +# **************************************************************************** # Copyright (C) 2011 Nathann Cohen -# Distributed under the terms of the GNU General Public License (GPL) -# The full text of the GPL is available at: -# http://www.gnu.org/licenses/ -############################################################################## +# 2021 David Coudert +# +# 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. +# https://www.gnu.org/licenses/ +# **************************************************************************** from sage.data_structures.binary_matrix cimport * from sage.numerical.backends.generic_backend cimport GenericBackend @@ -36,6 +42,13 @@ from sage.numerical.backends.generic_backend import get_solver from sage.graphs.distances_all_pairs cimport c_distances_all_pairs from cysignals.memory cimport sig_free from cysignals.signals cimport sig_on, sig_off +from memory_allocator cimport MemoryAllocator +from libc.stdint cimport uint32_t +from sage.graphs.base.static_sparse_graph cimport (short_digraph, + init_short_digraph, + free_short_digraph, + out_degree, + simple_BFS) cdef class ConvexityProperties: r""" @@ -476,3 +489,183 @@ cdef class ConvexityProperties: constraint.append(i) return self._integers_to_vertices(constraint) + + +def geodetic_closure(G, S): + r""" + Return the geodetic closure of the set of vertices `S` in `G`. + + The geodetic closure `g(S)` of a subset of vertices `S` of a graph `G` is in + [HLT1993]_ as the set of all vertices that lie on a shortest `u-v` path for + any pair of vertices `u,v \in S`. We assume that `g(\emptyset) = \emptyset` + and that `g(\{u\}) = \{u\}` for any `u` in `G`. + + .. WARNING:: + + This operation is **not** a closure function. Indeed, a closure function + must satisfy the property that `f(f(X))` should be equal to `f(X)`, + which is not always the case here. The term ``closure`` is used here to + follow the terminology of the domain. See for instance [HLT1993]_. + + Here, we implement a simple algorithm to determine this set. Roughly, for + each vertex `u \in S`, the algorithm first performs a breadth first search + from `u` to get distances, and then identifies the vertices of `G` lying on + a shortest path from `u` to any `v\in S` using a reversal traversal from + vertices in `S`. This algorithm has time complexity in `O(|S|(n + m))` and + space complexity in `O(n + m)`. + + INPUT: + + - ``G`` -- a Sage graph + + - ``S`` -- a subset of vertices of `G` + + EXAMPLES: + + The vertices of the Petersen graph can be obtained by a geodetic closure of + four of its vertices:: + + sage: from sage.graphs.convexity_properties import geodetic_closure + sage: G = graphs.PetersenGraph() + sage: geodetic_closure(G, [0, 2, 8, 9]) + [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] + + The vertices of a 2D grid can be obtained by a geodetic closure of + two vertices:: + + sage: G = graphs.Grid2dGraph(4, 4) + sage: c = G.geodetic_closure([(0, 0), (3, 3)]) + sage: len(c) == G.order() + True + + If two vertices belong to different connected components of a graph, their + geodetic closure is trivial:: + + sage: G = Graph([(0, 1), (2, 3)]) + sage: geodetic_closure(G, [0, 2]) + [0, 2] + + The geodetic closure does not satisfy the closure function property that + `f(f(X))` should be equal to `f(X)`:: + + sage: G = graphs.DiamondGraph() + sage: G.subdivide_edge((1, 2), 1) + sage: geodetic_closure(G, [0, 3]) + [0, 1, 2, 3] + sage: geodetic_closure(G, geodetic_closure(G, [0, 3])) + [0, 1, 2, 3, 4] + + TESTS:: + + sage: G = graphs.DiamondGraph() + sage: geodetic_closure(G, []) + [] + sage: geodetic_closure(G, [1]) + [1] + sage: S = geodetic_closure(G, list(G)) + sage: all(u in G for u in S) and len(S) == G.order() + True + sage: S = geodetic_closure(G, G) + sage: all(u in G for u in S) and len(S) == G.order() + True + sage: geodetic_closure(G, [1, 'foo']) + Traceback (most recent call last): + ... + ValueError: S is not a subset of vertices of the graph + """ + S = list(S) + if not S: + return [] + elif any(v not in G for v in S): + raise ValueError("S is not a subset of vertices of the graph") + elif len(S) == 1 or len(S) == G.order(): + return S + elif not G.is_connected(): + L = [] + for g in G.connected_components_subgraphs(): + Sg = [u for u in S if u in g] + L.extend(geodetic_closure(g, Sg)) + return L + + cdef int n = G.order() + cdef int nS = len(S) + cdef list int_to_vertex = list(G) + cdef dict vertex_to_int = {u: i for i, u in enumerate(int_to_vertex)} + cdef list S_int = [vertex_to_int[u] for u in S] + + # Copy the graph has a short digraph + cdef short_digraph sd + init_short_digraph(sd, G, edge_labelled=False, vertex_list=int_to_vertex) + + # Allocate some data structures + cdef MemoryAllocator mem = MemoryAllocator() + cdef uint32_t * distances = mem.malloc(n * sizeof(uint32_t)) + cdef uint32_t * waiting_list = mem.malloc(n * sizeof(uint32_t)) + if not distances or not waiting_list: + free_short_digraph(sd) + raise MemoryError() + cdef bitset_t seen + cdef bitset_t visited + cdef bitset_t closure + bitset_init(seen, n) + bitset_init(visited, n) + bitset_init(closure, n) + + cdef int ui, vi, xi, yi, i_begin, i_end, i, j, k + + # Vertices in S are in the closure + bitset_clear(closure) + for ui in S_int: + bitset_add(closure, ui) + + # We now explore geodesics between vertices in S, and we avoid visiting + # twice the geodesics between u and v + for i in range(nS - 1): + ui = S_int[i] + + # Compute distances from ui using BFS + _ = simple_BFS(sd, ui, distances, NULL, waiting_list, seen) + + # Perform a reverse BFS from vertices in S, following only vertices + # along a shortest path from ui to identify vertices of the geodetic + # closure. + bitset_clear(visited) + i_begin = 0 + i_end = 0 + for j in range(i + 1, nS): + vi = S_int[j] + if not bitset_in(seen, vi) or bitset_in(visited, vi): + # vi is not reachable from ui using BFS or has already been + # considered for the geodetic closure from ui + continue + + # We explore all vertices on a shortest path from ui to vi + waiting_list[i_end] = vi + i_end += 1 + bitset_add(visited, vi) + + while i_begin < i_end: + xi = waiting_list[i_begin] + i_begin += 1 + + for k in range(out_degree(sd, xi)): + yi = sd.neighbors[xi][k] + if distances[xi] == distances[yi] + 1: + # yi in on a shortest path to ui + if not bitset_in(visited, yi): + waiting_list[i_end] = yi + i_end += 1 + bitset_add(visited, yi) + + # Now, visited contains all vertices on geodesics from ui to any other + # vertex in S + bitset_union(closure, closure, visited) + + cdef list ret = [int_to_vertex[ui] for ui in range(n) if bitset_in(closure, ui)] + + bitset_free(seen) + bitset_free(visited) + bitset_free(closure) + free_short_digraph(sd) + + return ret diff --git a/src/sage/graphs/graph.py b/src/sage/graphs/graph.py index b1fbb941e84..6022024ae19 100644 --- a/src/sage/graphs/graph.py +++ b/src/sage/graphs/graph.py @@ -9389,6 +9389,7 @@ def bipartite_double(self, extended=False): from sage.graphs.connectivity import is_triconnected from sage.graphs.comparability import is_comparability from sage.graphs.comparability import is_permutation + from sage.graphs.convexity_properties import geodetic_closure from sage.graphs.domination import is_dominating from sage.graphs.domination import is_redundant from sage.graphs.domination import private_neighbors @@ -9441,7 +9442,8 @@ def bipartite_double(self, extended=False): "edge_isoperimetric_number" : "Expansion properties", "vertex_isoperimetric_number" : "Expansion properties", "fractional_chromatic_number" : "Coloring", - "fractional_chromatic_index" : "Coloring" + "fractional_chromatic_index" : "Coloring", + "geodetic_closure" : "Leftovers" } __doc__ = __doc__.replace("{INDEX_OF_METHODS}",gen_thematic_rest_table_index(Graph,_additional_categories)) From 8bac3324636f074cd6439b962d86e5592c866f45 Mon Sep 17 00:00:00 2001 From: dcoudert Date: Sun, 5 Sep 2021 12:17:01 +0200 Subject: [PATCH 106/359] trac #17537: prevent calling this method on digraphs --- src/sage/graphs/convexity_properties.pyx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/sage/graphs/convexity_properties.pyx b/src/sage/graphs/convexity_properties.pyx index ca73f4b21e2..19c1224cab3 100644 --- a/src/sage/graphs/convexity_properties.pyx +++ b/src/sage/graphs/convexity_properties.pyx @@ -572,7 +572,13 @@ def geodetic_closure(G, S): Traceback (most recent call last): ... ValueError: S is not a subset of vertices of the graph + sage: geodetic_closure(digraphs.Path(3), [0, 1]) + Traceback (most recent call last): + ... + NotImplementedError: the geodetic closure of digraphs has not been implemented yet """ + if G.is_directed(): + raise NotImplementedError("the geodetic closure of digraphs has not been implemented yet") S = list(S) if not S: return [] From 2f5be2d0bd3a77bc132c3cd18b90238d96c2164d Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 10 Sep 2021 19:45:59 -0700 Subject: [PATCH 107/359] configure.ac, build/pkgs/python3/spkg-configure.m4: New default --with-sage-venv=auto --- build/pkgs/python3/spkg-configure.m4 | 11 +++++++++++ configure.ac | 7 +++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/build/pkgs/python3/spkg-configure.m4 b/build/pkgs/python3/spkg-configure.m4 index 9ebcdf77fa9..0134ace054a 100644 --- a/build/pkgs/python3/spkg-configure.m4 +++ b/build/pkgs/python3/spkg-configure.m4 @@ -119,6 +119,17 @@ To build Sage with a different system python, use ./configure --with-python=/pat ]) AC_SUBST([PYTHON_FOR_VENV]) + AS_VAR_IF([SAGE_VENV], [auto], [SAGE_VENV=$SAGE_VENV_AUTO]) + AS_CASE([$SAGE_VENV], + [no], [SAGE_VENV='${SAGE_LOCAL}'],dnl Quoted so that it is resolved at build time by shell/Makefile + [yes], [AS_IF([test -n "$PYTHON_FOR_VENV"], [ + PYTHON_VERSION=$("$PYTHON_FOR_VENV" -c "import sysconfig; print(sysconfig.get_python_version())") + ], [ + PYTHON_VERSION=$(echo $(cat build/pkgs/python3/package-version.txt)) + ]) + SAGE_VENV='${SAGE_LOCAL}'/var/lib/sage/venv-python$PYTHON_VERSION] + ) + dnl These temporary directories are created by the check above dnl and need to be cleaned up to prevent the "rm -f conftest*" dnl (that a bunch of other checks do) from emitting warnings about diff --git a/configure.ac b/configure.ac index 7156bf4aecf..83323ce3ce2 100644 --- a/configure.ac +++ b/configure.ac @@ -70,15 +70,18 @@ SAGE_LOCAL="$prefix" # This is nonstandard. if test "$SAGE_LOCAL" = NONE; then SAGE_LOCAL=local + SAGE_VENV_AUTO=yes +else + SAGE_VENV_AUTO=no fi SAGE_SRC="$SAGE_ROOT/src" SAGE_SPKG_INST="$SAGE_LOCAL/var/lib/sage/installed" AC_ARG_WITH([sage-venv], - [AS_HELP_STRING([--with-sage-venv=SAGE_VENV], + [AS_HELP_STRING([--with-sage-venv={auto,yes,no,SAGE_VENV}], [put Python packages into an installation hierarchy separate from prefix])], [SAGE_VENV="$withval"], - [SAGE_VENV='${SAGE_LOCAL}'])dnl Quoted so that it is resolved at build time by shell/Makefile + [SAGE_VENV="auto"]) AC_SUBST([SAGE_VENV]) #--------------------------------------------------------- From f70064047c24f2ffffcdd2b4bae4aee5d8cca7c2 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 10 Sep 2021 20:18:09 -0700 Subject: [PATCH 108/359] configure.ac: In config.status, create convenience symlinks prefix, venv --- configure.ac | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/configure.ac b/configure.ac index 83323ce3ce2..6fb3b740511 100644 --- a/configure.ac +++ b/configure.ac @@ -492,6 +492,27 @@ AC_CONFIG_COMMANDS(mkdirs, SAGE_INST="$SAGE_SPKG_INST" ]) +AC_CONFIG_COMMANDS(links, [ + dnl Create links for the convenience of users + SYMLINK="${ac_top_build_prefix}prefix" + AS_IF([test -L "$SYMLINK" -o ! -e "$SYMLINK"], [ + AC_MSG_NOTICE([creating convenience symlink $SYMLINK -> $SAGE_LOCAL]) + ln -sf "$SAGE_LOCAL" "$SYMLINK" + ], [ + AC_MSG_NOTICE([cannot create convenience symlink $SYMLINK -> $SAGE_LOCAL because the file exists and is not a symlink; this is harmless]) + ]) + SYMLINK="${ac_top_build_prefix}venv" + AS_IF([test -L "$SYMLINK" -o ! -e "$SYMLINK"], [ + AC_MSG_NOTICE([creating convenience symlink $SYMLINK -> $SAGE_VENV]) + ln -sf "$SAGE_VENV" "$SYMLINK" + ], [ + AC_MSG_NOTICE([cannot create convenience symlink $SYMLINK -> $SAGE_VENV because the file exists and is not a symlink; this is harmless]) + ]) +], [ + SAGE_LOCAL="$SAGE_LOCAL" + eval SAGE_VENV="$SAGE_VENV"dnl eval so as to evaluate the embedded ${SAGE_LOCAL} +]) + AC_OUTPUT() SAGE_SYSTEM_PACKAGE_NOTICE() From b4a3845dc3f61f0547c890aa1a81b1d212c648a4 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 15 Sep 2021 16:38:17 -0700 Subject: [PATCH 109/359] m4/sage_spkg_collect.m4: If we install python3 spkg, install it in SAGE_VENV --- m4/sage_spkg_collect.m4 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/m4/sage_spkg_collect.m4 b/m4/sage_spkg_collect.m4 index 1ab62d6fa47..30848c33c40 100644 --- a/m4/sage_spkg_collect.m4 +++ b/m4/sage_spkg_collect.m4 @@ -153,8 +153,8 @@ for DIR in $SAGE_ROOT/build/pkgs/*; do dnl Jupyter notebook, then packages such as jupyter_core would have to be installed into dnl two trees. SPKG_TREE_VAR=SAGE_LOCAL - if test -f "$DIR/requirements.txt" -o -f "$DIR/install-requires.txt"; then - dnl A Python package + if test -f "$DIR/requirements.txt" -o -f "$DIR/install-requires.txt" -o "$SPKG_NAME" = python3; then + dnl A Python package or spkg installation of python3 itself SPKG_TREE_VAR=SAGE_VENV fi SAGE_PACKAGE_TREES="${SAGE_PACKAGE_TREES}$(printf '\ntrees_')${SPKG_NAME} = ${SPKG_TREE_VAR}" From 12cbbdaaf45b96b9cf680d544d0b268afd6b4258 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 15 Sep 2021 16:44:31 -0700 Subject: [PATCH 110/359] configure.ac: Keep old behavior of SAGE_VENV in incremental builds --- configure.ac | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 6fb3b740511..be53bf20960 100644 --- a/configure.ac +++ b/configure.ac @@ -70,7 +70,13 @@ SAGE_LOCAL="$prefix" # This is nonstandard. if test "$SAGE_LOCAL" = NONE; then SAGE_LOCAL=local - SAGE_VENV_AUTO=yes + if test -x "$SAGE_LOCAL"/bin/python3; then + # Incremental build with an existing installation of python3 spkg + # in SAGE_LOCAL or venv in SAGE_LOCAL. Keep old behavior. + SAGE_VENV_AUTO=no + else + SAGE_VENV_AUTO=yes + fi else SAGE_VENV_AUTO=no fi From 117fe3a3ed83aa97ed8c5faee347587772d00749 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 15 Sep 2021 17:27:08 -0700 Subject: [PATCH 111/359] build/make/Makefile.in (...-clean): Do not fail trying to uninstall if SAGE_VENV has not been created yet --- build/make/Makefile.in | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/build/make/Makefile.in b/build/make/Makefile.in index 2391e4ab9ba..ac20a5f8df9 100644 --- a/build/make/Makefile.in +++ b/build/make/Makefile.in @@ -532,8 +532,10 @@ $(1)-$(4)-no-deps: $(1)-no-deps: $(1)-$(4)-no-deps $(1)-$(4)-clean: - sage-spkg-uninstall $(if $(filter $(1),$(TOOLCHAIN_DEPS)),--keep-files) \ - $(1) '$$($(4))' + if [ -d '$$($(4))' ]; then \ + sage-spkg-uninstall $(if $(filter $(1),$(TOOLCHAIN_DEPS)),--keep-files) \ + $(1) '$$($(4))'; \ + fi $(1)-clean: $(1)-$(4)-clean From 2576f86d5b782b81746f5e8a961d848d5757082f Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 18 Sep 2021 12:08:18 -0700 Subject: [PATCH 112/359] build/make/Makefile.in: If a script package has no spkg-install, run "sage -info" and exit with error --- build/make/Makefile.in | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/build/make/Makefile.in b/build/make/Makefile.in index bd8ca2a99da..5191d4da759 100644 --- a/build/make/Makefile.in +++ b/build/make/Makefile.in @@ -630,7 +630,8 @@ $$($(4))/$(SPKG_INST_RELDIR)/$(1)-$(2): $(3) $(1): $$($(4))/$(SPKG_INST_RELDIR)/$(1)-$(2) $(1)-$(4)-no-deps: - $(AM_V_at)cd '$$(SAGE_ROOT)/build/pkgs/$(1)' && \ + @if [ -x '$$(SAGE_ROOT)/build/pkgs/$(1)/spkg-install' ]; then \ + $(AM_V_at)cd '$$(SAGE_ROOT)/build/pkgs/$(1)' && \ . '$$(SAGE_ROOT)/src/bin/sage-src-env-config' && \ . '$$(SAGE_ROOT)/src/bin/sage-env-config' && \ . '$$(SAGE_ROOT)/src/bin/sage-env' && \ @@ -638,8 +639,20 @@ $(1)-$(4)-no-deps: . '$$(SAGE_ROOT)/build/bin/sage-build-env' && \ SAGE_SPKG_WHEELS=$$($(4))/var/lib/sage/wheels \ SAGE_INST_LOCAL=$$($(4)) \ - sage-logger -p '$$(SAGE_ROOT)/build/pkgs/$(1)/spkg-install' '$$(SAGE_LOGS)/$(1)-$(2).log' - touch "$$($(4))/$(SPKG_INST_RELDIR)/$(1)-$(2)" + sage-logger -p '$$(SAGE_ROOT)/build/pkgs/$(1)/spkg-install' '$$(SAGE_LOGS)/$(1)-$(2).log' && \ + touch "$$($(4))/$(SPKG_INST_RELDIR)/$(1)-$(2)"; \ + else \ + echo; \ + echo "Error: $(1) is a dummy script 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); \ + exit 1; \ + fi $(1)-no-deps: $(1)-$(4)-no-deps From feb8de7542cc2d97c1b43f114dc2d96db313a22d Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 18 Sep 2021 12:08:41 -0700 Subject: [PATCH 113/359] build/pkgs/: Remove spkg-install scripts for dummy script packages --- build/pkgs/graphviz/spkg-install | 4 ---- build/pkgs/libxml2/spkg-install | 4 ---- build/pkgs/llvm/spkg-install | 4 ---- build/pkgs/pandoc/spkg-install | 5 ----- build/pkgs/perl_cpan_polymake_prereq/spkg-install | 6 ------ 5 files changed, 23 deletions(-) delete mode 100755 build/pkgs/graphviz/spkg-install delete mode 100755 build/pkgs/libxml2/spkg-install delete mode 100755 build/pkgs/llvm/spkg-install delete mode 100755 build/pkgs/pandoc/spkg-install delete mode 100755 build/pkgs/perl_cpan_polymake_prereq/spkg-install diff --git a/build/pkgs/graphviz/spkg-install b/build/pkgs/graphviz/spkg-install deleted file mode 100755 index aeb51456c5d..00000000000 --- a/build/pkgs/graphviz/spkg-install +++ /dev/null @@ -1,4 +0,0 @@ -#! /usr/bin/env bash -echo Error: graphviz is not installed as a system package. -echo Please install the system package recommended by ./configure -exit 1 diff --git a/build/pkgs/libxml2/spkg-install b/build/pkgs/libxml2/spkg-install deleted file mode 100755 index f61a49e9072..00000000000 --- a/build/pkgs/libxml2/spkg-install +++ /dev/null @@ -1,4 +0,0 @@ -#! /usr/bin/env bash -echo Error: libxml2 is not installed. -echo Please install it, for example using the system packages recommended by ./configure -exit 1 diff --git a/build/pkgs/llvm/spkg-install b/build/pkgs/llvm/spkg-install deleted file mode 100755 index 4233e976c04..00000000000 --- a/build/pkgs/llvm/spkg-install +++ /dev/null @@ -1,4 +0,0 @@ -#! /usr/bin/env bash -echo Error: llvm is not installed. -echo Please install it, for example using the system packages recommended by ./configure -exit 1 diff --git a/build/pkgs/pandoc/spkg-install b/build/pkgs/pandoc/spkg-install deleted file mode 100755 index 45fa6a3e0a9..00000000000 --- a/build/pkgs/pandoc/spkg-install +++ /dev/null @@ -1,5 +0,0 @@ -#! /usr/bin/env bash -echo Error: pandoc, a prerequisite of rst2ipynb, is not installed. -echo Please install it manually, for example using the system packages -echo recommended by ./configure. -exit 1 diff --git a/build/pkgs/perl_cpan_polymake_prereq/spkg-install b/build/pkgs/perl_cpan_polymake_prereq/spkg-install deleted file mode 100755 index 44bb1e1a6ef..00000000000 --- a/build/pkgs/perl_cpan_polymake_prereq/spkg-install +++ /dev/null @@ -1,6 +0,0 @@ -#! /usr/bin/env bash -echo Error: The Perl prerequisites of the package polymake are not installed. -echo Please install CPAN packages $(cat distros/cpan.txt) -echo manually, either using the system packages recommended by ./configure -echo or directly from CPAN. -exit 1 From 8f782c01dbc947dcf386303444402b280346f14c Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 18 Sep 2021 12:22:33 -0700 Subject: [PATCH 114/359] .github/workflows/tox-{optional,experimental}.yml: Do not try to test dummy script packages --- .github/workflows/tox-experimental.yml | 8 ++++++-- .github/workflows/tox-optional.yml | 8 ++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/.github/workflows/tox-experimental.yml b/.github/workflows/tox-experimental.yml index 862f00476e9..674a43f7fdf 100644 --- a/.github/workflows/tox-experimental.yml +++ b/.github/workflows/tox-experimental.yml @@ -47,7 +47,9 @@ jobs: TOX_ENV: docker-${{ matrix.tox_system_factor }}-${{ matrix.tox_packages_factor }} LOGS_ARTIFACT_NAME: logs-commit-${{ github.sha }}-tox-docker-${{ matrix.tox_system_factor }}-${{ matrix.tox_packages_factor }} DOCKER_TARGETS: configured with-targets with-targets-optional - TARGETS_OPTIONAL: "$( echo $(PATH=build/bin:$PATH build/bin/sage-package list :experimental: | grep -v database_stein_watkins\\$ | grep -v polytopes_db_4d | grep '^[${{ matrix.targets_pattern }}]' ) )" + # Test all non-dummy experimental packages, but do not test huge packages + # and do not test packages that require external software + TARGETS_OPTIONAL: "$( echo $(export PATH=build/bin:$PATH && sage-package list :experimental: --has-file spkg-install.in && sage-package list :experimental: --has-file spkg-install && sage-package list :experimental: --has-file requirements.txt | grep -v ^_ | grep -v database_stein_watkins\\$ | grep -v polytopes_db_4d | grep -v cplex | grep -v gurobi | grep '^[${{ matrix.targets_pattern }}]' ) )" steps: - uses: actions/checkout@v2 with: @@ -146,7 +148,9 @@ jobs: env: TOX_ENV: local-${{ matrix.tox_system_factor }}-${{ matrix.tox_packages_factor }} LOGS_ARTIFACT_NAME: logs-commit-${{ github.sha }}-tox-local-${{ matrix.tox_system_factor }}-${{ matrix.tox_packages_factor }}-${{ matrix.os }}-xcode_${{ matrix.xcode_version_factor }} - TARGETS_OPTIONAL: "$( echo $(PATH=build/bin:$PATH build/bin/sage-package list :experimental: | grep -v database_stein_watkins\\$ | grep -v polytopes_db_4d | grep '^[${{ matrix.targets_pattern }}]' ) )" + # Test all non-dummy experimental packages, but do not test huge packages + # and do not test packages that require external software + TARGETS_OPTIONAL: "$( echo $(export PATH=build/bin:$PATH && sage-package list :experimental: --has-file spkg-install.in && sage-package list :experimental: --has-file spkg-install && sage-package list :experimental: --has-file requirements.txt | grep -v ^_ | grep -v database_stein_watkins\\$ | grep -v polytopes_db_4d | grep -v cplex | grep -v gurobi | grep '^[${{ matrix.targets_pattern }}]' ) )" steps: - uses: actions/checkout@v2 - name: Select Xcode version diff --git a/.github/workflows/tox-optional.yml b/.github/workflows/tox-optional.yml index 279c6d23feb..72aec6cb82a 100644 --- a/.github/workflows/tox-optional.yml +++ b/.github/workflows/tox-optional.yml @@ -47,9 +47,9 @@ jobs: TOX_ENV: docker-${{ matrix.tox_system_factor }}-${{ matrix.tox_packages_factor }} LOGS_ARTIFACT_NAME: logs-commit-${{ github.sha }}-tox-docker-${{ matrix.tox_system_factor }}-${{ matrix.tox_packages_factor }} DOCKER_TARGETS: configured with-targets with-targets-optional - # Test all optional packages, but do not test huge packages, + # Test all non-dummy optional packages, but do not test huge packages # and do not test packages that require external software - TARGETS_OPTIONAL: "$( echo $(PATH=build/bin:$PATH build/bin/sage-package list :optional: | grep -v database_stein_watkins\\$ | grep -v polytopes_db_4d | grep -v cplex | grep -v gurobi | grep '^[${{ matrix.targets_pattern }}]' ) )" + TARGETS_OPTIONAL: "$( echo $(export PATH=build/bin:$PATH && (sage-package list :optional: --has-file spkg-install.in && sage-package list :optional: --has-file spkg-install && sage-package list :optional: --has-file requirements.txt) | grep -v ^_ | grep -v database_stein_watkins\\$ | grep -v polytopes_db_4d | grep -v cplex | grep -v gurobi | grep '^[${{ matrix.targets_pattern }}]' ) )" steps: - uses: actions/checkout@v2 with: @@ -148,9 +148,9 @@ jobs: env: TOX_ENV: local-${{ matrix.tox_system_factor }}-${{ matrix.tox_packages_factor }} LOGS_ARTIFACT_NAME: logs-commit-${{ github.sha }}-tox-local-${{ matrix.tox_system_factor }}-${{ matrix.tox_packages_factor }}-${{ matrix.os }}-xcode_${{ matrix.xcode_version_factor }} - # Test all optional packages, but do not test huge packages + # Test all non-dummy optional packages, but do not test huge packages # and do not test packages that require external software - TARGETS_OPTIONAL: "$( echo $(PATH=build/bin:$PATH build/bin/sage-package list :optional: | grep -v database_stein_watkins\\$ | grep -v polytopes_db_4d | grep -v cplex | grep -v gurobi | grep '^[${{ matrix.targets_pattern }}]' ) )" + TARGETS_OPTIONAL: "$( echo $(export PATH=build/bin:$PATH && (sage-package list :optional: --has-file spkg-install.in && sage-package list :optional: --has-file spkg-install && sage-package list :optional: --has-file requirements.txt) | grep -v ^_ | grep -v database_stein_watkins\\$ | grep -v polytopes_db_4d | grep -v cplex | grep -v gurobi | grep '^[${{ matrix.targets_pattern }}]' ) )" steps: - uses: actions/checkout@v2 - name: Select Xcode version From 4b292bef2d14ad14c71baf0cba22d07d7a5b55d7 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 19 Sep 2021 21:14:58 -0700 Subject: [PATCH 115/359] build/pkgs/perl_mongodb/spkg-install: Remove --- build/pkgs/perl_mongodb/spkg-install | 6 ------ 1 file changed, 6 deletions(-) delete mode 100755 build/pkgs/perl_mongodb/spkg-install diff --git a/build/pkgs/perl_mongodb/spkg-install b/build/pkgs/perl_mongodb/spkg-install deleted file mode 100755 index 7f087781bb9..00000000000 --- a/build/pkgs/perl_mongodb/spkg-install +++ /dev/null @@ -1,6 +0,0 @@ -#! /usr/bin/env bash -echo Error: The optional prerequisite perl_mongodb of the package polymake are not installed. -echo Please install CPAN package $(cat distros/cpan.txt) -echo manually, either using the system package recommended by ./configure -echo or directly from CPAN. -exit 1 From a7b63520b3cc2daa5a7da2f6b7218f40211d92fc Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 19 Sep 2021 21:22:42 -0700 Subject: [PATCH 116/359] build/bin/sage-spkg-info: Fix display of system packages --- build/bin/sage-spkg-info | 1 + 1 file changed, 1 insertion(+) diff --git a/build/bin/sage-spkg-info b/build/bin/sage-spkg-info index e9152065dc0..79de53afbee 100755 --- a/build/bin/sage-spkg-info +++ b/build/bin/sage-spkg-info @@ -57,6 +57,7 @@ if [ $have_repology = yes ]; then systems="$systems repology" fi for system in $systems; do + system_package_file="$PKG_DISTROS"/$system.txt system_packages="$(echo $(sed 's/#.*//;' $system_package_file))" case $system in debian) From 7b7f6ad24620b744d4decd6dcf648bd479762948 Mon Sep 17 00:00:00 2001 From: Christian Wuthrich Date: Tue, 21 Sep 2021 15:10:33 +0100 Subject: [PATCH 117/359] trac 32258: typos --- src/sage/schemes/elliptic_curves/padic_lseries.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/schemes/elliptic_curves/padic_lseries.py b/src/sage/schemes/elliptic_curves/padic_lseries.py index 72250f3ed6b..d462d6c7151 100644 --- a/src/sage/schemes/elliptic_curves/padic_lseries.py +++ b/src/sage/schemes/elliptic_curves/padic_lseries.py @@ -842,7 +842,7 @@ def series(self, n=2, quadratic_twist=+1, prec=5, eta=0): sage: lp.series(6) 2^2 + 2^6 + O(2^7) + (2 + O(2^4))*T + O(2^3)*T^2 + (2^2 + O(2^3))*T^3 + (2 + O(2^2))*T^4 + O(T^5) - Check that twists by odd Teichmuller charachters are ok (:trac:`32258`):: + Check that twists by odd Teichmuller characters are ok (:trac:`32258`):: sage: E = EllipticCurve("443c1") sage: lp = E.padic_lseries(17, implementation="num") @@ -1313,7 +1313,7 @@ def series(self, n=3, quadratic_twist=+1, prec=5, eta=0): j += 1 L = R(bj, prec) L /= self._quotient_of_periods_to_twist(D) - if si == +1 : + if si == +1: L /= self._E.real_components() self._set_series_in_cache(n, prec, quadratic_twist, eta, L) return L From e65b3092f97226196a5ea2de1b46508371745d00 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 21 Sep 2021 16:07:22 -0700 Subject: [PATCH 118/359] bootstrap: Do not provide ./configure --enable-SPKG options for dummy optional packages --- bootstrap | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/bootstrap b/bootstrap index 1ee0c6b9ab2..0feb5191eca 100755 --- a/bootstrap +++ b/bootstrap @@ -97,8 +97,13 @@ AS_VAR_SET_IF([SAGE_ENABLE_$pkgname], [], [AS_VAR_SET([SAGE_ENABLE_$pkgname], [y case "$pkgname" in _*) ;; *) spkg_configures="$spkg_configures -AC_SUBST(SAGE_ENABLE_$pkgname, [if_installed]) -SAGE_SPKG_ENABLE([$pkgname], [$pkgtype], [$(head -n1 build/pkgs/$pkgname/SPKG.rst 2>/dev/null || echo $pkgname)])" ;; +AC_SUBST(SAGE_ENABLE_$pkgname, [if_installed])" + if [ -f build/pkgs/$pkgname/spkg-install -o -f build/pkgs/$pkgname/spkg-install.in ]; then + # Trac #31163: Not just an optional dummy package + spkg_configures="$spkg_configures +SAGE_SPKG_ENABLE([$pkgname], [$pkgtype], [$(head -n1 build/pkgs/$pkgname/SPKG.rst 2>/dev/null || echo $pkgname)])" + fi + ;; esac fi done From b485d469cb1f61774b3f098b1e4277e66bd712fd Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 21 Sep 2021 16:35:13 -0700 Subject: [PATCH 119/359] m4/sage_spkg_collect.m4: Do not advertise dummy optional packages as installable --- m4/sage_spkg_collect.m4 | 69 ++++++++++++++++++++++++----------------- 1 file changed, 41 insertions(+), 28 deletions(-) diff --git a/m4/sage_spkg_collect.m4 b/m4/sage_spkg_collect.m4 index 1ab62d6fa47..d18ae090743 100644 --- a/m4/sage_spkg_collect.m4 +++ b/m4/sage_spkg_collect.m4 @@ -146,6 +146,35 @@ for DIR in $SAGE_ROOT/build/pkgs/*; do in_sdist=no + dnl Determine package source + dnl + if test -f "$DIR/requirements.txt"; then + SPKG_SOURCE=pip + # Since pip packages are downloaded and installed by pip, we don't + # include them in the source tarball. At the time of this writing, + # all pip packages are optional. + in_sdist=no + elif test ! -f "$DIR/checksums.ini"; then + if test -f "$DIR/spkg-install"; then + SPKG_SOURCE=script + else + dnl a dummy script package + SPKG_SOURCE=none + fi + # We assume that either (a) the sources for an optional script + # package will be downloaded by the script, or (b) that a + # standard script package's sources are already a part of the + # sage repository (and thus the release tarball). As a result, + # we don't need to download the sources, which is what + # "in_sdist" really means. At the time of this writing, the + # only standard script packages are sage_conf and sagelib. + # The sources of these packages are in subdirectories of + # $SAGE_ROOT/pkgs. + in_sdist=no + else + SPKG_SOURCE=normal + fi + dnl Write out information about the installation tree, using the name of the tree prefix dnl variable (SAGE_LOCAL or SAGE_VENV). The makefile variable of SPKG is called "trees_SPKG", dnl note plural, for possible future extension in which an SPKG would be installed into several @@ -177,7 +206,11 @@ for DIR in $SAGE_ROOT/build/pkgs/*; do AS_VAR_IF([SAGE_ENABLE_]${SPKG_NAME}, [yes], [ message="$SPKG_TYPE, will be installed as an SPKG" ], [ - message="$SPKG_TYPE, use \"$srcdir/configure --enable-$SPKG_NAME\" to install" + message="$SPKG_TYPE" + AS_VAR_IF([SPKG_SOURCE], [none], [], [ + dnl Non-dummy optional/experimental package, advertise how to install + message="$message, use \"$srcdir/configure --enable-$SPKG_NAME\" to install" + ]) SAGE_NEED_SYSTEM_PACKAGES_VAR=SAGE_NEED_SYSTEM_PACKAGES_OPTIONAL ]) ;; @@ -228,8 +261,12 @@ for DIR in $SAGE_ROOT/build/pkgs/*; do AS_VAR_IF([sage_spkg_install], [no], [ dnl We will use the system package (or not required for this platform.) SAGE_DUMMY_PACKAGES="${SAGE_DUMMY_PACKAGES} \\$(printf '\n ')${SPKG_NAME}" - AS_VAR_IF([sage_require], [yes], [ message="using system package; SPKG will not be installed" - ], [ message="not required on your platform; SPKG will not be installed" + AS_VAR_IF([sage_require], [yes], [ message="using system package" + ], [ message="not required on your platform" + ]) + dnl Trac #31163: Only talk about the SPKG if there is an SPKG + AS_VAR_IF([SPKG_SOURCE], [none], [], [ + message="$message; SPKG will not be installed" ]) ], [ dnl We will not use the system package. @@ -267,30 +304,6 @@ for DIR in $SAGE_ROOT/build/pkgs/*; do ;; esac - # Determine package source - # - if test -f "$DIR/requirements.txt"; then - SPKG_SOURCE=pip - # Since pip packages are downloaded and installed by pip, we don't - # include them in the source tarball. At the time of this writing, - # all pip packages are optional. - in_sdist=no - elif test ! -f "$DIR/checksums.ini"; then - SPKG_SOURCE=script - # We assume that either (a) the sources for an optional script - # package will be downloaded by the script, or (b) that a - # standard script package's sources are already a part of the - # sage repository (and thus the release tarball). As a result, - # we don't need to download the sources, which is what - # "in_sdist" really means. At the time of this writing, the - # only standard script packages are sage_conf and sagelib. - # The sources of these packages are in subdirectories of - # $SAGE_ROOT/pkgs. - in_sdist=no - else - SPKG_SOURCE=normal - fi - if test "$in_sdist" = yes; then SAGE_SDIST_PACKAGES="${SAGE_SDIST_PACKAGES} \\$(printf '\n ')${SPKG_NAME}" fi @@ -338,7 +351,7 @@ for DIR in $SAGE_ROOT/build/pkgs/*; do pip) SAGE_PIP_PACKAGES="${SAGE_PIP_PACKAGES} \\$(printf '\n ')${SPKG_NAME}" ;; - script) + script|none) SAGE_SCRIPT_PACKAGES="${SAGE_SCRIPT_PACKAGES} \\$(printf '\n ')${SPKG_NAME}" ;; normal) From 9fa072e89a176420d18f99fb0d00a08318ec87e7 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 22 Sep 2021 18:53:25 -0700 Subject: [PATCH 120/359] build/pkgs/mpir: Remove --- build/make/Makefile.in | 2 +- build/pkgs/cddlib/spkg-configure.m4 | 2 +- build/pkgs/ecl/spkg-configure.m4 | 2 +- build/pkgs/ecm/spkg-configure.m4 | 2 +- build/pkgs/fflas_ffpack/spkg-configure.m4 | 2 +- build/pkgs/givaro/spkg-configure.m4 | 2 +- build/pkgs/glpk/spkg-configure.m4 | 2 +- build/pkgs/gmp/spkg-configure.m4 | 26 +- build/pkgs/igraph/spkg-configure.m4 | 2 +- build/pkgs/iml/spkg-configure.m4 | 2 +- build/pkgs/isl/spkg-configure.m4 | 2 +- build/pkgs/lrslib/spkg-configure.m4 | 2 +- build/pkgs/mpfr/spkg-configure.m4 | 2 +- build/pkgs/mpir/SPKG.rst | 44 --- build/pkgs/mpir/checksums.ini | 4 - build/pkgs/mpir/dependencies | 5 - build/pkgs/mpir/distros/conda.txt | 1 - build/pkgs/mpir/distros/freebsd.txt | 1 - build/pkgs/mpir/distros/homebrew.txt | 1 - build/pkgs/mpir/distros/opensuse.txt | 1 - build/pkgs/mpir/distros/repology.txt | 1 - build/pkgs/mpir/package-version.txt | 1 - build/pkgs/mpir/patches/ticket-25858.patch | 144 --------- build/pkgs/mpir/spkg-check.in | 6 - build/pkgs/mpir/spkg-configure.m4 | 74 ----- build/pkgs/mpir/spkg-install.in | 322 --------------------- build/pkgs/mpir/spkg-src | 43 --- build/pkgs/mpir/type | 1 - build/pkgs/ntl/spkg-configure.m4 | 2 +- build/pkgs/pari/spkg-configure.m4 | 2 +- build/pkgs/ppl/spkg-configure.m4 | 2 +- build/pkgs/yasm/spkg-configure.m4 | 4 +- build/pkgs/zn_poly/spkg-configure.m4 | 2 +- 33 files changed, 40 insertions(+), 671 deletions(-) delete mode 100644 build/pkgs/mpir/SPKG.rst delete mode 100644 build/pkgs/mpir/checksums.ini delete mode 100644 build/pkgs/mpir/dependencies delete mode 100644 build/pkgs/mpir/distros/conda.txt delete mode 100644 build/pkgs/mpir/distros/freebsd.txt delete mode 100644 build/pkgs/mpir/distros/homebrew.txt delete mode 100644 build/pkgs/mpir/distros/opensuse.txt delete mode 100644 build/pkgs/mpir/distros/repology.txt delete mode 100644 build/pkgs/mpir/package-version.txt delete mode 100644 build/pkgs/mpir/patches/ticket-25858.patch delete mode 100644 build/pkgs/mpir/spkg-check.in delete mode 100644 build/pkgs/mpir/spkg-configure.m4 delete mode 100644 build/pkgs/mpir/spkg-install.in delete mode 100755 build/pkgs/mpir/spkg-src delete mode 100644 build/pkgs/mpir/type diff --git a/build/make/Makefile.in b/build/make/Makefile.in index bd8ca2a99da..82252009582 100644 --- a/build/make/Makefile.in +++ b/build/make/Makefile.in @@ -32,7 +32,7 @@ SPKG_INST_RELDIR = var/lib/sage/installed # Aliases for mutually exclusive standard packages selected at configure time TOOLCHAIN = @SAGE_TOOLCHAIN@ PYTHON = python3 -MP_LIBRARY = @SAGE_MP_LIBRARY@ +MP_LIBRARY = gmp BLAS = @SAGE_BLAS@ # pkgconfig files generated/installed at build time diff --git a/build/pkgs/cddlib/spkg-configure.m4 b/build/pkgs/cddlib/spkg-configure.m4 index aa313498737..ad227f032ed 100644 --- a/build/pkgs/cddlib/spkg-configure.m4 +++ b/build/pkgs/cddlib/spkg-configure.m4 @@ -1,5 +1,5 @@ SAGE_SPKG_CONFIGURE([cddlib], [ - SAGE_SPKG_DEPCHECK([gmp mpir], [ + SAGE_SPKG_DEPCHECK([gmp], [ dnl The sage library uses BOTH cddexec and cddexec_gmp. dnl These two executables were introduced in cddlib-094j. AC_CHECK_PROGS([CDDEXEC], [cddexec]) diff --git a/build/pkgs/ecl/spkg-configure.m4 b/build/pkgs/ecl/spkg-configure.m4 index 9fd61393b31..ae1e0ac5e1a 100644 --- a/build/pkgs/ecl/spkg-configure.m4 +++ b/build/pkgs/ecl/spkg-configure.m4 @@ -3,7 +3,7 @@ SAGE_SPKG_CONFIGURE([ecl], [ # Default to installing the SPKG sage_spkg_install_ecl=yes - SAGE_SPKG_DEPCHECK([gcc gc gmp mpir], [ + SAGE_SPKG_DEPCHECK([gcc gc gmp], [ AC_PATH_PROG([ECL_CONFIG], [ecl-config]) AS_IF([test x$ECL_CONFIG != x], [ # "CPPFLAGS" is not a typo, the --cflags output from diff --git a/build/pkgs/ecm/spkg-configure.m4 b/build/pkgs/ecm/spkg-configure.m4 index ada5f34b0d9..e62c21cb32e 100644 --- a/build/pkgs/ecm/spkg-configure.m4 +++ b/build/pkgs/ecm/spkg-configure.m4 @@ -2,7 +2,7 @@ SAGE_SPKG_CONFIGURE([ecm], [ m4_pushdef([SAGE_ECM_MINVER],[7.0.4]) AC_REQUIRE([SAGE_SPKG_CONFIGURE_GMP]) AC_MSG_CHECKING([installing gmp/mpir? ]) - if test x$sage_spkg_install_mpir = xyes -o x$sage_spkg_install_gmp = xyes; then + if test x$sage_spkg_install_gmp = xyes; then AC_MSG_RESULT([yes; install ecm as well]) sage_spkg_install_ecm=yes else diff --git a/build/pkgs/fflas_ffpack/spkg-configure.m4 b/build/pkgs/fflas_ffpack/spkg-configure.m4 index f85295a7767..f107ff5cf15 100644 --- a/build/pkgs/fflas_ffpack/spkg-configure.m4 +++ b/build/pkgs/fflas_ffpack/spkg-configure.m4 @@ -1,7 +1,7 @@ SAGE_SPKG_CONFIGURE([fflas_ffpack], [ # fflas-lapack uses whatever multi-precision library givaro uses, # either gmp or mpir. - SAGE_SPKG_DEPCHECK([atlas givaro gmp mpir openblas], [ + SAGE_SPKG_DEPCHECK([atlas givaro gmp openblas], [ # If our dependencies come from the system, then we can use # the system fflas-ffpack, too. Use pkg-config to find a # recentish version, if there is one. diff --git a/build/pkgs/givaro/spkg-configure.m4 b/build/pkgs/givaro/spkg-configure.m4 index 6afb9e95599..7eb91edfd00 100644 --- a/build/pkgs/givaro/spkg-configure.m4 +++ b/build/pkgs/givaro/spkg-configure.m4 @@ -1,6 +1,6 @@ SAGE_SPKG_CONFIGURE([givaro], [ m4_pushdef([SAGE_GIVARO_MINVER],["40101"]) - SAGE_SPKG_DEPCHECK([gmp mpir], [ + SAGE_SPKG_DEPCHECK([gmp], [ AC_PATH_PROG([GIVAROCONFIG], [givaro-config]) AS_IF([test x$GIVAROCONFIG = x], [ AC_MSG_NOTICE([givaro-config not found. Installing givaro]) diff --git a/build/pkgs/glpk/spkg-configure.m4 b/build/pkgs/glpk/spkg-configure.m4 index d23ab9cc59f..6fb7d64aa44 100644 --- a/build/pkgs/glpk/spkg-configure.m4 +++ b/build/pkgs/glpk/spkg-configure.m4 @@ -1,6 +1,6 @@ SAGE_SPKG_CONFIGURE([glpk], [ m4_pushdef([SAGE_GLPK_MINVER],["4.63"]) - SAGE_SPKG_DEPCHECK([gmp mpir zlib], [ + SAGE_SPKG_DEPCHECK([gmp zlib], [ AC_PATH_PROG([GLPSOL], [glpsol]) AS_IF([test x$GLPSOL = x], [ AC_MSG_NOTICE([glpsol not found. Installing glpk]) diff --git a/build/pkgs/gmp/spkg-configure.m4 b/build/pkgs/gmp/spkg-configure.m4 index 9f5ffea5aa2..61d7c5f3b2f 100644 --- a/build/pkgs/gmp/spkg-configure.m4 +++ b/build/pkgs/gmp/spkg-configure.m4 @@ -1,8 +1,26 @@ SAGE_SPKG_CONFIGURE([gmp], [ - AC_REQUIRE([SAGE_SPKG_CONFIGURE_MPIR]) - if test x"$with_mp" = xgmp -o x"$_sage_spkg_install_gmp" = xyes; then - if test x"$SAGE_MP_LIBRARY" = xgmp; then - sage_spkg_install_gmp=yes + sage_spkg_install_gmp=no + AC_CHECK_HEADER(gmp.h, [], [sage_spkg_install_gmp=yes]) + AC_CHECK_HEADER(gmpxx.h, [], [sage_spkg_install_gmp=yes]) + dnl mpq_cmp_z appeared in GMP 6.1.0 and is used by pynac + AC_SEARCH_LIBS([__gmpq_cmp_z], [gmp], [], + [sage_spkg_install_gmp=yes]) +], [], [], [ + if test x$sage_spkg_install_gmp = xyes; then + AC_SUBST(SAGE_GMP_PREFIX, ['$SAGE_LOCAL']) + AC_SUBST(SAGE_GMP_INCLUDE, ['$SAGE_LOCAL/include']) + else + dnl If found, we want to get the absolute path to where we + dnl found it for use with some packages (e.g. iml) that need + dnl this information at configure time + AX_ABSOLUTE_HEADER([gmp.h]) + if test x$gl_cv_absolute_gmp_h = x; then + AC_MSG_ERROR(m4_normalize([ + failed to find absolute path to gmp.h despite it being reported + found + ])) fi + AC_SUBST(SAGE_GMP_INCLUDE, [`AS_DIRNAME($gl_cv_absolute_gmp_h)`]) + AC_SUBST(SAGE_GMP_PREFIX, ['']) fi ]) diff --git a/build/pkgs/igraph/spkg-configure.m4 b/build/pkgs/igraph/spkg-configure.m4 index a292b33d8a7..ed604d599f9 100644 --- a/build/pkgs/igraph/spkg-configure.m4 +++ b/build/pkgs/igraph/spkg-configure.m4 @@ -1,5 +1,5 @@ SAGE_SPKG_CONFIGURE([igraph], [ -SAGE_SPKG_DEPCHECK([glpk atlas openblas gmp mpir], [ +SAGE_SPKG_DEPCHECK([glpk atlas openblas gmp], [ dnl check for igraph with pkg-config PKG_CHECK_MODULES([IGRAPH], [igraph >= 0.8.3], [], [ sage_spkg_install_igraph=yes]) diff --git a/build/pkgs/iml/spkg-configure.m4 b/build/pkgs/iml/spkg-configure.m4 index ea78a6bbdcd..efab2c105c6 100644 --- a/build/pkgs/iml/spkg-configure.m4 +++ b/build/pkgs/iml/spkg-configure.m4 @@ -1,5 +1,5 @@ SAGE_SPKG_CONFIGURE([iml], [ - SAGE_SPKG_DEPCHECK([gmp mpir openblas], [ + SAGE_SPKG_DEPCHECK([gmp openblas], [ AC_CHECK_HEADER([iml.h], [ AC_SEARCH_LIBS([nonsingSolvLlhsMM], [iml], [], [sage_spkg_install_iml=yes]) diff --git a/build/pkgs/isl/spkg-configure.m4 b/build/pkgs/isl/spkg-configure.m4 index 9394030dbc1..1b16f70870b 100644 --- a/build/pkgs/isl/spkg-configure.m4 +++ b/build/pkgs/isl/spkg-configure.m4 @@ -1,7 +1,7 @@ SAGE_SPKG_CONFIGURE([isl], [ AC_REQUIRE([SAGE_SPKG_CONFIGURE_GMP]) AC_MSG_CHECKING([installing gmp/mpir? ]) - if test x$sage_spkg_install_mpir = xyes -o x$sage_spkg_install_gmp = xyes; then + if test x$sage_spkg_install_gmp = xyes; then AC_MSG_RESULT([yes; install isl as well]) sage_spkg_install_isl=yes else diff --git a/build/pkgs/lrslib/spkg-configure.m4 b/build/pkgs/lrslib/spkg-configure.m4 index 860cca451e0..0297f7118e3 100644 --- a/build/pkgs/lrslib/spkg-configure.m4 +++ b/build/pkgs/lrslib/spkg-configure.m4 @@ -1,6 +1,6 @@ SAGE_SPKG_CONFIGURE([lrslib], [ dnl System lrslib may already be 7.x, which may be compiled with FLINT - SAGE_SPKG_DEPCHECK([gmp mpir flint], [ + SAGE_SPKG_DEPCHECK([gmp flint], [ AC_CHECK_PROGS([LRSNASH], [lrsnash]) AS_IF([test -z "$LRSNASH"], [ sage_spkg_install_lrslib=yes diff --git a/build/pkgs/mpfr/spkg-configure.m4 b/build/pkgs/mpfr/spkg-configure.m4 index 0c15b56df43..2300be67076 100644 --- a/build/pkgs/mpfr/spkg-configure.m4 +++ b/build/pkgs/mpfr/spkg-configure.m4 @@ -1,7 +1,7 @@ SAGE_SPKG_CONFIGURE([mpfr], [ AC_REQUIRE([SAGE_SPKG_CONFIGURE_GMP]) AC_MSG_CHECKING([installing gmp/mpir? ]) - if test x$sage_spkg_install_mpir = xyes -o x$sage_spkg_install_gmp = xyes; then + if test x$sage_spkg_install_gmp = xyes; then AC_MSG_RESULT([yes; install mpfr as well]) sage_spkg_install_mpfr=yes else diff --git a/build/pkgs/mpir/SPKG.rst b/build/pkgs/mpir/SPKG.rst deleted file mode 100644 index a03133b1f6c..00000000000 --- a/build/pkgs/mpir/SPKG.rst +++ /dev/null @@ -1,44 +0,0 @@ -mpir: Multiple precision integers and rationals (fork of GMP) -============================================================= - -Description ------------ - -Multiple Precision Integers and Rationals. - -MPIR is an open source multiprecision integer library derived from -version 5.0.1 of the GMP (GNU Multi Precision) project (which was -licensed LGPL v2+). - -See http://www.mpir.org - -License -------- - -- LGPL V3+ - - -Upstream Contact ----------------- - -- The Google group mpir-devel -- thempirteam@googlemail.com - -Dependencies ------------- - -- iconv -- GNU patch - - -Special Update/Build Instructions ---------------------------------- - -- TODO: -- Perhaps also modify CXXFLAGS (and/or CPPFLAGS). -- We currently don't use anything of GMP's/MPIR's CC setting, and - matching with the current compiler (``$CC``) is perhaps suboptimal. -- Remove some files / directories not needed for Sage from upstream: -- build.vc\* directories (Microsoft Visual C build files) -- 3.0.0-644faf502c56f97d9accd301965fc57d6ec70868 - was created by running the spkg-src script. diff --git a/build/pkgs/mpir/checksums.ini b/build/pkgs/mpir/checksums.ini deleted file mode 100644 index d482fd960d9..00000000000 --- a/build/pkgs/mpir/checksums.ini +++ /dev/null @@ -1,4 +0,0 @@ -tarball=mpir-VERSION.tar.bz2 -sha1=30044be9f48ce15ddfc8871bde14e363fe2f46ea -md5=55e9e31d6371b30dd046f16333c84499 -cksum=1799000157 diff --git a/build/pkgs/mpir/dependencies b/build/pkgs/mpir/dependencies deleted file mode 100644 index 8ca2e8756c8..00000000000 --- a/build/pkgs/mpir/dependencies +++ /dev/null @@ -1,5 +0,0 @@ -| yasm - ----------- -All lines of this file are ignored except the first. -It is copied by SAGE_ROOT/build/make/install into SAGE_ROOT/build/make/Makefile. diff --git a/build/pkgs/mpir/distros/conda.txt b/build/pkgs/mpir/distros/conda.txt deleted file mode 100644 index bef94785573..00000000000 --- a/build/pkgs/mpir/distros/conda.txt +++ /dev/null @@ -1 +0,0 @@ -mpir diff --git a/build/pkgs/mpir/distros/freebsd.txt b/build/pkgs/mpir/distros/freebsd.txt deleted file mode 100644 index 75bf5706674..00000000000 --- a/build/pkgs/mpir/distros/freebsd.txt +++ /dev/null @@ -1 +0,0 @@ -math/mpir diff --git a/build/pkgs/mpir/distros/homebrew.txt b/build/pkgs/mpir/distros/homebrew.txt deleted file mode 100644 index bef94785573..00000000000 --- a/build/pkgs/mpir/distros/homebrew.txt +++ /dev/null @@ -1 +0,0 @@ -mpir diff --git a/build/pkgs/mpir/distros/opensuse.txt b/build/pkgs/mpir/distros/opensuse.txt deleted file mode 100644 index 16b5b660968..00000000000 --- a/build/pkgs/mpir/distros/opensuse.txt +++ /dev/null @@ -1 +0,0 @@ -libmpir-devel diff --git a/build/pkgs/mpir/distros/repology.txt b/build/pkgs/mpir/distros/repology.txt deleted file mode 100644 index bef94785573..00000000000 --- a/build/pkgs/mpir/distros/repology.txt +++ /dev/null @@ -1 +0,0 @@ -mpir diff --git a/build/pkgs/mpir/package-version.txt b/build/pkgs/mpir/package-version.txt deleted file mode 100644 index 27bffd152e1..00000000000 --- a/build/pkgs/mpir/package-version.txt +++ /dev/null @@ -1 +0,0 @@ -3.0.0-644faf502c56f97d9accd301965fc57d6ec70868.p0 diff --git a/build/pkgs/mpir/patches/ticket-25858.patch b/build/pkgs/mpir/patches/ticket-25858.patch deleted file mode 100644 index e4aa2fd0db4..00000000000 --- a/build/pkgs/mpir/patches/ticket-25858.patch +++ /dev/null @@ -1,144 +0,0 @@ -Add support for Celeron/Pentium CPUs that use the Haswell microarchitecture but -without various extended instruction sets -https://trac.sagemath.org/ticket/25858 -diff -ru a/configure b/configure ---- a/configure 2018-07-13 14:49:36.839366500 +0200 -+++ b/configure 2018-07-13 15:08:51.229370000 +0200 -@@ -4585,7 +4585,7 @@ - # mode, in case -m32 has failed not because it's an old gcc, but because - # it's a dual 32/64-bit gcc without a 32-bit libc, or whatever. - # -- i?86*-*-* | k[5-8]*-*-* | pentium*-*-* | prescott-*-* | core-*-* | athlon-*-* | viac3*-*-* | x86_64-*-* | netburst-*-* | netburstlahf-*-* | k8-*-* | k10-*-* | k102-*-* | k103-*-* | core2-*-* | penryn-*-* | nehalem-*-* | westmere-*-* | sandybridge-*-* | atom-*-* | nano-*-* | bobcat-*-* | bulldozer-*-* | piledriver-*-* | ivybridge-*-* | haswell-*-* | broadwell-*-* | skylake-*-* | skylakeavx-*-*) -+ i?86*-*-* | k[5-8]*-*-* | pentium*-*-* | prescott-*-* | core-*-* | athlon-*-* | viac3*-*-* | x86_64-*-* | netburst-*-* | netburstlahf-*-* | k8-*-* | k10-*-* | k102-*-* | k103-*-* | core2-*-* | penryn-*-* | nehalem-*-* | westmere-*-* | sandybridge-*-* | atom-*-* | nano-*-* | bobcat-*-* | bulldozer-*-* | piledriver-*-* | ivybridge-*-* | haswell-*-* | haswellavx-*-* | broadwell-*-* | skylake-*-* | skylakeavx-*-*) - abilist="32" - cclist="gcc icc cc" - gcc_cflags="-O2 $fomit_frame_pointer" -@@ -4761,7 +4761,11 @@ - gcc_cflags_cpu="-mtune=corei7 -mtune=core2 -mtune=nocona -mtune=pentium3 -mcpu=pentiumpro -mcpu=i486 -m486" - gcc_cflags_arch="-march=corei7 -march=core2 -march=nocona -march=pentium3 -march=pentiumpro -march=pentium" - ;; -- sandybridge | ivybridge | haswell) -+ haswell) -+ gcc_cflags_cpu="-mtune=corei7 -mtune=corei7 -mtune=core2 -mtune=nocona -mtune=pentium3 -mcpu=pentiumpro -mcpu=i486 -m486" -+ gcc_cflags_arch="-march=corei7 -march=corei7 -march=core2 -march=nocona -march=pentium3 -march=pentiumpro -march=pentium" -+ ;; -+ sandybridge | ivybridge | haswellavx) - gcc_cflags_cpu="-mtune=corei7-avx -mtune=corei7 -mtune=core2 -mtune=nocona -mtune=pentium3 -mcpu=pentiumpro -mcpu=i486 -m486" - gcc_cflags_arch="-march=corei7-avx -march=corei7 -march=core2 -march=nocona -march=pentium3 -march=pentiumpro -march=pentium" - ;; -@@ -4800,7 +4804,7 @@ - k8 | bobcat) path="x86/k7/mmx/k8 x86/k7/mmx x86/k7 x86" ;; - core2 | penryn) path="x86/core2 x86" ;; - i786 | pentium4) path="x86/pentium4/sse2 x86/pentium4/mmx x86/pentium4 x86" ;; -- nehalem | westmere | sandybridge | ivybridge | haswell | skylake | skylakeavx | broadwell) path="x86/nehalem x86" ;; -+ nehalem | westmere | sandybridge | ivybridge | haswell | haswellavx | skylake | skylakeavx | broadwell) path="x86/nehalem x86" ;; - prescott | netburst | netburstlahf) path="x86/pentium4/sse2 x86/pentium4/mmx x86/pentium4 x86" ;; - # VIA/Centaur processors, sold as CyrixIII and C3. - nano | viac32) path="x86/p6/p3mmx x86/p6/mmx x86/p6 x86";; -@@ -4842,7 +4846,7 @@ - fi - - case $host in -- x86_64-*-* | netburst-*-* | netburstlahf-*-* | k8-*-* | k10-*-* | k102-*-* | k103-*-* | core2-*-* | penryn-*-* | nehalem-*-* | westmere-*-* | sandybridge-*-* | atom-*-* | nano-*-* | bobcat-*-* | bulldozer-*-* | piledriver-*-* | ivybridge-*-* | haswell-*-* | broadwell-*-* | skylake-*-* | skylakeavx-*-*) -+ x86_64-*-* | netburst-*-* | netburstlahf-*-* | k8-*-* | k10-*-* | k102-*-* | k103-*-* | core2-*-* | penryn-*-* | nehalem-*-* | westmere-*-* | sandybridge-*-* | atom-*-* | nano-*-* | bobcat-*-* | bulldozer-*-* | piledriver-*-* | ivybridge-*-* | haswell-*-* | haswellavx-*-* | broadwell-*-* | skylake-*-* | skylakeavx-*-*) - abilist="64 32" - cclist_64="gcc cc" - gcc_64_cflags="-m64" -@@ -4901,10 +4905,12 @@ - path_64="x86_64w/sandybridge/ivybridge x86_64w/sandybridge x86_64w" ;; - haswell-pc-msys|haswell-w64-mingw*|haswell-*-cygwin*) - path_64="x86_64w/haswell x86_64w/sandybridge x86_64w" ;; -+ haswellavx-pc-msys|haswellavx-w64-mingw*|haswellavx-*-cygwin*) -+ path_64="x86_64w/haswell/avx x86_64w/haswell x86_64w/sandybridge x86_64w" ;; - skylake-pc-msys|skylake-w64-mingw*|skylake-*-cygwin*) - path_64="x86_64w/skylake x86_64w/sandybridge x86_64w" ;; - skylakeavx-pc-msys|skylakeavx-w64-mingw*|skylakeavx-*-cygwin*) -- path_64="x86_64w/skylakeavx x86_64w/skylake x86_64w/haswell x86_64w/sandybridge x86_64w" ;; -+ path_64="x86_64w/skylake/avx x86_64w/skylake x86_64w/haswell x86_64w/sandybridge x86_64w" ;; - broadwell-pc-msys|broadwell-w64-mingw*|broadwell-*-cygwin*) - path_64="x86_64w/haswell/broadwell x86_64w/haswell/avx x86_64w/haswell x86_64w/sandybridge x86_64w" ;; - atom-pc-msys|atom-w64-mingw*|atom-*-cygwin*) -@@ -4945,6 +4951,8 @@ - ivybridge-*-*) - path_64="x86_64/sandybridge/ivybridge x86_64/sandybridge x86_64/nehalem x86_64/core2 x86_64" ;; - haswell-*-*) -+ path_64="x86_64/haswell x86_64/sandybridge x86_64" ;; -+ haswellavx-*-*) - path_64="x86_64/haswell/avx x86_64/haswell x86_64/sandybridge x86_64" ;; - broadwell-*-*) - path_64="x86_64/haswell/broadwell x86_64/haswell/avx x86_64/haswell x86_64/sandybridge x86_64" ;; -@@ -10775,7 +10783,7 @@ - # enough assembler. - # - case $host in -- i?86*-*-* | k[5-8]*-*-* | pentium*-*-* | prescott-*-* | core-*-* | athlon-*-* | viac3*-*-* | x86_64-*-* | netburst-*-* | netburstlahf-*-* | k8-*-* | k10-*-* | k102-*-* | k103-*-* | core2-*-* | penryn-*-* | nehalem-*-* | westmere-*-* | sandybridge-*-* | atom-*-* | nano-*-* | bobcat-*-* | bulldozer-*-* | piledriver-*-* | ivybridge-*-* | haswell-*-* | broadwell-*-* | skylake-*-* | skylakeavx-*-*) -+ i?86*-*-* | k[5-8]*-*-* | pentium*-*-* | prescott-*-* | core-*-* | athlon-*-* | viac3*-*-* | x86_64-*-* | netburst-*-* | netburstlahf-*-* | k8-*-* | k10-*-* | k102-*-* | k103-*-* | core2-*-* | penryn-*-* | nehalem-*-* | westmere-*-* | sandybridge-*-* | atom-*-* | nano-*-* | bobcat-*-* | bulldozer-*-* | piledriver-*-* | ivybridge-*-* | haswell-*-* | haswellavx-*-* | broadwell-*-* | skylake-*-* | skylakeavx-*-*) - if test "$ABI" = 32; then - case "$path $fat_path" in - *mmx*) { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the assembler knows about MMX instructions" >&5 -@@ -25885,7 +25867,7 @@ - ;; - esac - ;; -- i?86*-*-* | k[5-8]*-*-* | pentium*-*-* | prescott-*-* | core-*-* | athlon-*-* | viac3*-*-* | x86_64-*-* | netburst-*-* | netburstlahf-*-* | k8-*-* | k10-*-* | k102-*-* | k103-*-* | core2-*-* | penryn-*-* | nehalem-*-* | westmere-*-* | sandybridge-*-* | atom-*-* | nano-*-* | bobcat-*-* | bulldozer-*-* | piledriver-*-* | ivybridge-*-* | haswell-*-* | broadwell-*-* | skylake-*-* | skylakeavx-*-*) -+ i?86*-*-* | k[5-8]*-*-* | pentium*-*-* | prescott-*-* | core-*-* | athlon-*-* | viac3*-*-* | x86_64-*-* | netburst-*-* | netburstlahf-*-* | k8-*-* | k10-*-* | k102-*-* | k103-*-* | core2-*-* | penryn-*-* | nehalem-*-* | westmere-*-* | sandybridge-*-* | atom-*-* | nano-*-* | bobcat-*-* | bulldozer-*-* | piledriver-*-* | ivybridge-*-* | haswell-*-* | haswellavx-*-* | broadwell-*-* | skylake-*-* | skylakeavx-*-*) - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the .align directive accepts an 0x90 fill in .text" >&5 - $as_echo_n "checking if the .align directive accepts an 0x90 fill in .text... " >&6; } -diff -ru a/cpuid.c b/cpuid.c ---- a/cpuid.c 2018-07-13 14:49:31.111368100 +0200 -+++ b/cpuid.c 2018-07-13 15:08:45.680372700 +0200 -@@ -174,12 +174,16 @@ CPUVEC_SETUP_x86_64; - if (model == 54){ CPUIS(atom);break;}//DualCore Intel Atom D2700, 2133 MHz (16 x 133) (Cedarview, Saltwell core) 32nm - if (model == 55){ CPUIS(atom);break;} - if (model == 58){ CPUIS(ivybridge);break;} -- if (model == 60){ CPUIS(haswell);break;} -+ if (model == 60){ -+ int feat = ((int *)features)[2]; -+ if (feat & FEAT_HAS_AVX) { CPUIS(haswellavx);break; } /* Core i Haswell */ -+ else { CPUIS(haswell);break; } /* Celeron/Pentium Haswell without AVX */ -+ } - if (model == 61){ CPUIS(broadwell);break;} - if (model == 62){ CPUIS(ivybridge);break;} -- if (model == 63){ CPUIS(haswell);break;} -- if (model == 69){ CPUIS(haswell);break;} -- if (model == 70){ CPUIS(haswell);break;} -+ if (model == 63){ CPUIS(haswellavx);break;} -+ if (model == 69){ CPUIS(haswellavx);break;} -+ if (model == 70){ CPUIS(haswellavx);break;} - if (model == 71){ CPUIS(broadwell);break;} - if (model == 78){ CPUIS(skylakeavx);break;} - if (model == 79){ CPUIS(broadwell);break;} -diff -ru a/mpn/x86/fat/fat.c b/mpn/x86/fat/fat.c ---- a/mpn/x86/fat/fat.c 2018-07-13 14:49:31.111368100 +0200 -+++ b/mpn/x86/fat/fat.c 2018-07-13 15:08:45.680372700 +0200 -@@ -109,6 +109,7 @@ - #define CPUSETUP_sandybridge CPUVEC_SETUP_nehalem - #define CPUSETUP_ivybridge CPUVEC_SETUP_nehalem - #define CPUSETUP_haswell CPUVEC_SETUP_nehalem -+#define CPUSETUP_haswellavx CPUVEC_SETUP_nehalem - #define CPUSETUP_broadwell CPUVEC_SETUP_nehalem - #define CPUSETUP_skylake CPUVEC_SETUP_nehalem - #define CPUSETUP_skylakeavx CPUVEC_SETUP_nehalem -diff -ru a/mpn/x86_64/fat/fat.c b/mpn/x86_64/fat/fat.c ---- a/mpn/x86_64/fat/fat.c 2018-07-13 14:49:32.356372900 +0200 -+++ b/mpn/x86_64/fat/fat.c 2018-07-13 15:08:46.992374500 +0200 -@@ -103,6 +103,7 @@ - #define CPUSETUP_sandybridge CPUVEC_SETUP_sandybridge - #define CPUSETUP_ivybridge CPUVEC_SETUP_sandybridge;CPUVEC_SETUP_sandybridge_ivybridge - #define CPUSETUP_haswell CPUVEC_SETUP_haswell -+#define CPUSETUP_haswellavx CPUVEC_SETUP_haswell;CPUVEC_SETUP_haswell_avx - #define CPUSETUP_broadwell CPUVEC_SETUP_haswell;CPUVEC_SETUP_haswell_broadwell - #define CPUSETUP_skylake CPUVEC_SETUP_skylake - #define CPUSETUP_skylakeavx CPUVEC_SETUP_skylake;CPUVEC_SETUP_skylake_avx -diff -ru a/mpn/x86_64w/fat/fat.c b/mpn/x86_64w/fat/fat.c ---- a/mpn/x86_64w/fat/fat.c 2018-07-13 14:49:28.284367600 +0200 -+++ b/mpn/x86_64w/fat/fat.c 2018-07-13 15:08:43.058372800 +0200 -@@ -103,6 +103,7 @@ - #define CPUSETUP_sandybridge CPUVEC_SETUP_sandybridge - #define CPUSETUP_ivybridge CPUVEC_SETUP_sandybridge - #define CPUSETUP_haswell CPUVEC_SETUP_haswell -+#define CPUSETUP_haswellavx CPUVEC_SETUP_haswell;CPUVEC_SETUP_haswell_avx - #define CPUSETUP_broadwell CPUVEC_SETUP_haswell;CPUVEC_SETUP_haswell_broadwell - #define CPUSETUP_skylake CPUVEC_SETUP_skylake - #define CPUSETUP_skylakeavx CPUVEC_SETUP_skylake;CPUVEC_SETUP_skylake_avx diff --git a/build/pkgs/mpir/spkg-check.in b/build/pkgs/mpir/spkg-check.in deleted file mode 100644 index 4727de00ffe..00000000000 --- a/build/pkgs/mpir/spkg-check.in +++ /dev/null @@ -1,6 +0,0 @@ -cd src - -# We don't have to set up any environment variables here since the -# Makefiles already have them from 'configure'. - -$MAKE check diff --git a/build/pkgs/mpir/spkg-configure.m4 b/build/pkgs/mpir/spkg-configure.m4 deleted file mode 100644 index fd167864ee7..00000000000 --- a/build/pkgs/mpir/spkg-configure.m4 +++ /dev/null @@ -1,74 +0,0 @@ -SAGE_SPKG_CONFIGURE([mpir], [ -dnl Implement cases for what to do on different options here - _sage_spkg_install_gmp=no - case "$with_mp" in - system) - AC_CHECK_HEADER(gmp.h, [], [_sage_spkg_install_gmp=yes]) - AC_CHECK_HEADER(gmpxx.h, [], [_sage_spkg_install_gmp=yes]) - dnl mpq_cmp_z appeared in GMP 6.1.0 and is used by pynac - AC_SEARCH_LIBS([__gmpq_cmp_z], [gmp], [], - [_sage_spkg_install_gmp=yes]) - SAGE_MP_LIBRARY=gmp - ;; - mpir) - sage_spkg_install_mpir=yes - SAGE_MP_LIBRARY=mpir - ;; - gmp) - _sage_spkg_install_gmp=yes - SAGE_MP_LIBRARY=gmp - ;; - esac -], [], [ - AC_ARG_WITH([mp], - [AS_HELP_STRING([--with-mp=system], - [use the system GMP as multiprecision library, if possible (default)]) -dnl Not indented because whitespace ends up in the help text -AS_HELP_STRING([--with-mp=mpir], - [use the Sage SPKG for MPIR as multiprecision library]) -AS_HELP_STRING([--with-mp=gmp], - [use the Sage SPKG for GMP as multiprecision library])]) - -dnl Just parse the options here - case "$with_mp" in - system) ;; - MPIR|mpir) with_mp=mpir;; - GMP|gmp) with_mp=gmp;; - "") with_mp=system;; - *) - AC_MSG_ERROR([allowed values for --with-mp are system, mpir, or gmp]);; - esac - -dnl Set SAGE_MP_LIBRARY depending on the with_mp option - case "$with_mp" in - mpir) - SAGE_MP_LIBRARY=mpir - ;; - gmp|system) - SAGE_MP_LIBRARY=gmp - ;; - esac - - AC_SUBST([SAGE_MP_LIBRARY], [$SAGE_MP_LIBRARY]) -], [ - if test x$sage_spkg_install_mpir = xyes -o x$_sage_spkg_install_gmp = xyes; then - AC_SUBST(SAGE_GMP_PREFIX, ['$SAGE_LOCAL']) - AC_SUBST(SAGE_GMP_INCLUDE, ['$SAGE_LOCAL/include']) - AC_MSG_RESULT([using $SAGE_MP_LIBRARY SPKG (via --with-mp=$SAGE_MP_LIBRARY)]) - else - dnl If found, we want to get the absolute path to where we - dnl found it for use with some packages (e.g. iml) that need - dnl this information at configure time - AX_ABSOLUTE_HEADER([gmp.h]) - if test x$gl_cv_absolute_gmp_h = x; then - AC_MSG_ERROR(m4_normalize([ - failed to find absolute path to gmp.h despite it being reported - found - ])) - fi - AC_SUBST(SAGE_GMP_INCLUDE, [`AS_DIRNAME($gl_cv_absolute_gmp_h)`]) - AC_SUBST(SAGE_GMP_PREFIX, ['']) - AC_MSG_RESULT([using GMP-compatible library from the system]) - fi -]) - diff --git a/build/pkgs/mpir/spkg-install.in b/build/pkgs/mpir/spkg-install.in deleted file mode 100644 index 01070d1dc3e..00000000000 --- a/build/pkgs/mpir/spkg-install.in +++ /dev/null @@ -1,322 +0,0 @@ -cd src - -############################################################################### -# Previous MPIR installations are only removed after a *successful* (re)build, -# before installing the new one. (Done below.) -############################################################################### - -############################################################################### -# Find out the machine type -############################################################################### - -MACHINE_TYPE_MPIR=$(bash ./config.guess) -if [ $? -ne 0 ]; then - echo >&2 "Error: failed to determine the machine type (mpir-extended)" - exit 1 -fi - -# This is the vanilla config.guess (renamed to configfsf.guess in -# MPIR) file instead of MPIR's version. It is used when -# SAGE_FAT_BINARY is set. -MACHINE_TYPE_DEFAULT=$(bash ./configfsf.guess) -if [ $? -ne 0 ]; then - echo >&2 "Error: failed to determine the machine type (default)" - exit 1 -fi - -echo "Machine type (default): $MACHINE_TYPE_DEFAULT" -echo "Machine type (mpir): $MACHINE_TYPE_MPIR" - -############################################################################### -# Set up environment variables: -############################################################################### - -user_cflags=$CFLAGS # Save them. 'sage-env' sets CC, but not CFLAGS. -required_cflags="" # Additional mandatory settings required by Sage, accumulated below. -user_ldflags=$LDFLAGS # Save them. -required_ldflags="" # Additional mandatory settings required by Sage, accumulated below. -user_abi=$ABI # Just save it. -# In case we changed CPPFLAGS or CXXFLAGS, too, we should save the user's here as well. -# We don't have to add (e.g.) '-m64' to CFLAGS/CPPFLAGS/CXXFLAGS/LDFLAGS, since -# MPIR's 'configure' is smart enough to add it if necessary or appropriate. - - -if [ -z "$CFLAG32" ]; then - CFLAG32="-m32" # Only used in this script, no need to export it. -fi -if [ -z "$CFLAG64" ]; then - CFLAG64="-m64" # Only used in this script, no need to export it. -fi - - -case "$UNAME" in - SunOS) - true;; # Auto-detect ABI - Darwin) - # In some cases (see SAGE_ROOT/spkg/bin/sage-env), on Darwin, - # CC might be set to clang, but MPIR doesn't seem to build - # with clang. - CLANG=`command -v clang` - GCC=`command -v gcc` - if [ -n "$CC" ] && [ "$CC" = "$CLANG" ] && [ -n "$GCC" ] ; then - export CC="$GCC" - fi - # Do not set ABI=32 on MacOS X 10.6 (Darwin 10) and later, since - # there everything defaults to 64-bit: - if [ "`uname -r | sed 's/\..*//'`" -lt 10 ]; then - # Assume MacOS X 10.4 or 10.5 (Darwin 8 or 9); also, PPC CPUs - # are only supported by these, not later versions. - echo "Building a 32-bit version of MPIR, which is the only supported option." - ABI=32 - case "`uname -m`" in - ppc|ppc64|[Pp]ower*) # Apple's 'uname' returns strange strings - # The Darwin assembler rejects code using an - # extended instruction set by default (cf. #8664): - required_cflags="$required_cflags -Wa,-force_cpusubtype_ALL" - ;; - esac - else - # Darwin 10 (MacOS X 10.6) or later. - # We don't have to set ABI here. - echo "Building a 64-bit version of MPIR, which is the default." - fi - ;; # Darwin - Linux) - # MPIR fails to build on 32-bit operating systems running on - # 64-bit CPUs if CFLAGS happen to contain '-m32' and ABI is - # *not* set, so we set it here if necessary: - # (Cf. http://groups.google.com/group/mpir-devel/browse_thread/thread/46ccdc5dfc3485cd#) - # Note: This code snippet could in principle be moved out of the - # Linux branch, but since we already set ABI for other - # OSs above (and print an according message), it's here. - if [ -z "$ABI" ]; then - echo "int main(){return 0;}" > foo.c - # Try building and running a 64-bit executable: - # (Building usually succeeds even on 32-bit systems, unless e.g. a 32-bit - # CPU is explicitly selected by CFLAGS, while running does not.) - if $CC $CFLAGS $CFLAG64 -o foo foo.c 2>/dev/null && ./foo 2>/dev/null; then - # We can run 64-bit executables. - # Setting ABI=64 shouldn't be necessary, but shouldn't hurt either. - echo "Building a 64-bit version of MPIR." - case "`uname -m`" in - ppc*) ABI=mode64;; - *) ABI=64;; - esac - elif $CC $CFLAGS $CFLAG32 -o foo foo.c 2>/dev/null && ./foo 2>/dev/null; then - # We're on a 32-bit OS which cannot run 64-bit executables. - echo "Building a 32-bit version of MPIR." - ABI=32 - else - # It seems the compiler does not support -m32 nor -m64 (e.g. - # GCC on Itanium rejects both); do not set ABI at all. - echo "Your compiler does not support '$CFLAG32' nor '$CFLAG64'. Leaving ABI unset." - fi - rm -f foo foo.c - fi - ;; # Linux - CYGWIN) - if uname -a | grep x86_64 ; then - ABI=64 - else - ABI=32 - fi - ;; - *) # e.g. AIX or HP-UX - echo >&2 "Warning: Your platform ($UNAME) isn't yet explicitly supported" \ - "by this MPIR spkg, i.e., by Sage's part of it." -esac - -# MPIR 2.7.2 does not know about ppc64le and confuses it with plain -# ppc64. We need to disable specific powerpc64 assembly. -if [ "`uname -m`" = ppc64le ]; then - export MPN_PATH=generic -fi - -# Workaround old GNU as version by disabling assembly use. -if [ "$UNAME" = Linux ]; then - as_version=`$AS --version | head -1 | awk 'NF>1{print $NF}'` - as_version_major=${as_version%%.*} - as_version_rest=${as_version#*.} - as_version_minor=${as_version_rest%%.*} - if [ $as_version_major -lt 2 ] || \ - [ $as_version_major -eq 2 -a $as_version_minor -lt 24 ]; then - echo "Disable use of assembly because of GNU as <= 2.23." - export MPN_PATH=generic - if [ "$SAGE_FAT_BINARY" = "yes" ]; then - echo "Cannot build with SAGE_FAT_BINARY=yes." - exit 1 - fi - fi -fi - -# Work around a bug in GCC 4.7.0 which breaks the build on Itanium CPUs. -# See #12765, #12751, and http://gcc.gnu.org/bugzilla/show_bug.cgi?id=48496 -if [ "`uname -m`" = ia64 ] && [ "`testcc.sh $CC`" = GCC ] ; then - gcc_version=`$CC -dumpversion` - case "$gcc_version" in - 4.7.0) - required_cflags="$required_cflags -O0 -finline-functions -fschedule-insns" - echo >&2 "Warning: Disabling almost all optimization due to a bug in GCC 4.7.0" - echo >&2 " on Itanium, which otherwise would break the build." - echo >&2 " See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=48496" - echo >&2 " for current status and further details." - ;; - esac -fi - -export ABI CFLAGS CXXFLAGS LDFLAGS # Partially redundant, but safe(r). -# We don't export CPPFLAGS here, since we don't (have to) modify them. - -############################################################################### -# Now configure MPIR, eventually modifying CFLAGS [further]: -############################################################################### - -MPIR_CONFIGURE="--enable-shared $MPIR_CONFIGURE" -MPIR_CONFIGURE="--enable-gmpcompat $MPIR_CONFIGURE" - -# Fake yasm installation on non-x86[_64] system. -# It is not installed but not needed. -case `uname -m` in - i[3456]86|x86_64|amd64) - ;; - *) # Anything else - echo "Disabling check for yasm on non-x86[_64] system." - MPIR_CONFIGURE="--with-yasm=/bin/true $MPIR_CONFIGURE" - ;; -esac - -# Also build the static library to be used by e.g. ECM -# unless we are on Cygwin where we can only build a shared -# or a static library but not both: -if [ "$UNAME" = "CYGWIN" ]; then - echo "Building MPIR with the C++ interface and (only) shared libraries." - MPIR_CONFIGURE="--enable-cxx $MPIR_CONFIGURE --disable-static" -else - echo "Building MPIR with the C++ interface and (also) static libraries." - MPIR_CONFIGURE="--enable-cxx --enable-static $MPIR_CONFIGURE" -fi - -# If SAGE_FAT_BINARY is enabled, then add --enable-fat to configure -# options on Linux x86 systems. On other systems, fat binaries are not -# supported. There, we specify a build architecture which doesn't -# have a CPU name in it. -if [ "$SAGE_FAT_BINARY" = "yes" ]; then - case "$UNAME-`uname -m`" in - Linux-i[3456]86) - echo "** Building with \"fat binary\" support for 32-bit CPUs **" - MPIR_CONFIGURE="--enable-fat $MPIR_CONFIGURE" - ;; - Linux-x86_64|Linux-amd64) - echo "** Building with \"fat binary\" support for 64-bit CPUs **" - MPIR_CONFIGURE="--enable-fat $MPIR_CONFIGURE" - ;; - *) # Anything else - echo "** Building a generic binary (not assuming any specific CPU) **" - MPIR_CONFIGURE="--build=$MACHINE_TYPE_DEFAULT $MPIR_CONFIGURE" - ;; - esac -fi - - -# Pre-configure MPIR to get the settings it would use if CFLAGS were empty: -echo "------------------------------------------------------------------------" -echo "Configuring MPIR with empty CFLAGS to determine the defaults:" -(unset CFLAGS CPPFLAGS CXXFLAGS && ./configure $MPIR_CONFIGURE) -if [ $? -ne 0 ]; then - echo >&2 "Error configuring MPIR (with CFLAGS unset)." - echo >&2 "Consult `pwd`/config.log for for details." - exit 1 -fi - - -# Read MPIR-selected flags from Makefile -mpir_cc=`sed -n 's/^CC *= *//p' Makefile` -mpir_cflags=`sed -n 's/^CFLAGS *= *//p' Makefile` -if [ -z "$mpir_cc" ]; then - echo >&2 "Error: failed to determine \$CC from Makefile" - echo >&2 "Please report this to " - exit 1 -fi -echo "------------------------------------------------------------------------" -echo "Settings chosen by MPIR when configuring with CFLAGS unset:" -echo " CC: $mpir_cc" -echo " CFLAGS: $mpir_cflags" -echo "Settings added by Sage to build MPIR, taking into account SAGE_DEBUG etc.:" -echo " CFLAGS: $required_cflags" # Might be empty. -echo " LDFLAGS: $required_ldflags" # Might be empty. -echo " ABI: $ABI" # Might be empty, or the one specified by the user. -echo "Settings from the \"global\" environment:" -echo " CC: $CC" # Set by Sage, maybe overridden by the user. -echo " CFLAGS: $user_cflags" -echo " LDFLAGS: $user_ldflags" -echo " ABI: $user_abi" -echo " (CPP, CPPFLAGS, CXX and CXXFLAGS are listed below; these don't get modified.)" - -# Finally: use MPIR's flags, plus those required by Sage for the -# package to build properly, plus those specified by the user. -CFLAGS="$mpir_cflags $required_cflags $user_cflags" -LDFLAGS="$required_ldflags $user_ldflags" - -echo "Finally using the following settings:" -echo " CC=$CC" -echo " CFLAGS=$CFLAGS" -echo " CPP=$CPP" -echo " CPPFLAGS=$CPPFLAGS" -echo " CXX=$CXX" -echo " CXXFLAGS=$CXXFLAGS" -echo " LDFLAGS=$LDFLAGS" -echo " ABI=$ABI" -echo "(These settings may still get overridden by 'configure' or Makefiles.)" - -############################################################################### -# Now really configure MPIR with proper settings: -############################################################################### - -# We also add '--libdir="$SAGE_LOCAL/lib"' below, since newer autotools may -# otherwise put the libraries into .../lib64 on 64-bit systems (cf. #12131). - -echo "------------------------------------------------------------------------" -echo "Configuring MPIR with the following options:" -echo " --prefix=\"$SAGE_LOCAL\" --libdir=\"$SAGE_LOCAL/lib\" $MPIR_CONFIGURE" -echo "You can set MPIR_CONFIGURE to pass additional parameters." - -# Clear the cache of the previous configure run -find . -name config.cache -exec rm -f {} \; - -sdh_configure $MPIR_CONFIGURE - -############################################################################### -# Now build MPIR: -############################################################################### - -sdh_make -echo "Build succeeded." - -############################################################################### -# Remove previous installation (if any), *after* a successful build: -############################################################################### - -echo "Removing old GMP/MPIR headers..." -rm -f "$SAGE_LOCAL"/include/{gmp,mpir}*.h - -# Do NOT delete old GMP/MPIR shared libraries as Sage's versions of libraries -# used by GCC might still refer to them, such that their deletion would break -# GCC inside Sage. (We could perhaps remove libmpir* though.) -if false; then - echo "Removing old GMP/MPIR libraries..." - rm -f "$SAGE_LOCAL"/lib/lib{gmp,mpir}* -else - echo "Not removing old GMP/MPIR shared libraries, as other libraries" - echo "and executables might still refer to them:" - ls -l "$SAGE_LOCAL"/lib/lib{gmp,mpir}* - echo "(Libraries with the same version number will get updated though.)" -fi - -# Mark GMP as not installed (since we will overwrite it) -rm -f "$SAGE_SPKG_INST"/gmp-* - -############################################################################### -# Now install MPIR: -############################################################################### - -sdh_make_install diff --git a/build/pkgs/mpir/spkg-src b/build/pkgs/mpir/spkg-src deleted file mode 100755 index 8dde1a84941..00000000000 --- a/build/pkgs/mpir/spkg-src +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env bash - -set -e - -if [ -z "$SAGE_DISTFILES" ]; then - echo >&2 "SAGE_DISTFILES undefined ... exiting" - echo >&2 "Maybe run 'sage --sh'?" - exit 1 -fi - -set -e - -PACKAGEVERSION=`cat $SAGE_ROOT/build/pkgs/mpir/package-version.txt` -MPIRVERSION=mpir-`echo $PACKAGEVERSION | sed 's/-.*//'` -TARBALLVERSION="mpir-$PACKAGEVERSION" - -# Get the sources -cd "$SAGE_DISTFILES" -rm -rf mpir -git clone https://github.com/wbhart/mpir.git mpir -cd mpir -git checkout 644faf502c56f97d9accd301965fc57d6ec70868 - -# Add auto-generated files -./autogen.sh - -# Create the tarball -./configure -make dist-bzip2 - -# Unpack the tarball, remove some unwanted stuff -tar xjf $MPIRVERSION.tar.bz2 -find $MPIRVERSION -name 'build.vc*' -prune -exec rm -r {} \; - -# Repackage the tarball and put it in SAGE_DISTFILES -mv $MPIRVERSION $TARBALLVERSION -tar c $TARBALLVERSION | bzip2 --best >../$TARBALLVERSION.tar.bz2 -sage-package fix-checksum mpir - -# Cleanup -cd "$SAGE_DISTFILES" -rm -rf mpir -echo "New MPIR tarball is ready in $SAGE_DISTFILES/$TARBALLVERSION.tar.bz2" diff --git a/build/pkgs/mpir/type b/build/pkgs/mpir/type deleted file mode 100644 index a6a7b9cd726..00000000000 --- a/build/pkgs/mpir/type +++ /dev/null @@ -1 +0,0 @@ -standard diff --git a/build/pkgs/ntl/spkg-configure.m4 b/build/pkgs/ntl/spkg-configure.m4 index ba019d712de..f27ebc1bba7 100644 --- a/build/pkgs/ntl/spkg-configure.m4 +++ b/build/pkgs/ntl/spkg-configure.m4 @@ -1,7 +1,7 @@ SAGE_SPKG_CONFIGURE([ntl], [ m4_pushdef(SAGE_NTL_VERSION_MAJOR, [10]) m4_pushdef(SAGE_NTL_VERSION_MINOR, [3]) - SAGE_SPKG_DEPCHECK([gmp mpir gcc], [ + SAGE_SPKG_DEPCHECK([gmp gcc], [ AC_CHECK_HEADER([NTL/ZZ.h], [], [sage_spkg_install_ntl=yes]) AC_MSG_CHECKING([whether we can link a program using NTL]) NTL_SAVED_LIBS=$LIBS diff --git a/build/pkgs/pari/spkg-configure.m4 b/build/pkgs/pari/spkg-configure.m4 index 0baf6e427b6..9721849e7ba 100644 --- a/build/pkgs/pari/spkg-configure.m4 +++ b/build/pkgs/pari/spkg-configure.m4 @@ -1,7 +1,7 @@ SAGE_SPKG_CONFIGURE([pari], [ dnl See gp_version below on how the version is computed from MAJV.MINV.PATCHV m4_pushdef([SAGE_PARI_MINVER],["134401"]) - SAGE_SPKG_DEPCHECK([gmp mpir readline], [ + SAGE_SPKG_DEPCHECK([gmp readline], [ AC_PATH_PROG([GP], [gp]) if test x$GP = x; then dnl GP test AC_MSG_NOTICE([gp is not found]) diff --git a/build/pkgs/ppl/spkg-configure.m4 b/build/pkgs/ppl/spkg-configure.m4 index d2538903714..2f986f12168 100644 --- a/build/pkgs/ppl/spkg-configure.m4 +++ b/build/pkgs/ppl/spkg-configure.m4 @@ -1,5 +1,5 @@ SAGE_SPKG_CONFIGURE([ppl], [ - SAGE_SPKG_DEPCHECK([gcc glpk gmp mpir], [ + SAGE_SPKG_DEPCHECK([gcc glpk gmp], [ # If our dependencies come from the system, then we can use the # system ppl, too. This macro works sort-of like the # PKG_CHECK_MODULES macro, defining e.g. PPL_CFLAGS when a diff --git a/build/pkgs/yasm/spkg-configure.m4 b/build/pkgs/yasm/spkg-configure.m4 index bc85c7ce45c..738443a3a1d 100644 --- a/build/pkgs/yasm/spkg-configure.m4 +++ b/build/pkgs/yasm/spkg-configure.m4 @@ -12,8 +12,8 @@ SAGE_SPKG_CONFIGURE( AC_MSG_RESULT($ac_cv_path_YASM)], [dnl REQUIRED-CHECK AS_CASE("$host_cpu", [i@<:@0-9@:>@86|x86_64|amd64], [], [sage_require_yasm=no]) - AC_REQUIRE([SAGE_SPKG_CONFIGURE_MPIR]) - AS_IF([test x$sage_spkg_install_mpir = xno], [ + AC_REQUIRE([SAGE_SPKG_CONFIGURE_GMP]) + AS_IF([test x$sage_spkg_install_gmp = xno], [ sage_require_yasm=no ]) ] diff --git a/build/pkgs/zn_poly/spkg-configure.m4 b/build/pkgs/zn_poly/spkg-configure.m4 index ba3fd95a96a..c3e47c7621b 100644 --- a/build/pkgs/zn_poly/spkg-configure.m4 +++ b/build/pkgs/zn_poly/spkg-configure.m4 @@ -1,5 +1,5 @@ SAGE_SPKG_CONFIGURE([zn_poly], [ - SAGE_SPKG_DEPCHECK([gmp mpir], [ + SAGE_SPKG_DEPCHECK([gmp], [ AC_CHECK_HEADER([zn_poly/zn_poly.h], [ AC_SEARCH_LIBS([zn_mod_init], [zn_poly], [ ], [sage_spkg_install_zn_poly=yes]) From 81331d7af671345c3159662bc113b094b8660423 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 22 Sep 2021 18:54:14 -0700 Subject: [PATCH 121/359] build/pkgs/yasm: Remove (was mpir dependency) --- build/pkgs/yasm/SPKG.rst | 41 --------------------------- build/pkgs/yasm/checksums.ini | 4 --- build/pkgs/yasm/dependencies | 1 - build/pkgs/yasm/distros/alpine.txt | 1 - build/pkgs/yasm/distros/conda.txt | 1 - build/pkgs/yasm/distros/cygwin.txt | 1 - build/pkgs/yasm/distros/debian.txt | 1 - build/pkgs/yasm/distros/fedora.txt | 1 - build/pkgs/yasm/distros/freebsd.txt | 1 - build/pkgs/yasm/distros/homebrew.txt | 1 - build/pkgs/yasm/distros/macports.txt | 1 - build/pkgs/yasm/distros/opensuse.txt | 1 - build/pkgs/yasm/distros/repology.txt | 1 - build/pkgs/yasm/distros/slackware.txt | 1 - build/pkgs/yasm/distros/void.txt | 1 - build/pkgs/yasm/package-version.txt | 1 - build/pkgs/yasm/spkg-check.in | 5 ---- build/pkgs/yasm/spkg-configure.m4 | 20 ------------- build/pkgs/yasm/spkg-install.in | 5 ---- build/pkgs/yasm/type | 1 - 20 files changed, 90 deletions(-) delete mode 100644 build/pkgs/yasm/SPKG.rst delete mode 100644 build/pkgs/yasm/checksums.ini delete mode 100644 build/pkgs/yasm/dependencies delete mode 100644 build/pkgs/yasm/distros/alpine.txt delete mode 100644 build/pkgs/yasm/distros/conda.txt delete mode 100644 build/pkgs/yasm/distros/cygwin.txt delete mode 100644 build/pkgs/yasm/distros/debian.txt delete mode 100644 build/pkgs/yasm/distros/fedora.txt delete mode 100644 build/pkgs/yasm/distros/freebsd.txt delete mode 100644 build/pkgs/yasm/distros/homebrew.txt delete mode 100644 build/pkgs/yasm/distros/macports.txt delete mode 100644 build/pkgs/yasm/distros/opensuse.txt delete mode 100644 build/pkgs/yasm/distros/repology.txt delete mode 100644 build/pkgs/yasm/distros/slackware.txt delete mode 100644 build/pkgs/yasm/distros/void.txt delete mode 100644 build/pkgs/yasm/package-version.txt delete mode 100644 build/pkgs/yasm/spkg-check.in delete mode 100644 build/pkgs/yasm/spkg-configure.m4 delete mode 100644 build/pkgs/yasm/spkg-install.in delete mode 100644 build/pkgs/yasm/type diff --git a/build/pkgs/yasm/SPKG.rst b/build/pkgs/yasm/SPKG.rst deleted file mode 100644 index 0e1de168678..00000000000 --- a/build/pkgs/yasm/SPKG.rst +++ /dev/null @@ -1,41 +0,0 @@ -yasm: An assembler for the x86 and AMD64 instruction sets -========================================================= - -Description ------------ - -Yasm is a complete rewrite of the NASM assembler under the “new” BSD -License (some portions are under other licenses, see COPYING for -details). - -Yasm currently supports the x86 and AMD64 instruction sets, accepts NASM -and GAS assembler syntaxes, outputs binary, ELF32, ELF64, 32 and 64-bit -Mach-O, RDOFF2, COFF, Win32, and Win64 object formats, and generates -source debugging information in STABS, DWARF 2, and CodeView 8 formats. - -Yasm can be easily integrated into Visual Studio 2005/2008 and 2010 for -assembly of NASM or GAS syntax code into Win32 or Win64 object files. - -See https://yasm.tortall.net - -License -------- - -Yasm is licensed under the 2-clause and 3-clause “revised” BSD licenses, -with one exception: the Bit::Vector module used by the mainline version -of Yasm to implement its large integer and machine-independent floating -point support is triple-licensed under the Artistic license, GPL, and -LGPL. The “yasm-nextgen” codebase uses a different BSD-licensed -implementation and is thus entirely under BSD-equivalent licenses. The -full text of the licenses are provided in the Yasm source distribution. - - -Upstream Contact ----------------- - -- https://yasm.tortall.net - -Dependencies ------------- - -- none diff --git a/build/pkgs/yasm/checksums.ini b/build/pkgs/yasm/checksums.ini deleted file mode 100644 index 5889d0ce114..00000000000 --- a/build/pkgs/yasm/checksums.ini +++ /dev/null @@ -1,4 +0,0 @@ -tarball=yasm-VERSION.tar.gz -sha1=b7574e9f0826bedef975d64d3825f75fbaeef55e -md5=fc9e586751ff789b34b1f21d572d96af -cksum=3388492465 diff --git a/build/pkgs/yasm/dependencies b/build/pkgs/yasm/dependencies deleted file mode 100644 index 2f9f3849682..00000000000 --- a/build/pkgs/yasm/dependencies +++ /dev/null @@ -1 +0,0 @@ -# no dependencies diff --git a/build/pkgs/yasm/distros/alpine.txt b/build/pkgs/yasm/distros/alpine.txt deleted file mode 100644 index eff8d5c7abd..00000000000 --- a/build/pkgs/yasm/distros/alpine.txt +++ /dev/null @@ -1 +0,0 @@ -yasm diff --git a/build/pkgs/yasm/distros/conda.txt b/build/pkgs/yasm/distros/conda.txt deleted file mode 100644 index eff8d5c7abd..00000000000 --- a/build/pkgs/yasm/distros/conda.txt +++ /dev/null @@ -1 +0,0 @@ -yasm diff --git a/build/pkgs/yasm/distros/cygwin.txt b/build/pkgs/yasm/distros/cygwin.txt deleted file mode 100644 index eff8d5c7abd..00000000000 --- a/build/pkgs/yasm/distros/cygwin.txt +++ /dev/null @@ -1 +0,0 @@ -yasm diff --git a/build/pkgs/yasm/distros/debian.txt b/build/pkgs/yasm/distros/debian.txt deleted file mode 100644 index eff8d5c7abd..00000000000 --- a/build/pkgs/yasm/distros/debian.txt +++ /dev/null @@ -1 +0,0 @@ -yasm diff --git a/build/pkgs/yasm/distros/fedora.txt b/build/pkgs/yasm/distros/fedora.txt deleted file mode 100644 index eff8d5c7abd..00000000000 --- a/build/pkgs/yasm/distros/fedora.txt +++ /dev/null @@ -1 +0,0 @@ -yasm diff --git a/build/pkgs/yasm/distros/freebsd.txt b/build/pkgs/yasm/distros/freebsd.txt deleted file mode 100644 index d04eee4fbc4..00000000000 --- a/build/pkgs/yasm/distros/freebsd.txt +++ /dev/null @@ -1 +0,0 @@ -devel/yasm diff --git a/build/pkgs/yasm/distros/homebrew.txt b/build/pkgs/yasm/distros/homebrew.txt deleted file mode 100644 index eff8d5c7abd..00000000000 --- a/build/pkgs/yasm/distros/homebrew.txt +++ /dev/null @@ -1 +0,0 @@ -yasm diff --git a/build/pkgs/yasm/distros/macports.txt b/build/pkgs/yasm/distros/macports.txt deleted file mode 100644 index eff8d5c7abd..00000000000 --- a/build/pkgs/yasm/distros/macports.txt +++ /dev/null @@ -1 +0,0 @@ -yasm diff --git a/build/pkgs/yasm/distros/opensuse.txt b/build/pkgs/yasm/distros/opensuse.txt deleted file mode 100644 index eff8d5c7abd..00000000000 --- a/build/pkgs/yasm/distros/opensuse.txt +++ /dev/null @@ -1 +0,0 @@ -yasm diff --git a/build/pkgs/yasm/distros/repology.txt b/build/pkgs/yasm/distros/repology.txt deleted file mode 100644 index eff8d5c7abd..00000000000 --- a/build/pkgs/yasm/distros/repology.txt +++ /dev/null @@ -1 +0,0 @@ -yasm diff --git a/build/pkgs/yasm/distros/slackware.txt b/build/pkgs/yasm/distros/slackware.txt deleted file mode 100644 index eff8d5c7abd..00000000000 --- a/build/pkgs/yasm/distros/slackware.txt +++ /dev/null @@ -1 +0,0 @@ -yasm diff --git a/build/pkgs/yasm/distros/void.txt b/build/pkgs/yasm/distros/void.txt deleted file mode 100644 index eff8d5c7abd..00000000000 --- a/build/pkgs/yasm/distros/void.txt +++ /dev/null @@ -1 +0,0 @@ -yasm diff --git a/build/pkgs/yasm/package-version.txt b/build/pkgs/yasm/package-version.txt deleted file mode 100644 index 05749212e36..00000000000 --- a/build/pkgs/yasm/package-version.txt +++ /dev/null @@ -1 +0,0 @@ -1.3.0.p0 diff --git a/build/pkgs/yasm/spkg-check.in b/build/pkgs/yasm/spkg-check.in deleted file mode 100644 index ae888d81474..00000000000 --- a/build/pkgs/yasm/spkg-check.in +++ /dev/null @@ -1,5 +0,0 @@ -cd src - -# -j1 needed to avoid a possible race condition in the tests -# see https://trac.sagemath.org/ticket/23217 -$MAKE -j1 check diff --git a/build/pkgs/yasm/spkg-configure.m4 b/build/pkgs/yasm/spkg-configure.m4 deleted file mode 100644 index 738443a3a1d..00000000000 --- a/build/pkgs/yasm/spkg-configure.m4 +++ /dev/null @@ -1,20 +0,0 @@ -SAGE_SPKG_CONFIGURE( - [yasm], - # Yasm is only needed on x86(_64) systems; check also for system yasm which - # must support "adox" (new Skylake instruction) - [AC_MSG_CHECKING([for yasm supporting the adox instruction]) - AC_PATH_PROGS_FEATURE_CHECK([YASM], [yasm], - [[{ echo "BITS 64"; echo "adox rax, rax"; } | ${ac_path_YASM} - -o /dev/null >/dev/null 2>/dev/null && - ac_cv_path_YASM=${ac_path_YASM} && - ac_path_YASM_found=: - ]], - [sage_spkg_install_yasm=yes; ac_cv_path_YASM=no]) - AC_MSG_RESULT($ac_cv_path_YASM)], - [dnl REQUIRED-CHECK - AS_CASE("$host_cpu", [i@<:@0-9@:>@86|x86_64|amd64], [], [sage_require_yasm=no]) - AC_REQUIRE([SAGE_SPKG_CONFIGURE_GMP]) - AS_IF([test x$sage_spkg_install_gmp = xno], [ - sage_require_yasm=no - ]) - ] -) diff --git a/build/pkgs/yasm/spkg-install.in b/build/pkgs/yasm/spkg-install.in deleted file mode 100644 index a863950189e..00000000000 --- a/build/pkgs/yasm/spkg-install.in +++ /dev/null @@ -1,5 +0,0 @@ -cd src - -sdh_configure -sdh_make -sdh_make_install diff --git a/build/pkgs/yasm/type b/build/pkgs/yasm/type deleted file mode 100644 index a6a7b9cd726..00000000000 --- a/build/pkgs/yasm/type +++ /dev/null @@ -1 +0,0 @@ -standard From fabdbb3144335ee7fb33957f78d4591b2c176e42 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 22 Sep 2021 20:34:00 -0700 Subject: [PATCH 122/359] build/pkgs/*/SPKG.rst: Clear out redundant 'Dependencies' sections --- build/pkgs/arb/SPKG.rst | 11 ----------- build/pkgs/cddlib/SPKG.rst | 5 ----- build/pkgs/cocoalib/SPKG.rst | 11 ----------- build/pkgs/e_antic/SPKG.rst | 7 ------- build/pkgs/ecm/SPKG.rst | 12 ++---------- build/pkgs/fflas_ffpack/spkg-configure.m4 | 2 -- build/pkgs/flint/SPKG.rst | 7 ------- build/pkgs/gcc/SPKG.rst | 14 -------------- 8 files changed, 2 insertions(+), 67 deletions(-) diff --git a/build/pkgs/arb/SPKG.rst b/build/pkgs/arb/SPKG.rst index 404b21eb1db..cff49ddb95b 100644 --- a/build/pkgs/arb/SPKG.rst +++ b/build/pkgs/arb/SPKG.rst @@ -25,14 +25,3 @@ Upstream Contact - https://arblib.org/ - http://github.com/fredrik-johansson/arb/ - -Dependencies ------------- - -- FLINT -- MPIR or GMP -- MPFR - - -Special Update/Build Instructions ---------------------------------- diff --git a/build/pkgs/cddlib/SPKG.rst b/build/pkgs/cddlib/SPKG.rst index 89915efe311..6ab9a303cdd 100644 --- a/build/pkgs/cddlib/SPKG.rst +++ b/build/pkgs/cddlib/SPKG.rst @@ -31,8 +31,3 @@ Upstream Contact ---------------- https://github.com/cddlib/cddlib - -Dependencies ------------- - -- gmp (or its fork mpir) diff --git a/build/pkgs/cocoalib/SPKG.rst b/build/pkgs/cocoalib/SPKG.rst index 3afd8a68286..783c6cc7126 100644 --- a/build/pkgs/cocoalib/SPKG.rst +++ b/build/pkgs/cocoalib/SPKG.rst @@ -19,14 +19,3 @@ Upstream Contact - Email: cocoa@dima.unige.it - Website: http://cocoa.dima.unige.it/ - Releases: http://cocoa.dima.unige.it/cocoalib/ - -Dependencies ------------- - -- GMP/MPIR - - -Special Update/Build Instructions ---------------------------------- - -None. diff --git a/build/pkgs/e_antic/SPKG.rst b/build/pkgs/e_antic/SPKG.rst index 32dfecbef0b..005a25b7e13 100644 --- a/build/pkgs/e_antic/SPKG.rst +++ b/build/pkgs/e_antic/SPKG.rst @@ -19,10 +19,3 @@ Upstream Contact ---------------- - https://github.com/videlec/e-antic - -Dependencies ------------- - -- GMP/MPIR -- FLINT -- ARB diff --git a/build/pkgs/ecm/SPKG.rst b/build/pkgs/ecm/SPKG.rst index f8d0e352e56..2d88c659ae1 100644 --- a/build/pkgs/ecm/SPKG.rst +++ b/build/pkgs/ecm/SPKG.rst @@ -19,13 +19,6 @@ Upstream Contact - ecm-discuss@lists.gforge.inria.fr (requires subscription) -Dependencies ------------- - -- GMP/MPIR (Note: Python is \*not\* required for ordinary builds.) -- GNU patch - - Special Update/Build Instructions --------------------------------- @@ -47,11 +40,10 @@ Special Update/Build Instructions Note that this doesn't affect the packages' selection of processor- specific optimized [assembly] code. 'spkg-install' already reads the settings from Sage's and also a - system-wide GMP / MPIR now, but doesn't (yet) use all of them. + system-wide GMP now, but doesn't (yet) use all of them. If SAGE_FAT_BINARY="yes", we should avoid too specific settings of "-mcpu=...", and perhaps pass a more generic "--host=..." to - 'configure'. (MPIR honors '--enable-fat' to some extent, but this - option isn't used on anything other than x86 / x86_64.) + 'configure'. - We currently work around a linker bug on MacOS X 10.5 PPC (with GCC 4.2.1) which breaks 'configure' if debug symbols are enabled. diff --git a/build/pkgs/fflas_ffpack/spkg-configure.m4 b/build/pkgs/fflas_ffpack/spkg-configure.m4 index f107ff5cf15..6f6221cbb4f 100644 --- a/build/pkgs/fflas_ffpack/spkg-configure.m4 +++ b/build/pkgs/fflas_ffpack/spkg-configure.m4 @@ -1,6 +1,4 @@ SAGE_SPKG_CONFIGURE([fflas_ffpack], [ - # fflas-lapack uses whatever multi-precision library givaro uses, - # either gmp or mpir. SAGE_SPKG_DEPCHECK([atlas givaro gmp openblas], [ # If our dependencies come from the system, then we can use # the system fflas-ffpack, too. Use pkg-config to find a diff --git a/build/pkgs/flint/SPKG.rst b/build/pkgs/flint/SPKG.rst index 146c6ac1c82..f91de70d1ff 100644 --- a/build/pkgs/flint/SPKG.rst +++ b/build/pkgs/flint/SPKG.rst @@ -21,10 +21,3 @@ Upstream Contact - flint-devel Gougle Group (http://groups.google.co.uk/group/flint-devel) - William Hart - -Dependencies ------------- - -- MPIR -- MPFR -- NTL diff --git a/build/pkgs/gcc/SPKG.rst b/build/pkgs/gcc/SPKG.rst index 6004b986078..1f5684b86b2 100644 --- a/build/pkgs/gcc/SPKG.rst +++ b/build/pkgs/gcc/SPKG.rst @@ -16,17 +16,3 @@ Upstream Contact ---------------- https://gcc.gnu.org/ - -Dependencies ------------- - -- zlib -- MPIR -- MPFR -- MPC - - -Special Update/Build Instructions ---------------------------------- - -None. From 724c3ffd97682ced5521000df878a426a4901bd3 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 22 Sep 2021 21:13:30 -0700 Subject: [PATCH 123/359] src/doc/en/developer/portability_testing.rst: Remove references to package yasm --- src/doc/en/developer/portability_testing.rst | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/doc/en/developer/portability_testing.rst b/src/doc/en/developer/portability_testing.rst index 204c173dc52..e6a61ebeb58 100644 --- a/src/doc/en/developer/portability_testing.rst +++ b/src/doc/en/developer/portability_testing.rst @@ -220,10 +220,10 @@ Using Sage's database of equivalent distribution packages At the end of the ``./configure`` run, Sage issued a message like the following:: - configure: notice: the following SPKGs did not find equivalent system packages: arb boost boost_cropped bzip2 ... yasm zeromq zlib + configure: notice: the following SPKGs did not find equivalent system packages: arb boost_cropped bzip2 ... zeromq zlib checking for the package system in use... debian configure: hint: installing the following system packages is recommended and may avoid building some of the above SPKGs from source: - configure: $ sudo apt-get install libflint-arb-dev ... yasm libzmq3-dev libz-dev + configure: $ sudo apt-get install libflint-arb-dev ... libzmq3-dev libz-dev configure: After installation, re-run configure using: configure: $ ./config.status --recheck && ./config.status @@ -248,7 +248,7 @@ system, in particular a list of installed packages and their versions. Let us install a subset of these packages:: - root@39d693b2a75d:/sage# apt-get install libbz2-dev bzip2 yasm libz-dev + root@39d693b2a75d:/sage# apt-get install libbz2-dev bzip2 libz-dev Reading package lists... Done ... Setting up zlib1g-dev:amd64 (1:1.2.11.dfsg-0ubuntu2) ... @@ -285,8 +285,8 @@ have no access to the worktree:: root@73987568712c:/# cd sage root@73987568712c:/sage# command -v gcc /usr/bin/gcc - root@73987568712c:/sage# command -v yasm - /usr/bin/yasm + root@73987568712c:/sage# command -v bunzip2 + /usr/bin/bunzip2 root@73987568712c:/sage# ^D [mkoeppe@sage worktree-ubuntu-latest]$ @@ -337,7 +337,7 @@ image...:: Then, to install system packages...:: ... - RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -qqq --no-install-recommends --yes binutils make m4 perl python3 ... yasm libzmq3-dev libz-dev && apt-get clean + RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -qqq --no-install-recommends --yes binutils make m4 perl python3 ... libzmq3-dev libz-dev && apt-get clean Then, to bootstrap and configure...:: @@ -852,10 +852,10 @@ an isolated copy of Homebrew with all prerequisites for bootstrapping:: checking for a BSD-compatible install... /usr/bin/install -c checking whether build environment is sane... yes ... - configure: notice: the following SPKGs did not find equivalent system packages: arb cbc cliquer ... tachyon xz yasm zeromq + configure: notice: the following SPKGs did not find equivalent system packages: arb cbc cliquer ... tachyon xz zeromq checking for the package system in use... homebrew configure: hint: installing the following system packages is recommended and may avoid building some of the above SPKGs from source: - configure: $ brew install cmake gcc gsl mpfi ninja openblas gpatch r readline xz yasm zeromq + configure: $ brew install cmake gcc gsl mpfi ninja openblas gpatch r readline xz zeromq ... sage-logger -p 'sage-spkg -y -o lrslib-062+autotools-2017-03-03.p1' '.../worktree-local/logs/pkgs/lrslib-062+autotools-2017-03-03.p1.log' [lrslib-062+autotools-2017-03-03.p1] installing. Log file: .../worktree-local/logs/pkgs/lrslib-062+autotools-2017-03-03.p1.log From 519dc83bc151b00a07d7e534d392f1139c615696 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 22 Sep 2021 21:16:16 -0700 Subject: [PATCH 124/359] m4/sage_spkg_configure.m4: In documentation, do not use yasm as an example --- m4/sage_spkg_configure.m4 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/m4/sage_spkg_configure.m4 b/m4/sage_spkg_configure.m4 index d8b64f831fb..76d5f4b8e2b 100644 --- a/m4/sage_spkg_configure.m4 +++ b/m4/sage_spkg_configure.m4 @@ -29,8 +29,8 @@ # # - REQUIRED-CHECK - this checks whether or not the package is a required # dependency of Sage at all, depending typically on the platform. Some -# packages (e.g. yasm, among others) are only dependencies on certain -# platforms, and otherwise do not need to be checked for at all. If +# packages (e.g. sqlite) are only dependencies in some circumstances +# and otherwise do not need to be checked for at all. If # a REQUIRED-CHECK determines that the package is not required it sets # sage_require_="no". # From 01406bfea4ce7469c1d6520713f5952b6f133d2a Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 22 Sep 2021 21:20:28 -0700 Subject: [PATCH 125/359] build/pkgs/*/SPKG.rst: Clear out more redundant 'Dependencies' sections --- build/pkgs/gfan/SPKG.rst | 7 ------- build/pkgs/givaro/SPKG.rst | 6 ------ build/pkgs/glpk/SPKG.rst | 7 ------- 3 files changed, 20 deletions(-) diff --git a/build/pkgs/gfan/SPKG.rst b/build/pkgs/gfan/SPKG.rst index 58faef4f8f7..d2416f4a4d0 100644 --- a/build/pkgs/gfan/SPKG.rst +++ b/build/pkgs/gfan/SPKG.rst @@ -36,13 +36,6 @@ Anders Nedergaard Jensen https://users-math.au.dk/jensen/software/gfan/gfan.html -Dependencies ------------- - -- GMP/MPIR -- CDDLIB - - Special Update/Build Instructions --------------------------------- diff --git a/build/pkgs/givaro/SPKG.rst b/build/pkgs/givaro/SPKG.rst index fe64ba38237..1dcb4e45412 100644 --- a/build/pkgs/givaro/SPKG.rst +++ b/build/pkgs/givaro/SPKG.rst @@ -28,9 +28,3 @@ Upstream Contact ---------------- - Clement Pernet - -Dependencies ------------- - -- GNU patch -- GMP/MPIR diff --git a/build/pkgs/glpk/SPKG.rst b/build/pkgs/glpk/SPKG.rst index 75acbf1c1f2..4cabfae0ba1 100644 --- a/build/pkgs/glpk/SPKG.rst +++ b/build/pkgs/glpk/SPKG.rst @@ -36,13 +36,6 @@ GLPK is currently being maintained by: http://www.gnu.org/software/glpk/#maintainer -Dependencies ------------- - -- GMP/MPIR -- zlib - - Special Update/Build Instructions --------------------------------- From 205931c51add322c179185787fd90905f66f5f68 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 22 Sep 2021 21:27:02 -0700 Subject: [PATCH 126/359] src/doc/en/installation/source.rst: Remove doc of envvar SAGE_MP_LIBRARY --- src/doc/en/installation/source.rst | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/doc/en/installation/source.rst b/src/doc/en/installation/source.rst index 0b30005d755..d73e3b2ea60 100644 --- a/src/doc/en/installation/source.rst +++ b/src/doc/en/installation/source.rst @@ -1283,11 +1283,6 @@ Here are some of the more commonly used variables affecting the build process: Environment variables dealing with specific Sage packages: -- :envvar:`SAGE_MP_LIBRARY` - to use an alternative library in place of ``MPIR`` - for multiprecision integer arithmetic. Supported values are - - ``MPIR`` (default choice), ``GMP``. - - :envvar:`SAGE_ATLAS_ARCH` - if you are compiling ATLAS (in particular, if :envvar:`SAGE_ATLAS_LIB` is not set), you can use this environment variable to set a particular architecture and instruction set extension, From e7fdb3578039895ff83e372ec511363b67b3e584 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 22 Sep 2021 21:28:21 -0700 Subject: [PATCH 127/359] src/doc/en/installation/source.rst: Remove use of mpir as an example package --- src/doc/en/installation/source.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/en/installation/source.rst b/src/doc/en/installation/source.rst index d73e3b2ea60..e28bf58bb14 100644 --- a/src/doc/en/installation/source.rst +++ b/src/doc/en/installation/source.rst @@ -1125,8 +1125,8 @@ Here are some of the more commonly used variables affecting the build process: An entry ``package-name`` means to run the test suite for the named package regardless of the setting of :envvar:`SAGE_CHECK`. An entry ``!package-name`` means to skip its test suite. - So if this is set to ``mpir,!python3``, then always run the test suite for - MPIR, but always skip the test suite for Python 3. + So if this is set to ``ppl,!python3``, then always run the test suite for + PPL, but always skip the test suite for Python 3. .. note:: From 1eb83e30878c74b245547c22b6e165d4acf0595e Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 22 Sep 2021 21:39:29 -0700 Subject: [PATCH 128/359] build/pkgs/ratpoints/SPKG.rst: Remove redundant 'Dependencies' section --- build/pkgs/ratpoints/SPKG.rst | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/build/pkgs/ratpoints/SPKG.rst b/build/pkgs/ratpoints/SPKG.rst index 34616de3437..6607094bec9 100644 --- a/build/pkgs/ratpoints/SPKG.rst +++ b/build/pkgs/ratpoints/SPKG.rst @@ -19,16 +19,6 @@ Upstream Contact - Email: Michael.Stoll@uni-bayreuth.de - Website: http://www.mathe2.uni-bayreuth.de/stoll/programs/ -Dependencies ------------- - -- GMP/MPIR -- (GNU) patch - - -Special Update/Build Instructions ---------------------------------- - Note on SSE2 instructions ~~~~~~~~~~~~~~~~~~~~~~~~~ From f883ea4c76e96fdbf0cbf8028fd65ce4513a786d Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 23 Sep 2021 07:43:19 -0700 Subject: [PATCH 129/359] Integer.binomial: Add algorithm='gmp', keep 'mpir' as an alias --- src/sage/arith/misc.py | 8 ++++---- src/sage/rings/integer.pyx | 12 ++++++------ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/sage/arith/misc.py b/src/sage/arith/misc.py index 83f3a957d17..039e1fcae3f 100644 --- a/src/sage/arith/misc.py +++ b/src/sage/arith/misc.py @@ -2242,7 +2242,7 @@ def rational_reconstruction(a, m, algorithm='fast'): - ``algorithm`` -- (default: 'fast') - - ``'fast'`` - a fast implementation using direct MPIR calls + - ``'fast'`` - a fast implementation using direct GMP library calls in Cython. OUTPUT: @@ -3433,10 +3433,10 @@ def binomial(x, m, **kwds): 1/6*x^3 - 1/2*x^2 + 1/3*x If `x \in \ZZ`, there is an optional 'algorithm' parameter, which - can be 'mpir' (faster for small values) or 'pari' (faster for - large values):: + can be 'gmp' (faster for small values; alias: 'mpir') or + 'pari' (faster for large values):: - sage: a = binomial(100, 45, algorithm='mpir') + sage: a = binomial(100, 45, algorithm='gmp') sage: b = binomial(100, 45, algorithm='pari') sage: a == b True diff --git a/src/sage/rings/integer.pyx b/src/sage/rings/integer.pyx index 12f4124655c..b864dfe8857 100644 --- a/src/sage/rings/integer.pyx +++ b/src/sage/rings/integer.pyx @@ -6787,7 +6787,7 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): """ return self - def binomial(self, m, algorithm='mpir'): + def binomial(self, m, algorithm='gmp'): """ Return the binomial coefficient "self choose m". @@ -6795,9 +6795,9 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): - ``m`` -- an integer - - ``algorithm`` -- ``'mpir'`` (default) or ``'pari'``; ``'mpir'`` is - faster for small ``m``, and ``'pari'`` tends to be faster for - large ``m`` + - ``algorithm`` -- ``'gmp'`` (default), ``'mpir'`` (an alias for + ``gmp``), or ``'pari'``; ``'gmp'`` is faster for small ``m``, + and ``'pari'`` tends to be faster for large ``m`` OUTPUT: @@ -6878,7 +6878,7 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): return self # now call the various backend - if algorithm == 'mpir': + if algorithm == 'gmp' or algorithm == 'mpir': x = PY_NEW(Integer) if mpz_fits_ulong_p(mm.value): sig_on() @@ -6890,7 +6890,7 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): elif algorithm == 'pari': return the_integer_ring(self.__pari__().binomial(mm)) else: - raise ValueError("algorithm must be one of: 'pari', 'mpir'") + raise ValueError("algorithm must be one of: 'pari' or 'gmp' (alias: 'mpir')") cdef int mpz_set_str_python(mpz_ptr z, char* s, int base) except -1: From 1647e2f9ce387e40273b2cb42b46b7f6de378562 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 23 Sep 2021 09:23:00 -0700 Subject: [PATCH 130/359] src/sage/rings/integer.pyx: Rewrite a doctest so it works with gmp, mpir, 64bit, 32bit --- src/sage/rings/integer.pyx | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/sage/rings/integer.pyx b/src/sage/rings/integer.pyx index b864dfe8857..5dd604e7a87 100644 --- a/src/sage/rings/integer.pyx +++ b/src/sage/rings/integer.pyx @@ -6424,17 +6424,14 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): TESTS:: - sage: 1 << (2^60) # optional - mpir - Traceback (most recent call last): - ... - MemoryError: failed to allocate ... bytes # 64-bit - OverflowError: Python int too large to convert to C long # 32-bit - - sage: 1 << (2^60) # optional - gmp - Traceback (most recent call last): - ... - RuntimeError: Aborted # 64-bit - OverflowError: Python int too large to convert to C long # 32-bit + sage: try: + ....: print('Possible error output from gmp') + ....: 1 << (2^60) + ....: except (MemoryError, OverflowError, RuntimeError): + ....: pass + ....: else: + ....: print("Failed to raise exception") + Possible error output from gmp... """ cdef long n From 34526ca3ce293701c88607ec385a35b9d8a33e27 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 23 Sep 2021 09:29:53 -0700 Subject: [PATCH 131/359] build/pkgs/*/SPKG.rst: Remove some more redundant 'Dependencies' sections --- build/pkgs/latte_int/SPKG.rst | 5 ----- build/pkgs/ppl/SPKG.rst | 17 ----------------- build/pkgs/singular/SPKG.rst | 10 ---------- 3 files changed, 32 deletions(-) diff --git a/build/pkgs/latte_int/SPKG.rst b/build/pkgs/latte_int/SPKG.rst index 7f97ded201b..9bd0480ce25 100644 --- a/build/pkgs/latte_int/SPKG.rst +++ b/build/pkgs/latte_int/SPKG.rst @@ -17,8 +17,3 @@ Upstream Contact ---------------- Matthias Köppe, UC Davis, CA, USA - -Dependencies ------------- - -GMP (MPIR), 4ti2, NTL, cddlib. diff --git a/build/pkgs/ppl/SPKG.rst b/build/pkgs/ppl/SPKG.rst index 90f9f264b8e..53f1e8df54e 100644 --- a/build/pkgs/ppl/SPKG.rst +++ b/build/pkgs/ppl/SPKG.rst @@ -41,20 +41,3 @@ Core Development Team - Roberto Bagnara (University of Parma) - Patricia M. Hill (University of Parma) - Enea Zaffanella (University of Parma) - -Dependencies ------------- - -- gmp (or mpir) - - -Special Update/Build Instructions ---------------------------------- - -Patches -~~~~~~~ - -- ptrdiff_t-ppl-1.1.patch: Fixes to compile with gcc 4.9; C++ name - lookup issue. - -- weak.patch: disable use of weak symbols on Cygwin64. diff --git a/build/pkgs/singular/SPKG.rst b/build/pkgs/singular/SPKG.rst index eed2b57980d..f8bf274b4e2 100644 --- a/build/pkgs/singular/SPKG.rst +++ b/build/pkgs/singular/SPKG.rst @@ -20,16 +20,6 @@ libsingular-devel@mathematik.uni-kl.de https://www.singular.uni-kl.de/ -Dependencies ------------- - -- GNU patch -- readline -- GMP/MPIR -- MPFR -- NTL -- FLINT - Special Update/Build Instructions --------------------------------- From e3ff6aa5aacc6cde5ea466322878a69437b2b376 Mon Sep 17 00:00:00 2001 From: "John H. Palmieri" Date: Thu, 23 Sep 2021 15:24:02 -0700 Subject: [PATCH 132/359] trac 32549: misc small changes, plus don't include mpir in sdist --- COPYING.txt | 1 - build/pkgs/ecm/spkg-configure.m4 | 2 +- build/pkgs/gdb/SPKG.rst | 11 ----------- build/pkgs/isl/spkg-configure.m4 | 2 +- build/pkgs/mpfr/spkg-configure.m4 | 2 +- m4/sage_spkg_collect.m4 | 8 -------- 6 files changed, 3 insertions(+), 23 deletions(-) diff --git a/COPYING.txt b/COPYING.txt index 2da3a8e492c..7ce750a1aa9 100644 --- a/COPYING.txt +++ b/COPYING.txt @@ -86,7 +86,6 @@ mistune Modified BSD mpc LGPLv3+ mpfi COPYING is GPLv2, source files state LGPLv2.1+ mpfr LGPLv3+ -mpir LGPLv3+ mpmath Modified BSD networkx Modified BSD ntl GPLv2+ diff --git a/build/pkgs/ecm/spkg-configure.m4 b/build/pkgs/ecm/spkg-configure.m4 index e62c21cb32e..d5302a89fb0 100644 --- a/build/pkgs/ecm/spkg-configure.m4 +++ b/build/pkgs/ecm/spkg-configure.m4 @@ -1,7 +1,7 @@ SAGE_SPKG_CONFIGURE([ecm], [ m4_pushdef([SAGE_ECM_MINVER],[7.0.4]) AC_REQUIRE([SAGE_SPKG_CONFIGURE_GMP]) - AC_MSG_CHECKING([installing gmp/mpir? ]) + AC_MSG_CHECKING([installing gmp? ]) if test x$sage_spkg_install_gmp = xyes; then AC_MSG_RESULT([yes; install ecm as well]) sage_spkg_install_ecm=yes diff --git a/build/pkgs/gdb/SPKG.rst b/build/pkgs/gdb/SPKG.rst index b89773fe676..0716ac53fad 100644 --- a/build/pkgs/gdb/SPKG.rst +++ b/build/pkgs/gdb/SPKG.rst @@ -19,17 +19,6 @@ Upstream Contact http://www.gnu.org/software/gdb/ -Dependencies ------------- - -- python -- mpc -- mpfr -- ppl -- gmp/mpir -- makeinfo (external) - - Special Update/Build Instructions --------------------------------- diff --git a/build/pkgs/isl/spkg-configure.m4 b/build/pkgs/isl/spkg-configure.m4 index 1b16f70870b..d7bbef80c6b 100644 --- a/build/pkgs/isl/spkg-configure.m4 +++ b/build/pkgs/isl/spkg-configure.m4 @@ -1,6 +1,6 @@ SAGE_SPKG_CONFIGURE([isl], [ AC_REQUIRE([SAGE_SPKG_CONFIGURE_GMP]) - AC_MSG_CHECKING([installing gmp/mpir? ]) + AC_MSG_CHECKING([installing gmp? ]) if test x$sage_spkg_install_gmp = xyes; then AC_MSG_RESULT([yes; install isl as well]) sage_spkg_install_isl=yes diff --git a/build/pkgs/mpfr/spkg-configure.m4 b/build/pkgs/mpfr/spkg-configure.m4 index 2300be67076..f64ede4b750 100644 --- a/build/pkgs/mpfr/spkg-configure.m4 +++ b/build/pkgs/mpfr/spkg-configure.m4 @@ -1,6 +1,6 @@ SAGE_SPKG_CONFIGURE([mpfr], [ AC_REQUIRE([SAGE_SPKG_CONFIGURE_GMP]) - AC_MSG_CHECKING([installing gmp/mpir? ]) + AC_MSG_CHECKING([installing gmp? ]) if test x$sage_spkg_install_gmp = xyes; then AC_MSG_RESULT([yes; install mpfr as well]) sage_spkg_install_mpfr=yes diff --git a/m4/sage_spkg_collect.m4 b/m4/sage_spkg_collect.m4 index 1ab62d6fa47..c364ab62b72 100644 --- a/m4/sage_spkg_collect.m4 +++ b/m4/sage_spkg_collect.m4 @@ -259,14 +259,6 @@ for DIR in $SAGE_ROOT/build/pkgs/*; do AS_VAR_POPDEF([sage_require])dnl AS_VAR_POPDEF([sage_spkg_install])dnl - # Packages that should be included in the source distribution - # This includes all standard packages and two special cases - case "$SPKG_NAME" in - mpir) - in_sdist=yes - ;; - esac - # Determine package source # if test -f "$DIR/requirements.txt"; then From ccd0ff5770e18037d638e31c2cf67fdbd3f21b22 Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Sun, 26 Sep 2021 10:03:10 +0100 Subject: [PATCH 133/359] use SAGE_SPKG_DEPCHECK --- build/pkgs/ecm/spkg-configure.m4 | 10 ++-------- build/pkgs/isl/spkg-configure.m4 | 10 ++-------- build/pkgs/mpc/spkg-configure.m4 | 10 ++-------- build/pkgs/mpfi/spkg-configure.m4 | 15 ++------------- build/pkgs/mpfr/spkg-configure.m4 | 10 ++-------- 5 files changed, 10 insertions(+), 45 deletions(-) diff --git a/build/pkgs/ecm/spkg-configure.m4 b/build/pkgs/ecm/spkg-configure.m4 index d5302a89fb0..d456f1d8f2c 100644 --- a/build/pkgs/ecm/spkg-configure.m4 +++ b/build/pkgs/ecm/spkg-configure.m4 @@ -1,12 +1,6 @@ SAGE_SPKG_CONFIGURE([ecm], [ m4_pushdef([SAGE_ECM_MINVER],[7.0.4]) - AC_REQUIRE([SAGE_SPKG_CONFIGURE_GMP]) - AC_MSG_CHECKING([installing gmp? ]) - if test x$sage_spkg_install_gmp = xyes; then - AC_MSG_RESULT([yes; install ecm as well]) - sage_spkg_install_ecm=yes - else - AC_MSG_RESULT([no. ]) + SAGE_SPKG_DEPCHECK([gmp], [ AC_CHECK_HEADER(ecm.h, [ AX_ABSOLUTE_HEADER([ecm.h]) if test x$gl_cv_absolute_ecm_h = x; then @@ -38,6 +32,6 @@ SAGE_SPKG_CONFIGURE([ecm], [ AS_IF([test -z "$ac_cv_ECM"], [sage_spkg_install_ecm=yes]) AS_IF([test -z "$ac_cv_ECMBIN"], [sage_spkg_install_ecm=yes]) ], [sage_spkg_install_ecm=yes]) - fi + ]) m4_popdef([SAGE_ECM_MINVER]) ]) diff --git a/build/pkgs/isl/spkg-configure.m4 b/build/pkgs/isl/spkg-configure.m4 index d7bbef80c6b..db2b400b6e3 100644 --- a/build/pkgs/isl/spkg-configure.m4 +++ b/build/pkgs/isl/spkg-configure.m4 @@ -1,13 +1,7 @@ SAGE_SPKG_CONFIGURE([isl], [ - AC_REQUIRE([SAGE_SPKG_CONFIGURE_GMP]) - AC_MSG_CHECKING([installing gmp? ]) - if test x$sage_spkg_install_gmp = xyes; then - AC_MSG_RESULT([yes; install isl as well]) - sage_spkg_install_isl=yes - else - AC_MSG_RESULT([no]) + SAGE_SPKG_DEPCHECK([gmp], [ PKG_CHECK_MODULES([ISL], [isl >= 0.20], [], [ sage_spkg_install_isl=yes]) - fi + ]) ]) diff --git a/build/pkgs/mpc/spkg-configure.m4 b/build/pkgs/mpc/spkg-configure.m4 index 32aca4ada1b..1e8c475e1ff 100644 --- a/build/pkgs/mpc/spkg-configure.m4 +++ b/build/pkgs/mpc/spkg-configure.m4 @@ -1,15 +1,9 @@ SAGE_SPKG_CONFIGURE([mpc], [ - AC_REQUIRE([SAGE_SPKG_CONFIGURE_MPFR]) - AC_MSG_CHECKING([installing mpfr? ]) - if test x$sage_spkg_install_mpfr = xyes; then - AC_MSG_RESULT([yes; install mpc as well]) - sage_spkg_install_mpc=yes - else - AC_MSG_RESULT([no]) + SAGE_SPKG_DEPCHECK([mpfr], [ AC_CHECK_HEADER(mpc.h, [], [sage_spkg_install_mpc=yes]) dnl mpc_cmp_abs appeared in MPC 1.1.0 AC_SEARCH_LIBS([mpc_cmp_abs], [mpc], [], [sage_spkg_install_mpc=yes]) - fi + ]) ], [], [], [ if test x$sage_spkg_install_mpc = xyes; then AC_SUBST(SAGE_MPC_PREFIX, ['$SAGE_LOCAL']) diff --git a/build/pkgs/mpfi/spkg-configure.m4 b/build/pkgs/mpfi/spkg-configure.m4 index 0cdb10a920e..4542dce794a 100644 --- a/build/pkgs/mpfi/spkg-configure.m4 +++ b/build/pkgs/mpfi/spkg-configure.m4 @@ -1,17 +1,7 @@ SAGE_SPKG_CONFIGURE([mpfi], [ - AC_REQUIRE([SAGE_SPKG_CONFIGURE_MPFR]) - AC_MSG_CHECKING([installing mpfr? ]) - if test x$sage_spkg_install_mpfr = xyes; then - AC_MSG_RESULT([yes; install mpfi as well]) - sage_spkg_install_mpfi=yes - else - AC_MSG_RESULT([no]) - fi - m4_pushdef(SAGE_MPFI_VERSION_MAJOR, [1]) m4_pushdef(SAGE_MPFI_VERSION_MINOR, [5]) - - if test x$sage_spkg_install_mpfi != xyes; then + SAGE_SPKG_DEPCHECK([mpfr], [ AC_CHECK_HEADER([mpfi.h], [], [sage_spkg_install_mpfi=yes]) AC_SEARCH_LIBS([mpfi_diam_abs], [mpfi], [ AC_LANG_PUSH(C) @@ -31,9 +21,8 @@ SAGE_SPKG_CONFIGURE([mpfi], [ sage_spkg_install_mpfi=yes], [AC_MSG_RESULT([cross compiling. assume yes])]) AC_LANG_POP(C)], [sage_spkg_install_mpfi=yes]) - fi + ]) m4_popdef([SAGE_MPFI_VERSION_MAJOR]) m4_popdef([SAGE_MPFI_VERSION_MINOR]) ]) - diff --git a/build/pkgs/mpfr/spkg-configure.m4 b/build/pkgs/mpfr/spkg-configure.m4 index f64ede4b750..47056d06c09 100644 --- a/build/pkgs/mpfr/spkg-configure.m4 +++ b/build/pkgs/mpfr/spkg-configure.m4 @@ -1,15 +1,9 @@ SAGE_SPKG_CONFIGURE([mpfr], [ - AC_REQUIRE([SAGE_SPKG_CONFIGURE_GMP]) - AC_MSG_CHECKING([installing gmp? ]) - if test x$sage_spkg_install_gmp = xyes; then - AC_MSG_RESULT([yes; install mpfr as well]) - sage_spkg_install_mpfr=yes - else - AC_MSG_RESULT([no]) + SAGE_SPKG_DEPCHECK([gmp], [ AC_CHECK_HEADER(mpfr.h, [], [sage_spkg_install_mpfr=yes]) dnl mpfr_free_pool appeared in r11922 (Dec 2017) on MPFR svn AC_SEARCH_LIBS([mpfr_free_pool], [mpfr], [], [sage_spkg_install_mpfr=yes]) - fi + ]) ], [], [], [ if test x$sage_spkg_install_mpfr = xyes; then AC_SUBST(SAGE_MPFR_PREFIX, ['$SAGE_LOCAL']) From e400f0e29e1002c273df6e9dd7a518bf845e3b16 Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Sun, 26 Sep 2021 10:47:46 +0100 Subject: [PATCH 134/359] makes gmp test unconditional, remove mpir test --- src/sage/ext/memory.pyx | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/sage/ext/memory.pyx b/src/sage/ext/memory.pyx index ab29f81c0c3..1de6dedab82 100644 --- a/src/sage/ext/memory.pyx +++ b/src/sage/ext/memory.pyx @@ -6,13 +6,7 @@ TESTS: Check that a ``MemoryError`` is raised if we try to allocate a ridiculously large integer, see :trac:`15363`:: - sage: 2^(2^63-2) # optional - mpir - Traceback (most recent call last): - ... - OverflowError: exponent must be at most 2147483647 # 32-bit - MemoryError: failed to allocate 1152921504606847008 bytes # 64-bit - - sage: 2^(2^63-3) # optional - gmp + sage: 2^(2^63-3) Traceback (most recent call last): ... OverflowError: exponent must be at most 2147483647 # 32-bit From 07da6c3872534e01975d3d90affc102a19a8169d Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Sun, 26 Sep 2021 10:48:27 +0100 Subject: [PATCH 135/359] fix mpir mentions in FAQs and source comments --- build/pkgs/ppl/spkg-install.in | 2 +- src/doc/en/faq/faq-general.rst | 8 ++++---- src/doc/en/faq/faq-usage.rst | 16 +--------------- src/doc/it/faq/faq-general.rst | 8 ++++---- src/doc/it/faq/faq-usage.rst | 14 -------------- src/sage/all.py | 2 +- 6 files changed, 11 insertions(+), 39 deletions(-) diff --git a/build/pkgs/ppl/spkg-install.in b/build/pkgs/ppl/spkg-install.in index aed909ced26..bc570b95cfc 100644 --- a/build/pkgs/ppl/spkg-install.in +++ b/build/pkgs/ppl/spkg-install.in @@ -1,4 +1,4 @@ -# Make sure that we prefer Sage's mpir library over system-wide gmp/mpir installs +# Make sure that we prefer Sage's gmp library over system-wide gmp installs export CXXFLAGS="$CXXFLAGS -I$SAGE_LOCAL/include" cd src diff --git a/src/doc/en/faq/faq-general.rst b/src/doc/en/faq/faq-general.rst index 53fa60f5c96..bcfc15e6137 100644 --- a/src/doc/en/faq/faq-general.rst +++ b/src/doc/en/faq/faq-general.rst @@ -22,10 +22,10 @@ number theory, but throughout the mathematical sciences. Sage builds upon and extends functionalities of many underlying packages. Even from early on, when Sage was primarily used for number theory, this included -`Givaro `_, -`MPIR `_, -`NTL `_, -`Pari/GP `_, +`Givaro `_, +`GMP `_, +`NTL `_, +`Pari/GP `_, and many others too numerous to list here. Students, teachers, professors, researchers throughout the world use Sage because they require a comprehensive free open source mathematics package that diff --git a/src/doc/en/faq/faq-usage.rst b/src/doc/en/faq/faq-usage.rst index 5da1732f538..2b9c308d402 100644 --- a/src/doc/en/faq/faq-usage.rst +++ b/src/doc/en/faq/faq-usage.rst @@ -180,21 +180,7 @@ Since release 9.0 from January 2020, SageMath is running on top of Python 3. I downloaded a Sage binary and it crashes on startup with "Illegal instruction". What can I do? """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" -One way to fix this is to build Sage entirely from source. Another -option is to fix your Sage installation by rebuilding MPIR and ATLAS -by typing the following from the ``SAGE_ROOT`` of your Sage -installation directory and wait about 15 to 20 minutes - -.. CODE-BLOCK:: shell-session - - $ rm spkg/installed/mpir* spkg/installed/atlas* - $ make - -It is possible that the binaries have been built for a newer -architecture than what you have. Nobody has yet figured out how to -build Sage in such a way that MPIR and ATLAS work on all -hardware. This will eventually get fixed. Any help is appreciated. - +One way to fix this is to build Sage entirely from source. I used XXX to install Sage X.Y and that version is giving lots of errors. What can I do? """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" diff --git a/src/doc/it/faq/faq-general.rst b/src/doc/it/faq/faq-general.rst index 298178d1337..a8d81d4605a 100644 --- a/src/doc/it/faq/faq-general.rst +++ b/src/doc/it/faq/faq-general.rst @@ -21,10 +21,10 @@ dei Numeri, ma da ricercatori in tutte le scienze matematiche. Sage si avvale ed estende le funzionalità di molti dei pacchetti inglobati. Anche dal principio, quando Sage veiniva usato principalmente per la Teoria dei Numeri, includeva: -`Givaro `_, -`MPIR `_, -`NTL `_, -`Pari/GP `_, +`Givaro `_, +`GMP `_, +`NTL `_, +`Pari/GP `_, e molti altri troppo numerosi per essere elencati qui. Studenti, insegnanti, professori universitari, ricercatori di tutto il mondo usano Sage perché vogliono un pacchetto open-source comprensivo per la matematica che offra calcolo sia diff --git a/src/doc/it/faq/faq-usage.rst b/src/doc/it/faq/faq-usage.rst index 5267c991c94..1f3a223d902 100644 --- a/src/doc/it/faq/faq-usage.rst +++ b/src/doc/it/faq/faq-usage.rst @@ -160,20 +160,6 @@ Ho scaricato il binario di Sage e va in crash quando lo lancio, con il messaggio """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" Un modo di risolvere è compilare Sage interamente dal codice sorgente. -Un'altra possibilità è correggere la tua installazione di Sage con la -ricompilazione dei componenti MPIR e ATLAS (richiede da 15 a 20 minuti), -da effettuarsi da riga di comando a partire dalla cartella -``SAGE_ROOT`` della tua installazione con le 2 istruzioni:: - - rm spkg/installed/mpir* spkg/installed/atlas* - make - -È possibile che i binari siano stati compilati per un'architettura più -recente di quella della tua macchina. Nessuno ha ancora trovato un -modo di compilare Sage in maniera che MPIR ed ATLAS funzionino su -qualunque hardware. Questo sarà prima o poi risolto. -Qualunque aiuto in tal senso sarà apprezzato. - Ho usato Debian/Ubuntu per installare la versione 3.0.5 di Sage ed essa sta dando un sacco di errori. Cosa posso fare? """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" diff --git a/src/sage/all.py b/src/sage/all.py index 5d4d8a77d78..4cb8fd75c7d 100644 --- a/src/sage/all.py +++ b/src/sage/all.py @@ -283,7 +283,7 @@ def quit_sage(verbose=True): import sage.libs.flint.flint sage.libs.flint.flint.free_flint_stack() - # Free globally allocated mpir integers. + # Free globally allocated gmp integers. import sage.rings.integer sage.rings.integer.free_integer_pool() import sage.algebras.quatalg.quaternion_algebra_element From 8c071a8daa50bf21d6dc4cab6d56eadcdec92f1d Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Sun, 26 Sep 2021 20:04:18 +0100 Subject: [PATCH 136/359] https-fy consistently --- src/doc/en/faq/faq-general.rst | 4 +--- src/doc/it/faq/faq-general.rst | 5 +---- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/doc/en/faq/faq-general.rst b/src/doc/en/faq/faq-general.rst index bcfc15e6137..462fe69e617 100644 --- a/src/doc/en/faq/faq-general.rst +++ b/src/doc/en/faq/faq-general.rst @@ -181,8 +181,6 @@ Why did you write Sage from scratch, instead of using other existing software an Sage was not written from scratch. Most of its underlying mathematics functionalities are made possible through FOSS projects such as -* `ATLAS `_ --- Automatically Tuned - Linear Algebra Software. * `BLAS `_ --- Basic Linear Algebra Subprograms. * `ECL `_ --- Embeddable Common-Lisp system @@ -199,7 +197,7 @@ functionalities are made possible through FOSS projects such as * `NumPy and SciPy `_ --- numerical linear algebra and other numerical computing capabilities for Python. * `OpenBLAS `_ --- an optimized BLAS library. -* `Pari/GP `_ --- a computer algebra +* `Pari/GP `_ --- a computer algebra system for fast computations in number theory. * `Pynac `_ --- a modified version of GiNaC that replaces the dependency on CLN by Python. diff --git a/src/doc/it/faq/faq-general.rst b/src/doc/it/faq/faq-general.rst index a8d81d4605a..39ae0070bf9 100644 --- a/src/doc/it/faq/faq-general.rst +++ b/src/doc/it/faq/faq-general.rst @@ -168,9 +168,6 @@ Perché avete scritto Sage da zero, invece di usare software e librerie preesist Sage non è stato scritto da zero. La maggior parte delle sue funzionalità sono realizzate attraverso progetti FOSS come -* `ATLAS `_ --- libreria software per Algebra - Lineare ottimizzata automaticamente. - * `BLAS `_ --- sottoprogrammi per Algebra Lineare di base. @@ -188,7 +185,7 @@ realizzate attraverso progetti FOSS come * `NumPy `_ --- algebra lineare numerica ed altre funzioni di calcolo numerico per Python. -* `Pari/GP `_ --- software matematico per +* `Pari/GP `_ --- software matematico per calcolo veloce in Teoria dei Numeri. * `Pynac `_ --- versione modificata di GiNaC che From d22bd25f79a08712e03f2ebc8d0e2ff5872a38d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Mon, 27 Sep 2021 18:33:38 +0200 Subject: [PATCH 137/359] remove another set of #py2 doctest tags --- src/sage/misc/abstract_method.py | 4 +-- src/sage/misc/bindable_class.py | 12 --------- src/sage/misc/c3_controlled.pyx | 8 +----- src/sage/misc/classcall_metaclass.pyx | 4 +-- src/sage/misc/functional.py | 4 +-- src/sage/misc/lazy_import.pyx | 26 ++++--------------- src/sage/misc/remote_file.py | 3 +-- src/sage/misc/rest_index_of_methods.py | 4 +-- src/sage/misc/sage_eval.py | 11 ++++---- src/sage/misc/sagedoc.py | 7 +---- src/sage/misc/sageinspect.py | 34 +++++++------------------ src/sage/modules/with_basis/morphism.py | 9 ++----- 12 files changed, 28 insertions(+), 98 deletions(-) diff --git a/src/sage/misc/abstract_method.py b/src/sage/misc/abstract_method.py index fdfde979b96..49dc59ba9fa 100644 --- a/src/sage/misc/abstract_method.py +++ b/src/sage/misc/abstract_method.py @@ -125,9 +125,7 @@ def abstract_method(f=None, optional=False): The syntax ``@abstract_method`` w.r.t. @abstract_method(optional = True) is achieved by a little trick which we test here:: - sage: abstract_method(optional = True) # py2 - at ...> - sage: abstract_method(optional = True) # py3 + sage: abstract_method(optional = True) . at ...> sage: abstract_method(optional = True)(banner) diff --git a/src/sage/misc/bindable_class.py b/src/sage/misc/bindable_class.py index bf56d7272b8..c776faf7257 100644 --- a/src/sage/misc/bindable_class.py +++ b/src/sage/misc/bindable_class.py @@ -210,18 +210,6 @@ class BoundClass(functools.partial): sage: g() 8 - The following has incorrect syntax and thus a ``DeprecationWarning``:: - - sage: class mypartial(functools.partial): - ....: def __init__(self, f, i, j): - ....: functools.partial.__init__(self, f, i, j) - sage: g = mypartial(f, 2, 3) # py2; on Python 3 this is an error - Traceback (most recent call last): - ... - DeprecationWarning: object.__init__() takes no parameters - sage: g() - 8 - The following has correct syntax and no ``DeprecationWarning``:: sage: class mynewpartial(functools.partial): diff --git a/src/sage/misc/c3_controlled.pyx b/src/sage/misc/c3_controlled.pyx index d2ca1fe5784..3e70e529ad2 100644 --- a/src/sage/misc/c3_controlled.pyx +++ b/src/sage/misc/c3_controlled.pyx @@ -70,13 +70,7 @@ algorithm easily fails if the order of the bases is not chosen consistently (here for ``A2`` w.r.t. ``A1``):: sage: class B6(A1,A2): pass - sage: class B7(B6,A5): pass # py2 - Traceback (most recent call last): - ... - TypeError: Error when calling the metaclass bases - Cannot create a consistent method resolution - order (MRO) for bases ... - sage: class B7(B6,A5): pass # py3 + sage: class B7(B6,A5): pass Traceback (most recent call last): ... TypeError: Cannot create a consistent method resolution diff --git a/src/sage/misc/classcall_metaclass.pyx b/src/sage/misc/classcall_metaclass.pyx index eb8f75a5094..464a3ea93ec 100644 --- a/src/sage/misc/classcall_metaclass.pyx +++ b/src/sage/misc/classcall_metaclass.pyx @@ -391,9 +391,7 @@ cdef class ClasscallMetaclass(NestedClassMetaclass): sage: bind = obj.Inner calling __classget__(, <__main__.Outer object at 0x...>, ) - sage: bind # py2 - - sage: bind # py3 + sage: bind functools.partial(, <__main__.Outer object at 0x...>) """ if cls.classget: diff --git a/src/sage/misc/functional.py b/src/sage/misc/functional.py index c1f895c217c..45d74ea749a 100644 --- a/src/sage/misc/functional.py +++ b/src/sage/misc/functional.py @@ -809,9 +809,7 @@ def xinterval(a, b): EXAMPLES:: - sage: I = xinterval(2,5); I # py2 - xrange(2, 6) - sage: I = xinterval(2,5); I # py3 + sage: I = xinterval(2,5); I range(2, 6) sage: 5 in I True diff --git a/src/sage/misc/lazy_import.pyx b/src/sage/misc/lazy_import.pyx index 7e8b731965a..bccb7c7568f 100644 --- a/src/sage/misc/lazy_import.pyx +++ b/src/sage/misc/lazy_import.pyx @@ -466,13 +466,9 @@ cdef class LazyImport(object): sage: Foo().my_method() <__main__.Foo object at ...> - sage: Foo.my_method # py2 - - sage: Foo.my_method # py3 + sage: Foo.my_method - sage: Foo().my_method # py2 - > - sage: Foo().my_method # py3 + sage: Foo().my_method > When a :class:`LazyImport` method is a method (or attribute) @@ -498,9 +494,7 @@ cdef class LazyImport(object): We access the ``plot`` method:: - sage: Bar.plot # py2 - - sage: Bar.plot # py3 + sage: Bar.plot Now ``plot`` has been replaced in the dictionary of ``Foo``:: @@ -823,12 +817,7 @@ cdef class LazyImport(object): sage: sage.all.foo = 10 sage: lazy_import('sage.all', 'foo') - sage: oct(foo) # py2 - doctest:warning...: - DeprecationWarning: use the method .oct instead - See https://trac.sagemath.org/26756 for details. - '12' - sage: oct(foo) # py3 + sage: oct(foo) '0o12' """ return self.get_object().__oct__() @@ -839,12 +828,7 @@ cdef class LazyImport(object): sage: sage.all.foo = 10 sage: lazy_import('sage.all', 'foo') - sage: hex(foo) # py2 - doctest:warning...: - DeprecationWarning: use the method .hex instead - See https://trac.sagemath.org/26756 for details. - 'a' - sage: hex(foo) # py3 + sage: hex(foo) '0xa' """ return self.get_object().__hex__() diff --git a/src/sage/misc/remote_file.py b/src/sage/misc/remote_file.py index ec8b1194b4e..092640cc9e6 100644 --- a/src/sage/misc/remote_file.py +++ b/src/sage/misc/remote_file.py @@ -38,8 +38,7 @@ def get_remote_file(filename, verbose=True): # IMPORTANT -- urllib takes a long time to load, # so do not import it in the module scope. - # import compatible with py2 and py3 - req = Request(filename, headers={"User-Agent":"sage-doctest"}) + req = Request(filename, headers={"User-Agent": "sage-doctest"}) if verbose: print("Loading started") diff --git a/src/sage/misc/rest_index_of_methods.py b/src/sage/misc/rest_index_of_methods.py index 337d91c554f..b059887b014 100644 --- a/src/sage/misc/rest_index_of_methods.py +++ b/src/sage/misc/rest_index_of_methods.py @@ -233,9 +233,7 @@ def list_of_subfunctions(root, only_local_functions=True): sage: class A: ....: x = staticmethod(Graph.order) - sage: list_of_subfunctions(A) # py2 - ([], {: 'x'}) - sage: list_of_subfunctions(A) # py3 + sage: list_of_subfunctions(A) ([], {: 'x'}) diff --git a/src/sage/misc/sage_eval.py b/src/sage/misc/sage_eval.py index d5ddf7085bb..b1700ab393d 100644 --- a/src/sage/misc/sage_eval.py +++ b/src/sage/misc/sage_eval.py @@ -2,17 +2,18 @@ Evaluating a String in Sage """ -#***************************************************************************** +# **************************************************************************** # Copyright (C) 2006 William Stein # # Distributed under the terms of the GNU General Public License (GPL) # -# http://www.gnu.org/licenses/ -#***************************************************************************** +# https://www.gnu.org/licenses/ +# **************************************************************************** from copy import copy import sage.repl.preparse as preparser + def sage_eval(source, locals=None, cmds='', preparse=True): r""" Obtain a Sage object from the input string by evaluating it using @@ -90,9 +91,7 @@ def sage_eval(source, locals=None, cmds='', preparse=True): :: sage: x = 5 - sage: eval('4/3 + x', {'x': 25}) # py2 - 26 - sage: eval('4//3 + x', {'x': 25}) # py3 + sage: eval('4//3 + x', {'x': 25}) 26 sage: sage_eval('4/3 + x', locals={'x': 25}) 79/3 diff --git a/src/sage/misc/sagedoc.py b/src/sage/misc/sagedoc.py index 01e4ec4bcc1..93fa01cb5cc 100644 --- a/src/sage/misc/sagedoc.py +++ b/src/sage/misc/sagedoc.py @@ -1052,12 +1052,7 @@ def search_src(string, extra1='', extra2='', extra3='', extra4='', The following produces an error because the string 'fetch(' is a malformed regular expression:: - sage: print(search_src(" fetch(", "def", interact=False)) # py2 - Traceback (most recent call last): - ... - error: unbalanced parenthesis - - sage: print(search_src(" fetch(", "def", interact=False)) # py3 + sage: print(search_src(" fetch(", "def", interact=False)) Traceback (most recent call last): ... error: missing ), unterminated subpattern at position 6 diff --git a/src/sage/misc/sageinspect.py b/src/sage/misc/sageinspect.py index 72c9cdf1d22..db5013337a3 100644 --- a/src/sage/misc/sageinspect.py +++ b/src/sage/misc/sageinspect.py @@ -334,11 +334,8 @@ def _extract_embedded_signature(docstring, name): ... sage: _extract_embedded_signature(MainClass.NestedClass.NestedSubClass.dummy.__doc__, 'dummy')[1] ArgSpec(args=['self', 'x', 'r'], varargs='args', keywords='kwds', defaults=((1, 2, 3.4),)) - sage: _extract_embedded_signature(range.__call__.__doc__, '__call__') # py2 - ('x.__call__(...) <==> x(...)', None) - sage: _extract_embedded_signature(range.__call__.__doc__, '__call__') # py3 + sage: _extract_embedded_signature(range.__call__.__doc__, '__call__') ('Call self as a function.', None) - """ # If there is an embedded signature, it is in the first line L = docstring.split(os.linesep, 1) @@ -502,14 +499,10 @@ def visit_Name(self, node): sage: import ast, sage.misc.sageinspect as sms sage: visitor = sms.SageArgSpecVisitor() sage: vis = lambda x: visitor.visit_Name(ast.parse(x).body[0].value) - sage: [vis(n) for n in ['True', 'False', 'None', 'foo', 'bar']] # py2 - [True, False, None, 'foo', 'bar'] - sage: [type(vis(n)) for n in ['True', 'False', 'None', 'foo', 'bar']] # py2 - [, , , , ] - sage: [vis(n) for n in ['foo', 'bar']] # py3 + sage: [vis(n) for n in ['foo', 'bar']] ['foo', 'bar'] - sage: [type(vis(n)) for n in ['foo', 'bar']] # py3 - [, ] + sage: [type(vis(n)) for n in ['foo', 'bar']] + [, ] """ return node.id @@ -587,9 +580,7 @@ def visit_Num(self, node): sage: import ast, sage.misc.sageinspect as sms sage: visitor = sms.SageArgSpecVisitor() sage: vis = lambda x: visitor.visit_Num(ast.parse(x).body[0].value) - sage: [vis(n) for n in ['123', '0.0', str(-pi.n())]] # py2 - [123, 0.0, -3.14159265358979] - sage: [vis(n) for n in ['123', '0.0']] # py3 + sage: [vis(n) for n in ['123', '0.0']] [123, 0.0] .. NOTE:: @@ -809,9 +800,7 @@ def visit_BinOp(self, node): sage: import ast, sage.misc.sageinspect as sms sage: visitor = sms.SageArgSpecVisitor() sage: vis = lambda x: visitor.visit(ast.parse(x).body[0].value) - sage: [vis(d) for d in ['(3+(2*4))', '7|8', '5^3', '7/3', '7//3', '3<<4']] #indirect doctest # py2 - [11, 15, 6, 2, 2, 48] - sage: [vis(d) for d in ['(3+(2*4))', '7|8', '5^3', '7/3', '7//3', '3<<4']] #indirect doctest # py3 + sage: [vis(d) for d in ['(3+(2*4))', '7|8', '5^3', '7/3', '7//3', '3<<4']] #indirect doctest [11, 15, 6, 2.3333333333333335, 2, 48] """ op = node.op.__class__.__name__ @@ -1119,8 +1108,7 @@ def _sage_getargspec_from_ast(source): sage: from_ast(s) ArgSpec(args=['a', 'b', 'c', 'd'], varargs=None, keywords=None, defaults=(2, {'a': [4, 5.5, False]}, (None, True))) sage: context = {} - sage: exec compile(s, '', 'single') in context # py2 - sage: exec(compile(s, '', 'single'), context) # py3 + sage: exec(compile(s, '', 'single'), context) sage: inspect.getargspec(context['f']) ArgSpec(args=['a', 'b', 'c', 'd'], varargs=None, keywords=None, defaults=(2, {'a': [4, 5.5, False]}, (None, True))) sage: from_ast(s) == inspect.getargspec(context['f']) @@ -1207,12 +1195,8 @@ def _sage_getargspec_cython(source): Some input that is malformed in Python 2 but well formed in Cython or Python 3 is correctly parsed:: - sage: def dummy_python(self, *args, x=1): pass # py2 - Traceback (most recent call last): - ... - SyntaxError: invalid syntax - sage: def dummy_python(self, *args, x=1): pass # py3 - sage: sgc("def dummy_python(self, *args, x=1): pass") # py3 + sage: def dummy_python(self, *args, x=1): pass + sage: sgc("def dummy_python(self, *args, x=1): pass") ArgSpec(args=['self', 'x'], varargs='args', keywords=None, defaults=(1,)) sage: cython("def dummy_cython(self, *args, x=1): pass") sage: sgc("def dummy_cython(self, *args, x=1): pass") diff --git a/src/sage/modules/with_basis/morphism.py b/src/sage/modules/with_basis/morphism.py index 6658aa547ac..184b09a94e3 100644 --- a/src/sage/modules/with_basis/morphism.py +++ b/src/sage/modules/with_basis/morphism.py @@ -1312,16 +1312,11 @@ def __init__(self, domain, matrix, codomain=None, category=None, side="left"): True sage: TestSuite(phi).run(skip=["_test_pickling"]) - Pickling fails (:trac:`17957`) because ``phi._on_basis`` is - currently a ``dict.__getitem__`` which is not picklable in Python 2:: + Pickling works (:trac:`17957`) in Python 3:: sage: phi._on_basis - sage: dumps(phi._on_basis) # py2 - Traceback (most recent call last): - ... - TypeError: expected string or Unicode object, NoneType found - sage: loads(dumps(phi)) == phi # py3 + sage: loads(dumps(phi)) == phi True The matrix is stored in the morphism, as if it was for an From b550c3bcc97bd0ba9508eb09c08975b43b4a0015 Mon Sep 17 00:00:00 2001 From: Marc Mezzarobba Date: Mon, 27 Sep 2021 18:42:29 +0200 Subject: [PATCH 138/359] #32574 missing factorial factor in RBF/CBF zetaderiv --- src/sage/rings/complex_arb.pyx | 4 +++- src/sage/rings/real_arb.pyx | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/sage/rings/complex_arb.pyx b/src/sage/rings/complex_arb.pyx index 2fc0a3bb420..9b63bf28c01 100644 --- a/src/sage/rings/complex_arb.pyx +++ b/src/sage/rings/complex_arb.pyx @@ -3643,11 +3643,13 @@ cdef class ComplexBall(RingElement): sage: CBF(1/2, 3).zetaderiv(1) [0.191759884092721...] + [-0.073135728865928...]*I + sage: CBF(2).zetaderiv(3) + [-6.0001458028430...] """ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing Pol = PolynomialRing(self._parent, 'x') ser = Pol([self, 1])._zeta_series(k + 1) - return ser[k] + return ser[k]*ZZ.coerce(k).factorial() def lambert_w(self, branch=0): r""" diff --git a/src/sage/rings/real_arb.pyx b/src/sage/rings/real_arb.pyx index 66a9d7bda06..fe6fda6e3b1 100644 --- a/src/sage/rings/real_arb.pyx +++ b/src/sage/rings/real_arb.pyx @@ -3605,11 +3605,13 @@ cdef class RealBall(RingElement): sage: RBF(1/2).zetaderiv(1) [-3.92264613920915...] + sage: RBF(2).zetaderiv(3) + [-6.0001458028430...] """ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing Pol = PolynomialRing(self._parent.complex_field(), 'x') ser = Pol([self, 1])._zeta_series(k + 1) - return ser[k].real() + return ser[k].real()*ZZ.coerce(k).factorial() def lambert_w(self): r""" From b3f7d3426499114eed31882f06bdc6cc3b7053f1 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 27 Sep 2021 13:49:19 -0700 Subject: [PATCH 139/359] .gitignore: Add /venv --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index cf553895adb..91838a1627c 100644 --- a/.gitignore +++ b/.gitignore @@ -182,6 +182,7 @@ src/*.egg-info/ /src/bin/sage-src-env-config # Virtual environments +/venv src/.env src/.venv src/env/ From adae38e04c37dcdbbb9730e974e5eb0c162ec8da Mon Sep 17 00:00:00 2001 From: "John H. Palmieri" Date: Mon, 27 Sep 2021 14:24:26 -0700 Subject: [PATCH 140/359] trac 32575: Sphinx's install-requires.txt: allow version 4.2 --- build/pkgs/sphinx/install-requires.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/pkgs/sphinx/install-requires.txt b/build/pkgs/sphinx/install-requires.txt index 2d146f2fe48..0c661b6c6c1 100644 --- a/build/pkgs/sphinx/install-requires.txt +++ b/build/pkgs/sphinx/install-requires.txt @@ -1 +1 @@ -sphinx >=4, <4.2 +sphinx >=4, <4.3 From 5ac0f28559ab278a19833beb28761207fa1a2174 Mon Sep 17 00:00:00 2001 From: Eric Gourgoulhon Date: Tue, 28 Sep 2021 16:54:39 +0200 Subject: [PATCH 141/359] Allow for coordinate changes in curve plots (Trac #32578) --- src/sage/manifolds/differentiable/curve.py | 34 ++++++++++++---------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/src/sage/manifolds/differentiable/curve.py b/src/sage/manifolds/differentiable/curve.py index 7eb04fc8125..5b12e9d0469 100644 --- a/src/sage/manifolds/differentiable/curve.py +++ b/src/sage/manifolds/differentiable/curve.py @@ -805,6 +805,23 @@ def plot(self, chart=None, ambient_coords=None, mapping=None, prange=None, g = c.plot(color='green', style=':', thickness=3, aspect_ratio=1) sphinx_plot(g) + Cardioid defined in terms of polar coordinates and plotted with respect + to Cartesian coordinates, as an example of use of the optional argument + ``chart``:: + + sage: E. = EuclideanSpace(coordinates='polar') + sage: c = E.curve((1 + cos(ph), ph), (ph, 0, 2*pi)) + sage: c.plot(chart=E.cartesian_coordinates(), aspect_ratio=1) + Graphics object consisting of 1 graphics primitive + + .. PLOT:: + + E = EuclideanSpace(2, coordinates='polar') + r, ph = E.polar_coordinates()[:] + c = E.curve((1 + cos(ph), ph), (ph, 0, 2*pi)) + g = c.plot(chart=E.cartesian_coordinates(), aspect_ratio=1) + sphinx_plot(g) + Plot via a mapping to another manifold: loxodrome of a sphere viewed in `\RR^3`:: @@ -925,21 +942,8 @@ def plot(self, chart=None, ambient_coords=None, mapping=None, prange=None, # # The coordinate expression of the effective curve # - canon_chart = self._domain.canonical_chart() - transf = None - for chart_pair in eff_curve._coord_expression: - if chart_pair == (canon_chart, chart): - transf = eff_curve._coord_expression[chart_pair] - break - else: - # Search for a subchart - for chart_pair in eff_curve._coord_expression: - for schart in chart._subcharts: - if chart_pair == (canon_chart, schart): - transf = eff_curve._coord_expression[chart_pair] - if transf is None: - raise ValueError("No expression has been found for " + - "{} in terms of {}".format(self, chart)) + transf = eff_curve.coord_functions(chart1=self._domain.canonical_chart(), + chart2=chart) # # List of points for the plot curve # From 1c1e0a59dd103fa403d3ec6c7d12ab51d6867254 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Tue, 28 Sep 2021 18:37:22 +0200 Subject: [PATCH 142/359] fix doctest --- src/sage/misc/sagedoc.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/sage/misc/sagedoc.py b/src/sage/misc/sagedoc.py index 93fa01cb5cc..e3821e84e76 100644 --- a/src/sage/misc/sagedoc.py +++ b/src/sage/misc/sagedoc.py @@ -1101,8 +1101,7 @@ def search_src(string, extra1='', extra2='', extra3='', extra4='', misc/sagedoc.py:... len(search_src("matrix", interact=False).splitlines()) # random # long time misc/sagedoc.py:... len(search_src("matrix", module="sage.calculus", interact=False).splitlines()) # random misc/sagedoc.py:... len(search_src("matrix", path_re="calc", interact=False).splitlines()) > 15 - misc/sagedoc.py:... print(search_src(" fetch(", "def", interact=False)) # py2 - misc/sagedoc.py:... print(search_src(" fetch(", "def", interact=False)) # py3 + misc/sagedoc.py:... print(search_src(" fetch(", "def", interact=False)) misc/sagedoc.py:... print(search_src(r" fetch\(", "def", interact=False)) # random # long time misc/sagedoc.py:... print(search_src(r" fetch\(", "def", "pyx", interact=False)) # random # long time misc/sagedoc.py:... s = search_src('Matrix', path_re='matrix', interact=False); s.find('x') > 0 From 6f94502ec4378e9998b9ebf7e52490b6106bee85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Tue, 28 Sep 2021 18:56:20 +0200 Subject: [PATCH 143/359] some fixes for the relint linter --- src/.relint.yml | 3 ++- src/doc/en/thematic_tutorials/sandpile.rst | 2 +- src/sage/algebras/commutative_dga.py | 3 --- src/sage/all.py | 7 ------- src/sage/modules/with_basis/representation.py | 11 +++++------ src/sage/rings/finite_rings/integer_mod.pyx | 2 +- src/sage/rings/polynomial/omega.py | 14 ++++---------- src/sage/schemes/projective/projective_space.py | 2 +- 8 files changed, 14 insertions(+), 30 deletions(-) diff --git a/src/.relint.yml b/src/.relint.yml index cb1a1e5eac2..9377bc16114 100644 --- a/src/.relint.yml +++ b/src/.relint.yml @@ -14,7 +14,8 @@ - name: 'foreign_latex: foreign commands in LaTeX' hint: | use equivalent LaTeX commands instead of plain TeX commands such as \over, \choose, etc. - pattern: '(\\choose|\\over[^l]|\\atop|\\above|\\overwithdelims|\\atopwithdelims|\\abovewithdelims)' + pattern: '(\\choose|\\atop|\\above|\\overwithdelims|\\atopwithdelims|\\abovewithdelims)' + # \over appears in bad latex code coming from Fricas and Maxima - name: 'blocks: wrong syntax for blocks (INPUT, OUTPUT, EXAMPLES, NOTE, etc.)' hint: | diff --git a/src/doc/en/thematic_tutorials/sandpile.rst b/src/doc/en/thematic_tutorials/sandpile.rst index 7dd7091415a..ebfa825cbde 100644 --- a/src/doc/en/thematic_tutorials/sandpile.rst +++ b/src/doc/en/thematic_tutorials/sandpile.rst @@ -4988,7 +4988,7 @@ Other [ 0 -1 1650 -1649] [ 0 0 -1658 1658] - NOTES: + NOTE: The algorithm is due to John Wilmes. diff --git a/src/sage/algebras/commutative_dga.py b/src/sage/algebras/commutative_dga.py index a5e5404bf9f..2d11ee6e280 100644 --- a/src/sage/algebras/commutative_dga.py +++ b/src/sage/algebras/commutative_dga.py @@ -99,7 +99,6 @@ from sage.rings.quotient_ring import QuotientRing_nc from sage.rings.quotient_ring_element import QuotientRingElement from sage.misc.cachefunc import cached_function -from sage.misc.superseded import deprecated_function_alias def sorting_keys(element): @@ -1535,8 +1534,6 @@ def homogeneous_parts(self): res[deg] = term return {i: res[i] for i in sorted(res.keys())} - homogenous_parts = deprecated_function_alias(30585, homogeneous_parts) - def dict(self): r""" A dictionary that determines the element. diff --git a/src/sage/all.py b/src/sage/all.py index 4fa89329e81..e7167449434 100644 --- a/src/sage/all.py +++ b/src/sage/all.py @@ -31,13 +31,6 @@ sage: [inspect.getmodule(f).__name__ for f in frames if is_not_allowed(f)] [] -Check that the Sage Notebook is not imported at startup (see :trac:`15335`):: - - sage: sagenb - Traceback (most recent call last): - ... - NameError: name 'sagenb' is not defined - Check lazy import of ``interacts``:: sage: type(interacts) diff --git a/src/sage/modules/with_basis/representation.py b/src/sage/modules/with_basis/representation.py index a767525664b..e6f97d219a5 100644 --- a/src/sage/modules/with_basis/representation.py +++ b/src/sage/modules/with_basis/representation.py @@ -7,13 +7,13 @@ - Siddharth Singh (2020-03-21): Signed Representation """ -#################################################################################### +############################################################################## # Copyright (C) 2015 Travis Scrimshaw # # Distributed under the terms of the GNU General Public License (GPL) # The full text of the GPL is available at: # http://www.gnu.org/licenses/ -#################################################################################### +############################################################################## from sage.misc.abstract_method import abstract_method from sage.structure.element import Element @@ -154,7 +154,7 @@ def twisted_invariant_module(self, chi, G=None, **kwargs): Create the isotypic component of the action of ``G`` on ``self`` with irreducible character given by ``chi``. - .. SEEALSO: + .. SEEALSO:: - :class:`~sage.modules.with_basis.invariant.FiniteDimensionalTwistedInvariantModule` @@ -1026,7 +1026,7 @@ class SignRepresentationCoxeterGroup(SignRepresentation_abstract): def _default_sign(self, elem): """ Return the sign of the element - + INPUT: - ``elem`` -- the element of the group @@ -1039,5 +1039,4 @@ def _default_sign(self, elem): sage: V._default_sign(elem) 1 """ - return -1 if elem.length() % 2 == 1 else 1 - + return -1 if elem.length() % 2 else 1 diff --git a/src/sage/rings/finite_rings/integer_mod.pyx b/src/sage/rings/finite_rings/integer_mod.pyx index 4089c437934..ab92c9a8ecb 100644 --- a/src/sage/rings/finite_rings/integer_mod.pyx +++ b/src/sage/rings/finite_rings/integer_mod.pyx @@ -1347,7 +1347,7 @@ cdef class IntegerMod_abstract(FiniteRingElement): The 'extend' option is not implemented (yet). - NOTES: + NOTE: - If `n = 0`: diff --git a/src/sage/rings/polynomial/omega.py b/src/sage/rings/polynomial/omega.py index 2406e0e0197..97b97d4fe8c 100644 --- a/src/sage/rings/polynomial/omega.py +++ b/src/sage/rings/polynomial/omega.py @@ -36,25 +36,20 @@ - Daniel Krenn is supported by the Austrian Science Fund (FWF): P 24644-N26. - Functions ========= """ - -#***************************************************************************** +# **************************************************************************** # Copyright (C) 2016 Daniel Krenn # # 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/ +# **************************************************************************** import operator from sage.misc.cachefunc import cached_function -from sage.misc.superseded import deprecated_function_alias def MacMahonOmega(var, expression, denominator=None, op=operator.ge, @@ -595,6 +590,7 @@ def subs_power(expression, var, exponent): divisible by ``exponent``. """ p = tuple(var.dict().popitem()[0]).index(1) # var is the p-th generator + def subs_e(e): e = list(e) assert e[p] % exponent == 0 @@ -984,5 +980,3 @@ def homogeneous_symmetric_function(j, x): return sum(prod(xx**pp for xx, pp in zip(x, p)) for p in IntegerVectors(j, length=len(x))) - -homogenous_symmetric_function = deprecated_function_alias(30585, homogeneous_symmetric_function) diff --git a/src/sage/schemes/projective/projective_space.py b/src/sage/schemes/projective/projective_space.py index 14bf23cac43..c8a93db5b06 100644 --- a/src/sage/schemes/projective/projective_space.py +++ b/src/sage/schemes/projective/projective_space.py @@ -1531,7 +1531,7 @@ def hyperplane_transformation_matrix(self, plane_1, plane_2): Return a PGL element sending ``plane_1`` to ``plane_2``. ``plane_1`` and ``plane_2`` must be hyperplanes (subschemes of - codimension 1, each defined by a single linear homogenous equation). + codimension 1, each defined by a single linear homogeneous equation). INPUT: From c2afe429b00d3229a65edb7c0c12324f9242eb0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Tue, 28 Sep 2021 20:23:30 +0200 Subject: [PATCH 144/359] more fixes for relint --- src/sage/misc/latex_macros.py | 5 +---- src/sage/symbolic/ginac/inifcns_comb.cpp | 4 ++-- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/sage/misc/latex_macros.py b/src/sage/misc/latex_macros.py index 21b7fab46b4..24d2eee43cb 100644 --- a/src/sage/misc/latex_macros.py +++ b/src/sage/misc/latex_macros.py @@ -16,10 +16,7 @@ LaTeX macros is used in the file ``sage.docs.conf`` to add to the preambles of both the LaTeX file used to build the PDF version of the documentation -and the LaTeX file used to build the HTML version. The list of -MathJax macros is used in the file -``sagenb/notebook/tutorial.py`` to define MathJax macros for use -in the live documentation (and also in the notebook). +and the LaTeX file used to build the HTML version. Any macro defined here may be used in docstrings or in the tutorial (or other pieces of documentation). In a docstring, for example, diff --git a/src/sage/symbolic/ginac/inifcns_comb.cpp b/src/sage/symbolic/ginac/inifcns_comb.cpp index 2f34fe76700..f31ea4f14e4 100644 --- a/src/sage/symbolic/ginac/inifcns_comb.cpp +++ b/src/sage/symbolic/ginac/inifcns_comb.cpp @@ -126,9 +126,9 @@ static ex binomial_imag_part(const ex & x, const ex & y) static void binomial_print_latex(const ex & x, const ex & y, const print_context & c) { - c.s<<"{"; + c.s<<"\\binom{"; x.print(c); - c.s<<" \\choose "; + c.s<<"}{"; y.print(c); c.s<<"}"; } From 86bef1c6d47908d5e1a1f8015ba6e804a360302c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Tue, 28 Sep 2021 20:29:25 +0200 Subject: [PATCH 145/359] one more fix --- src/sage/cpython/cython_metaclass.pyx | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/sage/cpython/cython_metaclass.pyx b/src/sage/cpython/cython_metaclass.pyx index 11294c2bb97..530ff083d4f 100644 --- a/src/sage/cpython/cython_metaclass.pyx +++ b/src/sage/cpython/cython_metaclass.pyx @@ -30,9 +30,6 @@ metaclass: from foo import MyMetaclass return MyMetaclass -The above ``__getmetaclass__`` method is analogous to -``__metaclass__ = MyMetaclass`` in Python 2. - .. WARNING:: ``__getmetaclass__`` must be defined as an ordinary method taking a From e0782b169e48ef67a7b075f25b42dbc2feedc46f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Tue, 28 Sep 2021 20:36:56 +0200 Subject: [PATCH 146/359] another fix --- src/.relint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/.relint.yml b/src/.relint.yml index 9377bc16114..9d12054b982 100644 --- a/src/.relint.yml +++ b/src/.relint.yml @@ -8,7 +8,7 @@ # ifilter, imap, izip # __metaclass__ Hint: # update raise statements # except Exception, var Hint: # sagenb # six is no longer allowed - pattern: '(import.*[, ]ifilter|import.*[, ]imap|import.*[, ]izip|^\s*raise\s*[A-Za-z]*Error\s*,|__metaclass__|except\s*[A-Za-z]\s*,|sagenb|import six|from six import)' + pattern: '(import.*[, ]ifilter|import.*[, ]imap|import.*[, ]izip|^\s*raise\s*[A-Za-z]*Error\s*,|__metaclass__|except\s*[A-Za-z]\s*,|[^_]sagenb|import six|from six import)' filePattern: .*[.](py|pyx|rst) - name: 'foreign_latex: foreign commands in LaTeX' From fc4b641f651968af7fd8c4accb5841021ea0390c Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 28 Sep 2021 13:37:45 -0700 Subject: [PATCH 147/359] configure.ac: Remove conveniene symlinks before (re)creating them --- configure.ac | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configure.ac b/configure.ac index 48600bea7b5..f6078401bf8 100644 --- a/configure.ac +++ b/configure.ac @@ -507,6 +507,7 @@ AC_CONFIG_COMMANDS(links, [ SYMLINK="${ac_top_build_prefix}prefix" AS_IF([test -L "$SYMLINK" -o ! -e "$SYMLINK"], [ AC_MSG_NOTICE([creating convenience symlink $SYMLINK -> $SAGE_LOCAL]) + rm -f "$SYMLINK" ln -sf "$SAGE_LOCAL" "$SYMLINK" ], [ AC_MSG_NOTICE([cannot create convenience symlink $SYMLINK -> $SAGE_LOCAL because the file exists and is not a symlink; this is harmless]) @@ -514,6 +515,7 @@ AC_CONFIG_COMMANDS(links, [ SYMLINK="${ac_top_build_prefix}venv" AS_IF([test -L "$SYMLINK" -o ! -e "$SYMLINK"], [ AC_MSG_NOTICE([creating convenience symlink $SYMLINK -> $SAGE_VENV]) + rm -f "$SYMLINK" ln -sf "$SAGE_VENV" "$SYMLINK" ], [ AC_MSG_NOTICE([cannot create convenience symlink $SYMLINK -> $SAGE_VENV because the file exists and is not a symlink; this is harmless]) From 8bcbf1d919d7d90cefe1442a23aaa66df4ecd2d3 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 28 Sep 2021 15:21:42 -0700 Subject: [PATCH 148/359] Makefile (distclean): Remove convenience symlinks prefix, venv --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index 567bffbffd0..444e4f9e4ad 100644 --- a/Makefile +++ b/Makefile @@ -109,6 +109,7 @@ distclean: build-clean @echo "Deleting all remaining output from build system ..." rm -rf local rm -f src/bin/sage-env-config + rm -f prefix venv # Delete all auto-generated files which are distributed as part of the # source tarball From 2f16dc0cb5779eeae667697d3c41137fcde507c3 Mon Sep 17 00:00:00 2001 From: Jonathan Kliem Date: Wed, 29 Sep 2021 11:24:27 +0200 Subject: [PATCH 149/359] improve initialization of mset --- src/sage/combinat/combination.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/sage/combinat/combination.py b/src/sage/combinat/combination.py index 674c2c96ba2..44563d589b7 100644 --- a/src/sage/combinat/combination.py +++ b/src/sage/combinat/combination.py @@ -157,16 +157,22 @@ class of combinations of ``mset`` of size ``k``. [[], [(0, 0)], [(0, 1)], [(0, 0), (0, 1)]] """ # Check to see if everything in mset is unique + is_unique = False if isinstance(mset, (int, Integer)): mset = list(range(mset)) + is_unique = True + elif isinstance(mset, range): + mset = list(mset) + is_unique = True else: mset = list(mset) + for i, e in enumerate(mset): + if mset.index(e) != i: + break + else: + is_unique = True - d = {} - for i in mset: - d[mset.index(i)] = 1 - - if len(d) == len(mset): + if is_unique: if k is None: return Combinations_set(mset) else: From c30b3a3bb1698dbb800a23a479bade0384d5faab Mon Sep 17 00:00:00 2001 From: Jonathan Kliem Date: Wed, 29 Sep 2021 11:43:13 +0200 Subject: [PATCH 150/359] improve cardinality for combinations over non-multi-set --- src/sage/combinat/combination.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/sage/combinat/combination.py b/src/sage/combinat/combination.py index 44563d589b7..3fed5ab8c9c 100644 --- a/src/sage/combinat/combination.py +++ b/src/sage/combinat/combination.py @@ -30,6 +30,7 @@ from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets from sage.structure.parent import Parent from sage.misc.persist import register_unpickle_override +from sage.functions.other import binomial def Combinations(mset, k=None): @@ -320,6 +321,17 @@ def rank(self, x): r += rank(x, n) return r + def cardinality(self): + """ + Return the size of Combinations(set). + + EXAMPLES:: + + sage: Combinations(range(16000)).cardinality() == 2^16000 + True + """ + return 2**len(self.mset) + class Combinations_msetk(Parent): def __init__(self, mset, k): @@ -521,6 +533,17 @@ def rank(self, x): x = [self.mset.index(_) for _ in x] return rank(x, len(self.mset)) + def cardinality(self): + """ + Return the size of combinations(set, k). + + EXAMPLES:: + + sage: Combinations(range(16000), 5).cardinality() + 8732673194560003200 + """ + return binomial(len(self.mset), self.k) + def rank(comb, n, check=True): """ From a3d61ef2a307e365e39d109f51006582eb8deba1 Mon Sep 17 00:00:00 2001 From: Jonathan Kliem Date: Wed, 29 Sep 2021 21:22:47 +0200 Subject: [PATCH 151/359] do not overwrite binomial import --- src/sage/combinat/combination.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/sage/combinat/combination.py b/src/sage/combinat/combination.py index 3fed5ab8c9c..6e3dc71da83 100644 --- a/src/sage/combinat/combination.py +++ b/src/sage/combinat/combination.py @@ -30,7 +30,6 @@ from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets from sage.structure.parent import Parent from sage.misc.persist import register_unpickle_override -from sage.functions.other import binomial def Combinations(mset, k=None): From dcb4a08a1d5e5e2363c4b6e2f2f3d852efd3aae0 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 29 Sep 2021 15:24:23 -0700 Subject: [PATCH 152/359] configure.ac: Indicate default in help string for --with-sage-venv --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index f6078401bf8..6f59a5ea128 100644 --- a/configure.ac +++ b/configure.ac @@ -84,7 +84,7 @@ SAGE_SRC="$SAGE_ROOT/src" SAGE_SPKG_INST="$SAGE_LOCAL/var/lib/sage/installed" AC_ARG_WITH([sage-venv], - [AS_HELP_STRING([--with-sage-venv={auto,yes,no,SAGE_VENV}], + [AS_HELP_STRING([--with-sage-venv={auto (default),yes,no,SAGE_VENV}], [put Python packages into an installation hierarchy separate from prefix])], [SAGE_VENV="$withval"], [SAGE_VENV="auto"]) From 7a63b9c782df73f271c8455f5c613d5133bac67e Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 29 Sep 2021 19:01:26 -0700 Subject: [PATCH 153/359] sage.modules.fg_pid: Replace .all imports by more specific imports --- src/sage/modules/fg_pid/fgp_element.py | 4 +++- src/sage/modules/fg_pid/fgp_module.py | 9 +++++---- src/sage/modules/fg_pid/fgp_morphism.py | 4 ++-- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/sage/modules/fg_pid/fgp_element.py b/src/sage/modules/fg_pid/fgp_element.py index f6f03acd16c..c8174017343 100644 --- a/src/sage/modules/fg_pid/fgp_element.py +++ b/src/sage/modules/fg_pid/fgp_element.py @@ -448,7 +448,9 @@ def additive_order(self): I = Q.invariants() v = self.vector() - from sage.rings.all import infinity, Mod, Integer + from sage.rings.infinity import infinity + from sage.rings.finite_rings.integer_mod import Mod + from sage.rings.integer import Integer from sage.arith.all import lcm n = Integer(1) for i, a in enumerate(I): diff --git a/src/sage/modules/fg_pid/fgp_module.py b/src/sage/modules/fg_pid/fgp_module.py index 009d8679e21..bb2bd6e7148 100644 --- a/src/sage/modules/fg_pid/fgp_module.py +++ b/src/sage/modules/fg_pid/fgp_module.py @@ -215,8 +215,9 @@ from sage.structure.sequence import Sequence from .fgp_element import DEBUG, FGP_Element from .fgp_morphism import FGP_Morphism, FGP_Homset -from sage.rings.all import Integer, ZZ -from sage.arith.all import lcm +from sage.rings.integer_ring import ZZ +from sage.rings.integer import Integer +from sage.arith.functions import lcm from sage.misc.cachefunc import cached_method from sage.matrix.constructor import matrix @@ -1223,7 +1224,7 @@ def gens_vector(self, x, reduce=False): """ x = self(x) v = x.vector() * self.smith_to_gens() - from sage.rings.all import infinity + from sage.rings.infinity import infinity if reduce and self.base_ring() == ZZ: orders = [g.order() for g in self.gens()] v = v.parent()([v[i] if orders[i] == infinity @@ -1740,7 +1741,7 @@ def cardinality(self): return self.__cardinality except AttributeError: pass - from sage.rings.all import infinity + from sage.rings.infinity import infinity from sage.misc.misc_c import prod v = self.invariants() self.__cardinality = infinity if 0 in v else prod(v) diff --git a/src/sage/modules/fg_pid/fgp_morphism.py b/src/sage/modules/fg_pid/fgp_morphism.py index 2bca2484d8a..8eaf32ed7bd 100644 --- a/src/sage/modules/fg_pid/fgp_morphism.py +++ b/src/sage/modules/fg_pid/fgp_morphism.py @@ -507,10 +507,10 @@ def __init__(self, X, Y, category=None): if category is None: from sage.modules.free_module import is_FreeModule if is_FreeModule(X) and is_FreeModule(Y): - from sage.all import FreeModules + from sage.categories.all import FreeModules category = FreeModules(X.base_ring()) else: - from sage.all import Modules + from sage.categories.all import Modules category = Modules(X.base_ring()) Homset.__init__(self, X, Y, category) From 245d72695aed5fb297ed2db1f3e435ef9a88d94b Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 28 Sep 2021 23:32:46 -0700 Subject: [PATCH 154/359] src/sage/structure/sage_object.pyx: Replace import from sage.misc.all by more specific import --- src/sage/structure/sage_object.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/structure/sage_object.pyx b/src/sage/structure/sage_object.pyx index 7ebf2734e9f..8c05c347491 100644 --- a/src/sage/structure/sage_object.pyx +++ b/src/sage/structure/sage_object.pyx @@ -645,7 +645,7 @@ cdef class SageObject: remote Sage session, and get it back. """ tester = self._tester(**options) - from sage.misc.all import loads, dumps + from sage.misc.persist import loads, dumps tester.assertEqual(loads(dumps(self)), self) ############################################################################# From 5f1c296b11a43a6805ebf4c568442717c3649608 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 29 Sep 2021 19:00:37 -0700 Subject: [PATCH 155/359] src/sage/misc/sage_unittest.py: Import loads, dumps from sage.misc.persist --- src/sage/misc/sage_unittest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/misc/sage_unittest.py b/src/sage/misc/sage_unittest.py index 18827dfd118..c6c6d2741dc 100644 --- a/src/sage/misc/sage_unittest.py +++ b/src/sage/misc/sage_unittest.py @@ -610,7 +610,7 @@ def _test_pickling(self, **options): :func:`dumps`, :func:`loads` """ tester = instance_tester(self, **options) - from sage.misc.all import loads, dumps + from sage.misc.persist import loads, dumps tester.assertEqual(loads(dumps(self._instance)), self._instance) def _test_new(self, **options): From e251555a862c5089707dd906eccb20ecee49fe3f Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 28 Sep 2021 23:30:00 -0700 Subject: [PATCH 156/359] src/sage/geometry/polyhedron/backend_cdd_rdf.py: Split out from src/sage/geometry/polyhedron/backend_cdd.py --- src/sage/geometry/polyhedron/backend_cdd.py | 210 +--------------- .../geometry/polyhedron/backend_cdd_rdf.py | 227 ++++++++++++++++++ 2 files changed, 229 insertions(+), 208 deletions(-) create mode 100644 src/sage/geometry/polyhedron/backend_cdd_rdf.py diff --git a/src/sage/geometry/polyhedron/backend_cdd.py b/src/sage/geometry/polyhedron/backend_cdd.py index d839bc3ca5e..a8409e58a4f 100644 --- a/src/sage/geometry/polyhedron/backend_cdd.py +++ b/src/sage/geometry/polyhedron/backend_cdd.py @@ -21,7 +21,6 @@ from .base import Polyhedron_base from .base_QQ import Polyhedron_QQ -from .base_RDF import Polyhedron_RDF class Polyhedron_cdd(Polyhedron_base): @@ -460,210 +459,5 @@ def __init__(self, parent, Vrep, Hrep, **kwds): Polyhedron_cdd.__init__(self, parent, Vrep, Hrep, **kwds) -class Polyhedron_RDF_cdd(Polyhedron_cdd, Polyhedron_RDF): - """ - Polyhedra over RDF with cdd - - INPUT: - - - ``ambient_dim`` -- integer. The dimension of the ambient space. - - - ``Vrep`` -- a list ``[vertices, rays, lines]`` or ``None``. - - - ``Hrep`` -- a list ``[ieqs, eqns]`` or ``None``. - - EXAMPLES:: - - sage: from sage.geometry.polyhedron.parent import Polyhedra - sage: parent = Polyhedra(RDF, 2, backend='cdd') - sage: from sage.geometry.polyhedron.backend_cdd import Polyhedron_RDF_cdd - sage: Polyhedron_RDF_cdd(parent, [ [(1,0),(0,1),(0,0)], [], []], None, verbose=False) - A 2-dimensional polyhedron in RDF^2 defined as the convex hull of 3 vertices - - TESTS: - - Checks that :trac:`24877` is fixed:: - - sage: n1 = 1045602428815736513789288687833080060779 - sage: n2 = 76591188009721216624438400001815308369088648782156930777145 - sage: n3 = 141046287872967162025203834781636948939209065735662536571684677443277621519222367249160281646288602157866548267640061850035 - sage: n4 = 169296796161110084211548448622149955145002732358082778064645608216077666698460018565094060494217 - sage: verts = [[159852/261157, 227425/261157], - ....: [9/10, 7/10], - ....: [132/179, 143/179], - ....: [8/11, -59/33], - ....: [174/167, 95/167], - ....: [3/2, -1/2], - ....: [-1162016360399650274197433414376009691155/n1, - ....: 1626522696050475596930360993440360903664/n1], - ....: [-112565666321600055047037445519656973805313121630809713051718/n2, - ....: -15318574020578896781701071673537253327221557273483622682053/n2], - ....: [-222823992658914823798345935660863293259608796350232624336738123149601409997996952470726909468671437285720616325991022633438/n3, - ....: (-20857694835570598502487921801401627779907095024585170129381924208334510445828894861553290291713792691651471189597832832973*5)/n3], - ....: [-100432602675156818915933977983765863676402454634873648118147187022041830166292457614016362515164/n4, - ....: -429364759737031049317769174492863890735634068814210512342503744054527903830844433491149538512537/n4]] - sage: P = Polyhedron(verts, base_ring=RDF) - sage: len(P.faces(1)) - 10 - sage: P.n_vertices() - 10 - sage: P.n_facets() - 10 - - Check that :trac:`19803` is fixed:: - - sage: from sage.geometry.polyhedron.parent import Polyhedra - sage: P_cdd = Polyhedra(RDF, 3, 'cdd') - sage: P_cdd([[],[],[]], None) - The empty polyhedron in RDF^3 - sage: Polyhedron(vertices=[], backend='cdd', base_ring=RDF) - The empty polyhedron in RDF^0 - """ - _cdd_type = 'real' - - _cdd_executable = 'cddexec' - - def __init__(self, parent, Vrep, Hrep, **kwds): - """ - The Python constructor. - - See :class:`Polyhedron_base` for a description of the input - data. - - TESTS:: - - sage: p = Polyhedron(backend='cdd', base_ring=RDF) - sage: type(p) - - sage: TestSuite(p).run() - """ - Polyhedron_cdd.__init__(self, parent, Vrep, Hrep, **kwds) - - def _init_from_Vrepresentation_and_Hrepresentation(self, Vrep, Hrep, verbose=False): - """ - Construct polyhedron from Vrepresentation and Hrepresentation data. - - See :class:`Polyhedron_base` for a description of ``Vrep`` and ``Hrep``. - - .. NOTE:: - - The representation is assumed to be correct. - - As long as cdd can obtain a consistent object with Vrepresentation - or Hrepresentation no warning is raised. Consistency is checked by - comparing the output length of Vrepresentation and Hrepresentation - with the input. - - In comparison, the "normal" initialization from Vrepresentation over RDF - expects the output length to be consistent with the computed length - when re-feeding cdd the outputted Hrepresentation. - - EXAMPLES:: - - sage: from sage.geometry.polyhedron.parent import Polyhedra_RDF_cdd - sage: from sage.geometry.polyhedron.backend_cdd import Polyhedron_RDF_cdd - sage: parent = Polyhedra_RDF_cdd(RDF, 1, 'cdd') - sage: Vrep = [[[0.0], [1.0]], [], []] - sage: Hrep = [[[0.0, 1.0], [1.0, -1.0]], []] - sage: p = Polyhedron_RDF_cdd(parent, Vrep, Hrep, - ....: Vrep_minimal=True, Hrep_minimal=True) # indirect doctest - sage: p - A 1-dimensional polyhedron in RDF^1 defined as the convex hull of 2 vertices - - TESTS: - - Test that :trac:`29568` is fixed:: - - sage: P = polytopes.buckyball(exact=False) - sage: Q = P + P.center() - sage: P.is_combinatorially_isomorphic(Q) - True - sage: R = 2*P - sage: P.is_combinatorially_isomorphic(R) - True - - The polyhedron with zero inequalities works correctly; see :trac:`29899`:: - - sage: Vrep = [[], [], [[1.0]]] - sage: Hrep = [[], []] - sage: p = Polyhedron_RDF_cdd(parent, Vrep, Hrep, - ....: Vrep_minimal=True, Hrep_minimal=True) # indirect doctest - sage: p - A 1-dimensional polyhedron in RDF^1 defined as the convex hull of 1 vertex and 1 line - - Test that :trac:`30330` is fixed:: - - sage: P1 = polytopes.regular_polygon(5, exact=False) - sage: P2 = Polyhedron() - sage: P1*P2 - The empty polyhedron in RDF^2 - """ - def parse_Vrep(intro, data): - count = int(data[0][0]) - if count != len(vertices) + len(rays) + len(lines): - # Upstream claims that nothing can be done about these - # cases/that they are features not bugs. Imho, cddlib is - # not really suitable for automatic parsing of its output, - # the implementation backed by doubles has not really been - # optimized for numerical stability, and makes some - # somewhat random numerical choices. (But I am not an - # expert in that field by any means.) See also - # https://github.com/cddlib/cddlib/pull/7. - from warnings import warn - warn("This polyhedron data is numerically complicated; cdd could not convert between the inexact V and H representation without loss of data. The resulting object might show inconsistencies.") - - def parse_Hrep(intro, data): - count = int(data[0][0]) - infinite_count = len([d for d in data[1:] if d[0] == '1' and all(c == '0' for c in d[1:])]) - if count - infinite_count != len(ieqs) + len(eqns): - # Upstream claims that nothing can be done about these - # cases/that they are features not bugs. Imho, cddlib is - # not really suitable for automatic parsing of its output, - # the implementation backed by doubles has not really been - # optimized for numerical stability, and makes some - # somewhat random numerical choices. (But I am not an - # expert in that field by any means.) - from warnings import warn - warn("This polyhedron data is numerically complicated; cdd could not convert between the inexact V and H representation without loss of data. The resulting object might show inconsistencies.") - - def try_init(rep): - if rep == "Vrep": - from .cdd_file_format import cdd_Vrepresentation - s = cdd_Vrepresentation(self._cdd_type, vertices, rays, lines) - else: - # We have to add a trivial inequality, in case the polyhedron is the universe. - new_ieqs = ieqs + ((1,) + tuple(0 for _ in range(self.ambient_dim())),) - - from .cdd_file_format import cdd_Hrepresentation - s = cdd_Hrepresentation(self._cdd_type, new_ieqs, eqns) - - s = self._run_cdd(s, '--redcheck', verbose=verbose) - s = self._run_cdd(s, '--repall', verbose=verbose) - Polyhedron_cdd._parse_block(s.splitlines(), 'V-representation', parse_Vrep) - Polyhedron_cdd._parse_block(s.splitlines(), 'H-representation', parse_Hrep) - self._init_from_cdd_output(s) - - from warnings import catch_warnings, simplefilter - - vertices, rays, lines = (tuple(x) for x in Vrep) - ieqs, eqns = (tuple(x) for x in Hrep) - - if not (vertices or rays or lines): - # cdd refuses to handle empty polyhedra. - self._init_empty_polyhedron() - return - - # We prefer the shorter representation. - # Note that for the empty polyhedron we prefer Hrepresentation. - prim = "Hrep" if len(ieqs) <= len(vertices) + len(rays) else "Vrep" - sec = "Vrep" if len(ieqs) <= len(vertices) + len(rays) else "Hrep" - - with catch_warnings(): - # Raise an error and try the other representation in case of - # numerical inconsistency. - simplefilter("error") - try: - try_init(prim) - except UserWarning: - simplefilter("once") # Only print the first warning. - try_init(sec) +from sage.misc.lazy_import import lazy_import +lazy_import('sage.geometry.polyhedron.backend_cdd_rdf', 'Polyhedron_RDF_cdd') diff --git a/src/sage/geometry/polyhedron/backend_cdd_rdf.py b/src/sage/geometry/polyhedron/backend_cdd_rdf.py new file mode 100644 index 00000000000..e180448e1ad --- /dev/null +++ b/src/sage/geometry/polyhedron/backend_cdd_rdf.py @@ -0,0 +1,227 @@ +r""" +The cdd backend for polyhedral computations, floating point version +""" +# **************************************************************************** +# Copyright (C) 2011-2014 Volker Braun +# 2018 Timo Kaufmann +# 2018 Julian Rüth +# +# 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. +# https://www.gnu.org/licenses/ +# **************************************************************************** + + +from .backend_cdd import Polyhedron_cdd +from .base_RDF import Polyhedron_RDF + + +class Polyhedron_RDF_cdd(Polyhedron_cdd, Polyhedron_RDF): + """ + Polyhedra over RDF with cdd + + INPUT: + + - ``ambient_dim`` -- integer. The dimension of the ambient space. + + - ``Vrep`` -- a list ``[vertices, rays, lines]`` or ``None``. + + - ``Hrep`` -- a list ``[ieqs, eqns]`` or ``None``. + + EXAMPLES:: + + sage: from sage.geometry.polyhedron.parent import Polyhedra + sage: parent = Polyhedra(RDF, 2, backend='cdd') + sage: from sage.geometry.polyhedron.backend_cdd import Polyhedron_RDF_cdd + sage: Polyhedron_RDF_cdd(parent, [ [(1,0),(0,1),(0,0)], [], []], None, verbose=False) + A 2-dimensional polyhedron in RDF^2 defined as the convex hull of 3 vertices + + TESTS: + + Checks that :trac:`24877` is fixed:: + + sage: n1 = 1045602428815736513789288687833080060779 + sage: n2 = 76591188009721216624438400001815308369088648782156930777145 + sage: n3 = 141046287872967162025203834781636948939209065735662536571684677443277621519222367249160281646288602157866548267640061850035 + sage: n4 = 169296796161110084211548448622149955145002732358082778064645608216077666698460018565094060494217 + sage: verts = [[159852/261157, 227425/261157], + ....: [9/10, 7/10], + ....: [132/179, 143/179], + ....: [8/11, -59/33], + ....: [174/167, 95/167], + ....: [3/2, -1/2], + ....: [-1162016360399650274197433414376009691155/n1, + ....: 1626522696050475596930360993440360903664/n1], + ....: [-112565666321600055047037445519656973805313121630809713051718/n2, + ....: -15318574020578896781701071673537253327221557273483622682053/n2], + ....: [-222823992658914823798345935660863293259608796350232624336738123149601409997996952470726909468671437285720616325991022633438/n3, + ....: (-20857694835570598502487921801401627779907095024585170129381924208334510445828894861553290291713792691651471189597832832973*5)/n3], + ....: [-100432602675156818915933977983765863676402454634873648118147187022041830166292457614016362515164/n4, + ....: -429364759737031049317769174492863890735634068814210512342503744054527903830844433491149538512537/n4]] + sage: P = Polyhedron(verts, base_ring=RDF) + sage: len(P.faces(1)) + 10 + sage: P.n_vertices() + 10 + sage: P.n_facets() + 10 + + Check that :trac:`19803` is fixed:: + + sage: from sage.geometry.polyhedron.parent import Polyhedra + sage: P_cdd = Polyhedra(RDF, 3, 'cdd') + sage: P_cdd([[],[],[]], None) + The empty polyhedron in RDF^3 + sage: Polyhedron(vertices=[], backend='cdd', base_ring=RDF) + The empty polyhedron in RDF^0 + """ + _cdd_type = 'real' + + _cdd_executable = 'cddexec' + + def __init__(self, parent, Vrep, Hrep, **kwds): + """ + The Python constructor. + + See :class:`Polyhedron_base` for a description of the input + data. + + TESTS:: + + sage: p = Polyhedron(backend='cdd', base_ring=RDF) + sage: type(p) + + sage: TestSuite(p).run() + """ + Polyhedron_cdd.__init__(self, parent, Vrep, Hrep, **kwds) + + def _init_from_Vrepresentation_and_Hrepresentation(self, Vrep, Hrep, verbose=False): + """ + Construct polyhedron from Vrepresentation and Hrepresentation data. + + See :class:`Polyhedron_base` for a description of ``Vrep`` and ``Hrep``. + + .. NOTE:: + + The representation is assumed to be correct. + + As long as cdd can obtain a consistent object with Vrepresentation + or Hrepresentation no warning is raised. Consistency is checked by + comparing the output length of Vrepresentation and Hrepresentation + with the input. + + In comparison, the "normal" initialization from Vrepresentation over RDF + expects the output length to be consistent with the computed length + when re-feeding cdd the outputted Hrepresentation. + + EXAMPLES:: + + sage: from sage.geometry.polyhedron.parent import Polyhedra_RDF_cdd + sage: from sage.geometry.polyhedron.backend_cdd import Polyhedron_RDF_cdd + sage: parent = Polyhedra_RDF_cdd(RDF, 1, 'cdd') + sage: Vrep = [[[0.0], [1.0]], [], []] + sage: Hrep = [[[0.0, 1.0], [1.0, -1.0]], []] + sage: p = Polyhedron_RDF_cdd(parent, Vrep, Hrep, + ....: Vrep_minimal=True, Hrep_minimal=True) # indirect doctest + sage: p + A 1-dimensional polyhedron in RDF^1 defined as the convex hull of 2 vertices + + TESTS: + + Test that :trac:`29568` is fixed:: + + sage: P = polytopes.buckyball(exact=False) + sage: Q = P + P.center() + sage: P.is_combinatorially_isomorphic(Q) + True + sage: R = 2*P + sage: P.is_combinatorially_isomorphic(R) + True + + The polyhedron with zero inequalities works correctly; see :trac:`29899`:: + + sage: Vrep = [[], [], [[1.0]]] + sage: Hrep = [[], []] + sage: p = Polyhedron_RDF_cdd(parent, Vrep, Hrep, + ....: Vrep_minimal=True, Hrep_minimal=True) # indirect doctest + sage: p + A 1-dimensional polyhedron in RDF^1 defined as the convex hull of 1 vertex and 1 line + + Test that :trac:`30330` is fixed:: + + sage: P1 = polytopes.regular_polygon(5, exact=False) + sage: P2 = Polyhedron() + sage: P1*P2 + The empty polyhedron in RDF^2 + """ + def parse_Vrep(intro, data): + count = int(data[0][0]) + if count != len(vertices) + len(rays) + len(lines): + # Upstream claims that nothing can be done about these + # cases/that they are features not bugs. Imho, cddlib is + # not really suitable for automatic parsing of its output, + # the implementation backed by doubles has not really been + # optimized for numerical stability, and makes some + # somewhat random numerical choices. (But I am not an + # expert in that field by any means.) See also + # https://github.com/cddlib/cddlib/pull/7. + from warnings import warn + warn("This polyhedron data is numerically complicated; cdd could not convert between the inexact V and H representation without loss of data. The resulting object might show inconsistencies.") + + def parse_Hrep(intro, data): + count = int(data[0][0]) + infinite_count = len([d for d in data[1:] if d[0] == '1' and all(c == '0' for c in d[1:])]) + if count - infinite_count != len(ieqs) + len(eqns): + # Upstream claims that nothing can be done about these + # cases/that they are features not bugs. Imho, cddlib is + # not really suitable for automatic parsing of its output, + # the implementation backed by doubles has not really been + # optimized for numerical stability, and makes some + # somewhat random numerical choices. (But I am not an + # expert in that field by any means.) + from warnings import warn + warn("This polyhedron data is numerically complicated; cdd could not convert between the inexact V and H representation without loss of data. The resulting object might show inconsistencies.") + + def try_init(rep): + if rep == "Vrep": + from .cdd_file_format import cdd_Vrepresentation + s = cdd_Vrepresentation(self._cdd_type, vertices, rays, lines) + else: + # We have to add a trivial inequality, in case the polyhedron is the universe. + new_ieqs = ieqs + ((1,) + tuple(0 for _ in range(self.ambient_dim())),) + + from .cdd_file_format import cdd_Hrepresentation + s = cdd_Hrepresentation(self._cdd_type, new_ieqs, eqns) + + s = self._run_cdd(s, '--redcheck', verbose=verbose) + s = self._run_cdd(s, '--repall', verbose=verbose) + Polyhedron_cdd._parse_block(s.splitlines(), 'V-representation', parse_Vrep) + Polyhedron_cdd._parse_block(s.splitlines(), 'H-representation', parse_Hrep) + self._init_from_cdd_output(s) + + from warnings import catch_warnings, simplefilter + + vertices, rays, lines = (tuple(x) for x in Vrep) + ieqs, eqns = (tuple(x) for x in Hrep) + + if not (vertices or rays or lines): + # cdd refuses to handle empty polyhedra. + self._init_empty_polyhedron() + return + + # We prefer the shorter representation. + # Note that for the empty polyhedron we prefer Hrepresentation. + prim = "Hrep" if len(ieqs) <= len(vertices) + len(rays) else "Vrep" + sec = "Vrep" if len(ieqs) <= len(vertices) + len(rays) else "Hrep" + + with catch_warnings(): + # Raise an error and try the other representation in case of + # numerical inconsistency. + simplefilter("error") + try: + try_init(prim) + except UserWarning: + simplefilter("once") # Only print the first warning. + try_init(sec) From 1b0a5ab028885616c12adec26ffa6524c7ccbe46 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 29 Sep 2021 15:09:07 -0700 Subject: [PATCH 157/359] src/sage/modules/vector_space_morphism.py: Do not fail if sage.symbol is not present --- src/sage/modules/vector_space_morphism.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/sage/modules/vector_space_morphism.py b/src/sage/modules/vector_space_morphism.py index 7c2104b1f17..1a1fde6eb5a 100644 --- a/src/sage/modules/vector_space_morphism.py +++ b/src/sage/modules/vector_space_morphism.py @@ -688,8 +688,10 @@ def linear_transformation(arg0, arg1=None, arg2=None, side='left'): from sage.modules.module import is_VectorSpace from sage.modules.free_module import VectorSpace from sage.categories.homset import Hom - from sage.symbolic.ring import SR - from sage.modules.vector_callable_symbolic_dense import Vector_callable_symbolic_dense + try: + from sage.modules.vector_callable_symbolic_dense import Vector_callable_symbolic_dense + except ImportError: + Vector_callable_symbolic_dense = () if not side in ['left', 'right']: raise ValueError("side must be 'left' or 'right', not {0}".format(side)) @@ -734,6 +736,7 @@ def linear_transformation(arg0, arg1=None, arg2=None, side='left'): elif isinstance(arg2, (list, tuple)): pass elif isinstance(arg2, Vector_callable_symbolic_dense): + from sage.symbolic.ring import SR args = arg2.parent().base_ring()._arguments exprs = arg2.change_ring(SR) m = len(args) From 83b5038c1a34c3a9cbfa4607e7c4c0c7a2c2f510 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 28 Sep 2021 15:46:21 -0700 Subject: [PATCH 158/359] src/sage/modules/free_module_element.pyx: Move import from sage.misc.derivative into method --- src/sage/modules/free_module_element.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/modules/free_module_element.pyx b/src/sage/modules/free_module_element.pyx index 2075d07c0ae..21d898c117c 100644 --- a/src/sage/modules/free_module_element.pyx +++ b/src/sage/modules/free_module_element.pyx @@ -123,7 +123,6 @@ from sage.rings.infinity import Infinity, AnInfinity from sage.rings.integer_ring import ZZ from sage.rings.real_double import RDF from sage.rings.complex_double import CDF -from sage.misc.derivative import multi_derivative from sage.rings.ring cimport Ring from sage.rings.integer cimport Integer, smallInteger @@ -3968,6 +3967,7 @@ cdef class FreeModuleElement(Vector): # abstract base class sage: v.derivative(x,x) (0, 0, 2) """ + from sage.misc.derivative import multi_derivative return multi_derivative(self, args) diff = derivative From acca6c2219955e585fa1426e22486fe01a03f760 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 28 Sep 2021 19:06:50 -0700 Subject: [PATCH 159/359] src/sage/matrix/matrix2.pyx: Move import from sage.misc.derivative into method --- src/sage/matrix/matrix2.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/matrix/matrix2.pyx b/src/sage/matrix/matrix2.pyx index d4a8ec9d3a1..00e806b190c 100644 --- a/src/sage/matrix/matrix2.pyx +++ b/src/sage/matrix/matrix2.pyx @@ -94,7 +94,6 @@ from sage.rings.complex_double import CDF from sage.rings.real_mpfr import RealField from sage.rings.complex_mpfr import ComplexField from sage.rings.finite_rings.integer_mod_ring import IntegerModRing -from sage.misc.derivative import multi_derivative from sage.arith.numerical_approx cimport digits_to_bits from copy import copy @@ -15123,6 +15122,7 @@ cdef class Matrix(Matrix1): sage: v.derivative(x,x) (0, 0, 2) """ + from sage.misc.derivative import multi_derivative return multi_derivative(self, args) def exp(self): From 27bc041532bdeadd69f5285e0991fecad9da5022 Mon Sep 17 00:00:00 2001 From: Jonathan Kliem Date: Thu, 30 Sep 2021 15:49:35 +0200 Subject: [PATCH 160/359] update memory_allocator to fix test failures on 32bit --- build/pkgs/memory_allocator/checksums.ini | 6 +++--- build/pkgs/memory_allocator/package-version.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/pkgs/memory_allocator/checksums.ini b/build/pkgs/memory_allocator/checksums.ini index f7efcd9b150..fe48843d873 100644 --- a/build/pkgs/memory_allocator/checksums.ini +++ b/build/pkgs/memory_allocator/checksums.ini @@ -1,5 +1,5 @@ tarball=memory_allocator-VERSION.tar.gz -sha1=0e9256d307957e84eaba408f190cafc04d5c246a -md5=1ce1fb6dc5972017a26ee82c4371b180 -cksum=2493862442 +sha1=7721219be84207f6112e118fc79af0c2729fca34 +md5=868753a09c44194cba303db89cca4396 +cksum=16627262 upstream_url=https://pypi.io/packages/source/m/memory_allocator/memory_allocator-VERSION.tar.gz diff --git a/build/pkgs/memory_allocator/package-version.txt b/build/pkgs/memory_allocator/package-version.txt index 6e8bf73aa55..17e51c385ea 100644 --- a/build/pkgs/memory_allocator/package-version.txt +++ b/build/pkgs/memory_allocator/package-version.txt @@ -1 +1 @@ -0.1.0 +0.1.1 From 007683ecb8888463567345097d8ff88483766487 Mon Sep 17 00:00:00 2001 From: Thierry Monteil Date: Thu, 30 Sep 2021 16:44:08 +0200 Subject: [PATCH 161/359] #32598 : use pytest instead of nose for selftests --- build/pkgs/cvxopt/dependencies | 2 +- build/pkgs/cvxopt/spkg-check.in | 7 +------ 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/build/pkgs/cvxopt/dependencies b/build/pkgs/cvxopt/dependencies index 8930227ba65..9a585f3b003 100644 --- a/build/pkgs/cvxopt/dependencies +++ b/build/pkgs/cvxopt/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) numpy $(BLAS) gsl glpk suitesparse | $(PYTHON_TOOLCHAIN) pkgconfig nose matplotlib +$(PYTHON) numpy $(BLAS) gsl glpk suitesparse | $(PYTHON_TOOLCHAIN) pkgconfig pytest matplotlib matplotlib is needed to test cvxopt (i.e., if SAGE_CHECK=yes). See #12742. diff --git a/build/pkgs/cvxopt/spkg-check.in b/build/pkgs/cvxopt/spkg-check.in index e251b2cbb6f..8b3f5031762 100644 --- a/build/pkgs/cvxopt/spkg-check.in +++ b/build/pkgs/cvxopt/spkg-check.in @@ -1,8 +1,3 @@ cd src -if ! command -v nosetests ; then - echo >&2 'Testing cvxopt requires the package nose to be installed' - exit 1 -fi - -nosetests +pytest From 67ceb09c9d3dce0ee34d7a50423484b3bc5c0b68 Mon Sep 17 00:00:00 2001 From: Thierry Monteil Date: Thu, 30 Sep 2021 16:51:23 +0200 Subject: [PATCH 162/359] #32597 : use pytest instead of nose for networkx selftests --- build/pkgs/networkx/dependencies | 2 +- build/pkgs/networkx/spkg-check.in | 7 +------ 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/build/pkgs/networkx/dependencies b/build/pkgs/networkx/dependencies index 3d0462a6697..2a20cb459ba 100644 --- a/build/pkgs/networkx/dependencies +++ b/build/pkgs/networkx/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) decorator | $(PYTHON_TOOLCHAIN) scipy $(and $(filter-out no,$(SAGE_CHECK_networkx)), nose pytest) +$(PYTHON) decorator | $(PYTHON_TOOLCHAIN) scipy $(and $(filter-out no,$(SAGE_CHECK_networkx)), pytest) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/networkx/spkg-check.in b/build/pkgs/networkx/spkg-check.in index 60868aaefc5..8b3f5031762 100644 --- a/build/pkgs/networkx/spkg-check.in +++ b/build/pkgs/networkx/spkg-check.in @@ -1,8 +1,3 @@ cd src -if ! command -v nosetests ; then - echo >&2 'Testing networkx requires the package nose to be installed' - exit 1 -fi - -nosetests networkx -v +pytest From 2586c1e9f11d627ea2c7d440ea359e8ac964dd4b Mon Sep 17 00:00:00 2001 From: Thierry Monteil Date: Thu, 30 Sep 2021 17:15:00 +0200 Subject: [PATCH 163/359] #32598 : conditional dependency on pytest for cvxopt --- build/pkgs/cvxopt/dependencies | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/pkgs/cvxopt/dependencies b/build/pkgs/cvxopt/dependencies index 9a585f3b003..2354fdb1c1e 100644 --- a/build/pkgs/cvxopt/dependencies +++ b/build/pkgs/cvxopt/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) numpy $(BLAS) gsl glpk suitesparse | $(PYTHON_TOOLCHAIN) pkgconfig pytest matplotlib +$(PYTHON) numpy $(BLAS) gsl glpk suitesparse | $(PYTHON_TOOLCHAIN) pkgconfig matplotlib $(and $(filter-out no,$(SAGE_CHECK_cvxopt)), pytest) matplotlib is needed to test cvxopt (i.e., if SAGE_CHECK=yes). See #12742. From 8e27fdcd555117075d19e1ed7bf502758495cbc6 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 28 Sep 2021 23:32:20 -0700 Subject: [PATCH 164/359] src/sage/structure/sequence.py: Do not fail if polynomial rings cannot be imported --- src/sage/structure/sequence.py | 41 ++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/src/sage/structure/sequence.py b/src/sage/structure/sequence.py index 0c8440da8e0..29d960e4d27 100644 --- a/src/sage/structure/sequence.py +++ b/src/sage/structure/sequence.py @@ -213,15 +213,19 @@ def Sequence(x, universe=None, check=True, immutable=False, cr=False, cr_str=Non ... TypeError: unable to convert a to an element of Integer Ring """ - from sage.rings.polynomial.multi_polynomial_ideal import MPolynomialIdeal - - if isinstance(x, Sequence_generic) and universe is None: - universe = x.universe() - x = list(x) - - if isinstance(x, MPolynomialIdeal) and universe is None: - universe = x.ring() - x = x.gens() + if universe is None: + if isinstance(x, Sequence_generic): + universe = x.universe() + x = list(x) + else: + try: + from sage.rings.polynomial.multi_polynomial_ideal import MPolynomialIdeal + except ImportError: + pass + else: + if isinstance(x, MPolynomialIdeal): + universe = x.ring() + x = x.gens() if universe is None: orig_x = x @@ -248,15 +252,18 @@ def Sequence(x, universe=None, check=True, immutable=False, cr=False, cr_str=Non if universe is None: # no type errors raised. universe = sage.structure.element.parent(x[len(x)-1]) - from sage.rings.polynomial.multi_polynomial_sequence import PolynomialSequence - from sage.rings.polynomial.pbori.pbori import BooleanMonomialMonoid - from sage.rings.polynomial.multi_polynomial_ring import is_MPolynomialRing - from sage.rings.quotient_ring import is_QuotientRing - - if is_MPolynomialRing(universe) or isinstance(universe, BooleanMonomialMonoid) or (is_QuotientRing(universe) and is_MPolynomialRing(universe.cover_ring())): - return PolynomialSequence(x, universe, immutable=immutable, cr=cr, cr_str=cr_str) + try: + from sage.rings.polynomial.multi_polynomial_sequence import PolynomialSequence + from sage.rings.polynomial.pbori.pbori import BooleanMonomialMonoid + from sage.rings.polynomial.multi_polynomial_ring import is_MPolynomialRing + from sage.rings.quotient_ring import is_QuotientRing + except ImportError: + pass else: - return Sequence_generic(x, universe, check, immutable, cr, cr_str, use_sage_types) + if is_MPolynomialRing(universe) or isinstance(universe, BooleanMonomialMonoid) or (is_QuotientRing(universe) and is_MPolynomialRing(universe.cover_ring())): + return PolynomialSequence(x, universe, immutable=immutable, cr=cr, cr_str=cr_str) + + return Sequence_generic(x, universe, check, immutable, cr, cr_str, use_sage_types) class Sequence_generic(sage.structure.sage_object.SageObject, list): From b43a50c3f52ab9ddc652ce0a410baf21323f169c Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 30 Sep 2021 11:49:06 -0700 Subject: [PATCH 165/359] src/sage/sets/condition_set.py: Do not fail if sage.symbolic cannot be imported --- src/sage/sets/condition_set.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/sage/sets/condition_set.py b/src/sage/sets/condition_set.py index 757014ace6c..b9373e65fad 100644 --- a/src/sage/sets/condition_set.py +++ b/src/sage/sets/condition_set.py @@ -19,9 +19,12 @@ from sage.categories.enumerated_sets import EnumeratedSets from sage.misc.cachefunc import cached_method from sage.misc.misc import _stable_uniq -from sage.symbolic.expression import is_Expression -from sage.symbolic.callable import is_CallableSymbolicExpression -from sage.symbolic.ring import SR + +try: + from sage.symbolic.expression import is_Expression + from sage.symbolic.callable import is_CallableSymbolicExpression +except ImportError: + is_CallableSymbolicExpression = is_Expression = lambda x: False from .set import Set, Set_base, Set_boolean_operators, Set_add_sub_operators @@ -169,6 +172,7 @@ def __classcall_private__(cls, universe, *predicates, vars=None, names=None, cat if names is None: raise TypeError('use callable symbolic expressions or provide variable names') if vars is None: + from sage.symbolic.ring import SR vars = tuple(SR.var(name) for name in names) callable_symbolic_predicates.append(predicate.function(*vars)) else: From 4e2f0ab62ea50af638d3679a8ad61350f218a4d2 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 28 Sep 2021 17:01:21 -0700 Subject: [PATCH 166/359] src/sage/arith/misc.py: move pari/flint imports into methods --- src/sage/arith/misc.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/sage/arith/misc.py b/src/sage/arith/misc.py index 039e786aff7..3bf42a46daa 100644 --- a/src/sage/arith/misc.py +++ b/src/sage/arith/misc.py @@ -19,10 +19,6 @@ from sage.misc.misc import powerset from sage.misc.misc_c import prod -from sage.libs.pari.all import pari -from sage.libs.flint.arith import (bernoulli_number as flint_bernoulli, - dedekind_sum as flint_dedekind_sum) - from sage.structure.element import parent from sage.structure.coerce import py_scalar_to_element @@ -266,6 +262,7 @@ def norm(v): raise NotImplementedError("proof and height bound only implemented for real and complex numbers") else: + from sage.libs.pari.all import pari y = pari(z) f = y.algdep(degree) @@ -366,8 +363,10 @@ def bernoulli(n, algorithm='default', num_threads=1): if n >= 100000: from warnings import warn warn("flint is known to not be accurate for large Bernoulli numbers") + from sage.libs.flint.arith import bernoulli_number as flint_bernoulli return flint_bernoulli(n) elif algorithm == 'pari': + from sage.libs.pari.all import pari x = pari(n).bernfrac() # Use the PARI C library return Rational(x) elif algorithm == 'gap': @@ -465,6 +464,7 @@ def factorial(n, algorithm='gmp'): if algorithm == 'gmp': return ZZ(n).factorial() elif algorithm == 'pari': + from sage.libs.pari.all import pari return pari.factorial(n) else: raise ValueError('unknown algorithm') @@ -4160,6 +4160,7 @@ def nth_prime(n): """ if n <= 0: raise ValueError("nth prime meaningless for non-positive n (=%s)" % n) + from sage.libs.pari.all import pari return ZZ(pari.prime(n)) @@ -5872,6 +5873,7 @@ def dedekind_sum(p, q, algorithm='default'): - :wikipedia:`Dedekind\_sum` """ if algorithm == 'default' or algorithm == 'flint': + from sage.libs.flint.arith import dedekind_sum as flint_dedekind_sum return flint_dedekind_sum(p, q) if algorithm == 'pari': From 5145d43c5646f414f152e063fbbabed8854e2300 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 28 Sep 2021 17:02:07 -0700 Subject: [PATCH 167/359] src/sage/arith/misc.py: Use sage.rings.abc instead of importing element classes RealNumber, ComplexNumber --- src/sage/arith/misc.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/sage/arith/misc.py b/src/sage/arith/misc.py index 3bf42a46daa..b235cd552b1 100644 --- a/src/sage/arith/misc.py +++ b/src/sage/arith/misc.py @@ -26,8 +26,7 @@ from sage.rings.integer_ring import ZZ from sage.rings.integer import Integer, GCD_list from sage.rings.rational import Rational -from sage.rings.real_mpfr import RealNumber -from sage.rings.complex_mpfr import ComplexNumber +from sage.rings.abc import RealField, ComplexField from sage.rings.fast_arith import arith_int, arith_llong, prime_range @@ -203,7 +202,7 @@ def algdep(z, degree, known_bits=None, use_bits=None, known_digits=None, return None return z.denominator()*x - z.numerator() - if isinstance(z, (RealNumber, ComplexNumber)): + if isinstance(z.parent(), (RealField, ComplexField)): log2_10 = math.log(10,2) @@ -3609,7 +3608,7 @@ def binomial(x, m, **kwds): return P(x.binomial(m, **kwds)) # case 3: rational, real numbers, complex numbers -> use pari - if isinstance(x, (Rational, RealNumber, ComplexNumber)): + if isinstance(x, Rational) or isinstance(P, (RealField, ComplexField)): return P(x.__pari__().binomial(m)) # case 4: naive method From 5e5843a0c0703f0cb83c51b14c9aec8bc1450460 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 28 Sep 2021 21:12:55 -0700 Subject: [PATCH 168/359] sage.arith.misc: Fixup --- src/sage/arith/misc.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/sage/arith/misc.py b/src/sage/arith/misc.py index b235cd552b1..ddb143505b7 100644 --- a/src/sage/arith/misc.py +++ b/src/sage/arith/misc.py @@ -216,7 +216,7 @@ def algdep(z, degree, known_bits=None, use_bits=None, known_digits=None, if use_bits is not None: prec = int(use_bits) - is_complex = isinstance(z, ComplexNumber) + is_complex = isinstance(z.parent(), ComplexField) n = degree+1 from sage.matrix.all import matrix M = matrix(ZZ, n, n+1+int(is_complex)) @@ -3030,6 +3030,7 @@ def __call__(self, n): return ZZ(0) if n<=2: return ZZ(1) + from sage.libs.pari.all import pari return ZZ(pari(n).eulerphi()) def plot(self, xmin=1, xmax=50, pointsize=30, rgbcolor=(0,0,1), join=True, @@ -4100,6 +4101,7 @@ def primitive_root(n, check=True): sage: primitive_root(mpz(-46)) 5 """ + from sage.libs.pari.all import pari if not check: return ZZ(pari(n).znprimroot()) n = ZZ(n).abs() @@ -4278,6 +4280,7 @@ def __call__(self, n): # Use fast PARI algorithm if n == 0: return ZZ.zero() + from sage.libs.pari.all import pari return ZZ(pari(n).moebius()) @@ -4363,6 +4366,8 @@ def range(self, start, stop=None, step=None): return self.range(start, 0, step) + [ZZ.zero()] +\ self.range(step, stop, step) + from sage.libs.pari.all import pari + if step == 1: v = pari('vector(%s, i, moebius(i-1+%s))'%( stop-start, start)) @@ -4492,6 +4497,7 @@ def number_of_divisors(n): m = ZZ(n) if m.is_zero(): raise ValueError("input must be nonzero") + from sage.libs.pari.all import pari return ZZ(pari(m).numdiv()) @@ -4566,6 +4572,7 @@ def hilbert_symbol(a, b, p, algorithm="pari"): if algorithm == "pari": if p == -1: p = 0 + from sage.libs.pari.all import pari return ZZ(pari(a).hilbert(b, p)) elif algorithm == 'direct': From 5ec8fa8ff28f6328b49f29a81168b02af7b8c2ae Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 30 Sep 2021 15:18:22 -0700 Subject: [PATCH 169/359] src/sage/geometry/polyhedron/backend_cdd.py: Make Polyhedron_RDF_cdd a deprecated lazy_import --- src/sage/geometry/polyhedron/backend_cdd.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/sage/geometry/polyhedron/backend_cdd.py b/src/sage/geometry/polyhedron/backend_cdd.py index a8409e58a4f..0b99d0e6c23 100644 --- a/src/sage/geometry/polyhedron/backend_cdd.py +++ b/src/sage/geometry/polyhedron/backend_cdd.py @@ -22,6 +22,9 @@ from .base import Polyhedron_base from .base_QQ import Polyhedron_QQ +from sage.misc.lazy_import import lazy_import +lazy_import('sage.geometry.polyhedron.backend_cdd_rdf', 'Polyhedron_RDF_cdd', deprecation=32592) + class Polyhedron_cdd(Polyhedron_base): r""" @@ -457,7 +460,3 @@ def __init__(self, parent, Vrep, Hrep, **kwds): sage: TestSuite(p).run() """ Polyhedron_cdd.__init__(self, parent, Vrep, Hrep, **kwds) - - -from sage.misc.lazy_import import lazy_import -lazy_import('sage.geometry.polyhedron.backend_cdd_rdf', 'Polyhedron_RDF_cdd') From 7f317f128d20b1148f9e327e22254fb15fb477c5 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 30 Sep 2021 15:19:18 -0700 Subject: [PATCH 170/359] src/sage/geometry/polyhedron/parent.py: Use lazy_import for Polyhedron_RDF_cdd --- src/sage/geometry/polyhedron/parent.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/sage/geometry/polyhedron/parent.py b/src/sage/geometry/polyhedron/parent.py index 7f14eb0766e..002c93e9dfb 100644 --- a/src/sage/geometry/polyhedron/parent.py +++ b/src/sage/geometry/polyhedron/parent.py @@ -1127,7 +1127,8 @@ def _make_Line(self, polyhedron, data): -from sage.geometry.polyhedron.backend_cdd import Polyhedron_QQ_cdd, Polyhedron_RDF_cdd +from sage.geometry.polyhedron.backend_cdd import Polyhedron_QQ_cdd +lazy_import('sage.geometry.polyhedron.backend_cdd_rdf', Polyhedron_RDF_cdd) from sage.geometry.polyhedron.backend_ppl import Polyhedron_ZZ_ppl, Polyhedron_QQ_ppl from sage.geometry.polyhedron.backend_normaliz import Polyhedron_normaliz, Polyhedron_ZZ_normaliz, Polyhedron_QQ_normaliz from sage.geometry.polyhedron.backend_polymake import Polyhedron_polymake From 4ec38291bd3b7a53e44db4245ecd37f502f2f6c9 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 30 Sep 2021 15:24:25 -0700 Subject: [PATCH 171/359] src/sage/geometry/polyhedron/backend_cdd_rdf.py: Update imports in doctests --- src/sage/geometry/polyhedron/backend_cdd_rdf.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/geometry/polyhedron/backend_cdd_rdf.py b/src/sage/geometry/polyhedron/backend_cdd_rdf.py index e180448e1ad..2f3795a4b0f 100644 --- a/src/sage/geometry/polyhedron/backend_cdd_rdf.py +++ b/src/sage/geometry/polyhedron/backend_cdd_rdf.py @@ -34,7 +34,7 @@ class Polyhedron_RDF_cdd(Polyhedron_cdd, Polyhedron_RDF): sage: from sage.geometry.polyhedron.parent import Polyhedra sage: parent = Polyhedra(RDF, 2, backend='cdd') - sage: from sage.geometry.polyhedron.backend_cdd import Polyhedron_RDF_cdd + sage: from sage.geometry.polyhedron.backend_cdd_rdf import Polyhedron_RDF_cdd sage: Polyhedron_RDF_cdd(parent, [ [(1,0),(0,1),(0,0)], [], []], None, verbose=False) A 2-dimensional polyhedron in RDF^2 defined as the convex hull of 3 vertices @@ -119,7 +119,7 @@ def _init_from_Vrepresentation_and_Hrepresentation(self, Vrep, Hrep, verbose=Fal EXAMPLES:: sage: from sage.geometry.polyhedron.parent import Polyhedra_RDF_cdd - sage: from sage.geometry.polyhedron.backend_cdd import Polyhedron_RDF_cdd + sage: from sage.geometry.polyhedron.backend_cdd_rdf import Polyhedron_RDF_cdd sage: parent = Polyhedra_RDF_cdd(RDF, 1, 'cdd') sage: Vrep = [[[0.0], [1.0]], [], []] sage: Hrep = [[[0.0, 1.0], [1.0, -1.0]], []] From 9cd6a30daa0987acdf27d15bce672c568324d579 Mon Sep 17 00:00:00 2001 From: Thierry Monteil Date: Thu, 30 Sep 2021 16:59:21 +0200 Subject: [PATCH 172/359] #32595 : remove nose spkg --- build/pkgs/nose/SPKG.rst | 34 ---------------------------- build/pkgs/nose/checksums.ini | 4 ---- build/pkgs/nose/dependencies | 5 ---- build/pkgs/nose/distros/conda.txt | 1 - build/pkgs/nose/distros/macports.txt | 1 - build/pkgs/nose/distros/repology.txt | 2 -- build/pkgs/nose/install-requires.txt | 1 - build/pkgs/nose/package-version.txt | 1 - build/pkgs/nose/spkg-check.in | 5 ---- build/pkgs/nose/spkg-install.in | 6 ----- build/pkgs/nose/type | 1 - 11 files changed, 61 deletions(-) delete mode 100644 build/pkgs/nose/SPKG.rst delete mode 100644 build/pkgs/nose/checksums.ini delete mode 100644 build/pkgs/nose/dependencies delete mode 100644 build/pkgs/nose/distros/conda.txt delete mode 100644 build/pkgs/nose/distros/macports.txt delete mode 100644 build/pkgs/nose/distros/repology.txt delete mode 100644 build/pkgs/nose/install-requires.txt delete mode 100644 build/pkgs/nose/package-version.txt delete mode 100644 build/pkgs/nose/spkg-check.in delete mode 100644 build/pkgs/nose/spkg-install.in delete mode 100644 build/pkgs/nose/type diff --git a/build/pkgs/nose/SPKG.rst b/build/pkgs/nose/SPKG.rst deleted file mode 100644 index 49f74660ac7..00000000000 --- a/build/pkgs/nose/SPKG.rst +++ /dev/null @@ -1,34 +0,0 @@ -nose: Python unit testing framework -=================================== - -Description ------------ - -nose extends the test loading and running features of unittest, making -it easier to write, find and run tests. - -License -------- - -GNU LGPL - - -Upstream Contact ----------------- - -Author: Jason Pellerin Home Page: http://readthedocs.org/docs/nose/ - - see also https://github.com/nose-devs/nose - -Dependencies ------------- - -- setuptools / distribute -- Python -- GNU patch (shipped with Sage) - - -Special Update/Build Instructions ---------------------------------- - -None. diff --git a/build/pkgs/nose/checksums.ini b/build/pkgs/nose/checksums.ini deleted file mode 100644 index b9477e8524b..00000000000 --- a/build/pkgs/nose/checksums.ini +++ /dev/null @@ -1,4 +0,0 @@ -tarball=nose-VERSION.tar.gz -sha1=97f2a04c9d43b29ddf4794a1a1d1ba803f1074c6 -md5=4d3ad0ff07b61373d2cefc89c5d0b20b -cksum=3318391794 diff --git a/build/pkgs/nose/dependencies b/build/pkgs/nose/dependencies deleted file mode 100644 index 15df0c4d6d8..00000000000 --- a/build/pkgs/nose/dependencies +++ /dev/null @@ -1,5 +0,0 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) - ----------- -All lines of this file are ignored except the first. -It is copied by SAGE_ROOT/build/make/install into SAGE_ROOT/build/make/Makefile. diff --git a/build/pkgs/nose/distros/conda.txt b/build/pkgs/nose/distros/conda.txt deleted file mode 100644 index f3c7e8e6ffb..00000000000 --- a/build/pkgs/nose/distros/conda.txt +++ /dev/null @@ -1 +0,0 @@ -nose diff --git a/build/pkgs/nose/distros/macports.txt b/build/pkgs/nose/distros/macports.txt deleted file mode 100644 index a29026eec2b..00000000000 --- a/build/pkgs/nose/distros/macports.txt +++ /dev/null @@ -1 +0,0 @@ -py-nose diff --git a/build/pkgs/nose/distros/repology.txt b/build/pkgs/nose/distros/repology.txt deleted file mode 100644 index 4ebae104fde..00000000000 --- a/build/pkgs/nose/distros/repology.txt +++ /dev/null @@ -1,2 +0,0 @@ -nose -python:nose diff --git a/build/pkgs/nose/install-requires.txt b/build/pkgs/nose/install-requires.txt deleted file mode 100644 index 2e10ae2a3b2..00000000000 --- a/build/pkgs/nose/install-requires.txt +++ /dev/null @@ -1 +0,0 @@ -nose >=1.3.7 diff --git a/build/pkgs/nose/package-version.txt b/build/pkgs/nose/package-version.txt deleted file mode 100644 index 3336003dccd..00000000000 --- a/build/pkgs/nose/package-version.txt +++ /dev/null @@ -1 +0,0 @@ -1.3.7 diff --git a/build/pkgs/nose/spkg-check.in b/build/pkgs/nose/spkg-check.in deleted file mode 100644 index 9bfbe9f31ab..00000000000 --- a/build/pkgs/nose/spkg-check.in +++ /dev/null @@ -1,5 +0,0 @@ -cd src - -python3 setup.py build_tests - -python3 selftest.py diff --git a/build/pkgs/nose/spkg-install.in b/build/pkgs/nose/spkg-install.in deleted file mode 100644 index fe7461d2f8b..00000000000 --- a/build/pkgs/nose/spkg-install.in +++ /dev/null @@ -1,6 +0,0 @@ -cd src - -# Install new version -echo "Installing nose..." -sdh_pip_install . -echo diff --git a/build/pkgs/nose/type b/build/pkgs/nose/type deleted file mode 100644 index a6a7b9cd726..00000000000 --- a/build/pkgs/nose/type +++ /dev/null @@ -1 +0,0 @@ -standard From 53fa1c7ebf4e1e2b0677eafbcc5d87785342dc9b Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 30 Sep 2021 15:38:23 -0700 Subject: [PATCH 173/359] .github/workflows/ci-cygwin-minimal.yml: Remove nose --- .github/workflows/ci-cygwin-minimal.yml | 2 +- .github/workflows/ci-cygwin-standard.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-cygwin-minimal.yml b/.github/workflows/ci-cygwin-minimal.yml index 8c2a7d2213f..9e847e74740 100644 --- a/.github/workflows/ci-cygwin-minimal.yml +++ b/.github/workflows/ci-cygwin-minimal.yml @@ -84,7 +84,7 @@ jobs: cygwin-stage-i-b: env: STAGE: i-b - TARGETS: cython setuptools_scm kiwisolver dateutil cycler pyparsing nose certifi pkgconfig pplpy + TARGETS: cython setuptools_scm kiwisolver dateutil cycler pyparsing certifi pkgconfig pplpy LOCAL_ARTIFACT_NAME: sage-local-commit-${{ github.sha }}-cygwin-${{ matrix.pkgs }} LOGS_ARTIFACT_NAME: logs-commit-${{ github.sha }}-cygwin-${{ matrix.pkgs }} diff --git a/.github/workflows/ci-cygwin-standard.yml b/.github/workflows/ci-cygwin-standard.yml index a27118d7f17..cbbe0f46a8b 100644 --- a/.github/workflows/ci-cygwin-standard.yml +++ b/.github/workflows/ci-cygwin-standard.yml @@ -84,7 +84,7 @@ jobs: cygwin-stage-i-b: env: STAGE: i-b - TARGETS: cython setuptools_scm kiwisolver dateutil cycler pyparsing nose certifi pkgconfig pplpy + TARGETS: cython setuptools_scm kiwisolver dateutil cycler pyparsing certifi pkgconfig pplpy LOCAL_ARTIFACT_NAME: sage-local-commit-${{ github.sha }}-cygwin-${{ matrix.pkgs }} LOGS_ARTIFACT_NAME: logs-commit-${{ github.sha }}-cygwin-${{ matrix.pkgs }} From 0dba8bca20f6fcd20631e4252791427e45d4d8ea Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 30 Sep 2021 15:39:33 -0700 Subject: [PATCH 174/359] build/pkgs/pkgconfig/SPKG.rst: Remove outdated info --- build/pkgs/pkgconfig/SPKG.rst | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/build/pkgs/pkgconfig/SPKG.rst b/build/pkgs/pkgconfig/SPKG.rst index cd737e14763..3c5d61a167a 100644 --- a/build/pkgs/pkgconfig/SPKG.rst +++ b/build/pkgs/pkgconfig/SPKG.rst @@ -17,16 +17,3 @@ Upstream Contact ---------------- https://github.com/matze/pkgconfig - -Dependencies ------------- - -- Python 2.6+ - - -Special Update/Build Instructions ---------------------------------- - -Standard setup.py - -- remove_nose.patch: Remove the nose dependency (not actually used) From e5bde3ffd7dee5f2119e40b7e448857b71efb128 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 30 Sep 2021 15:41:41 -0700 Subject: [PATCH 175/359] build/bin/write-dockerfile.sh: Update SAGE_CHECK_PACKAGES for removed packages --- build/bin/write-dockerfile.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/build/bin/write-dockerfile.sh b/build/bin/write-dockerfile.sh index 05cfe124966..aa7050b203b 100755 --- a/build/bin/write-dockerfile.sh +++ b/build/bin/write-dockerfile.sh @@ -219,7 +219,7 @@ ARG NUMPROC=8 ENV MAKE="make -j\${NUMPROC}" ARG USE_MAKEFLAGS="-k V=0" ENV SAGE_CHECK=warn -ENV SAGE_CHECK_PACKAGES="!cython,!r,!python3,!python2,!nose,!pathpy,!gap,!cysignals,!linbox,!git,!ppl,!cmake,!networkx,!rpy2,!symengine_py,!sage_sws2rst" +ENV SAGE_CHECK_PACKAGES="!cython,!r,!python3,!gap,!cysignals,!linbox,!git,!ppl,!cmake,!networkx,!rpy2,!symengine_py,!sage_sws2rst" #:toolchain: $RUN make \${USE_MAKEFLAGS} base-toolchain $ENDRUN @@ -228,7 +228,7 @@ ARG NUMPROC=8 ENV MAKE="make -j\${NUMPROC}" ARG USE_MAKEFLAGS="-k V=0" ENV SAGE_CHECK=warn -ENV SAGE_CHECK_PACKAGES="!gfan,!cython,!r,!python3,!python2,!nose,!pathpy,!gap,!cysignals,!linbox,!git,!ppl,!cmake,!networkx,!rpy2,!symengine_py,!sage_sws2rst" +ENV SAGE_CHECK_PACKAGES="!gfan,!cython,!r,!python3,!gap,!cysignals,!linbox,!git,!ppl,!cmake,!networkx,!rpy2,!symengine_py,!sage_sws2rst" #:make: ARG TARGETS_PRE="all-sage-local" $RUN make SAGE_SPKG="sage-spkg -y -o" \${USE_MAKEFLAGS} \${TARGETS_PRE} $ENDRUN @@ -238,7 +238,7 @@ ARG NUMPROC=8 ENV MAKE="make -j\${NUMPROC}" ARG USE_MAKEFLAGS="-k V=0" ENV SAGE_CHECK=warn -ENV SAGE_CHECK_PACKAGES="!gfan,!cython,!r,!python3,!python2,!nose,!pathpy,!gap,!cysignals,!linbox,!git,!ppl,!cmake,!networkx,!rpy2,!symengine_py,!sage_sws2rst" +ENV SAGE_CHECK_PACKAGES="!gfan,!cython,!r,!python3,!gap,!cysignals,!linbox,!git,!ppl,!cmake,!networkx,!rpy2,!symengine_py,!sage_sws2rst" ADD src src ARG TARGETS="build" $RUN make SAGE_SPKG="sage-spkg -y -o" \${USE_MAKEFLAGS} \${TARGETS} $ENDRUN @@ -248,7 +248,7 @@ ARG NUMPROC=8 ENV MAKE="make -j\${NUMPROC}" ARG USE_MAKEFLAGS="-k V=0" ENV SAGE_CHECK=warn -ENV SAGE_CHECK_PACKAGES="!gfan,!cython,!r,!python3,!python2,!nose,!pathpy,!gap,!cysignals,!linbox,!git,!ppl,!cmake,!networkx,!rpy2,!symengine_py,!sage_sws2rst" +ENV SAGE_CHECK_PACKAGES="!gfan,!cython,!r,!python3,!gap,!cysignals,!linbox,!git,!ppl,!cmake,!networkx,!rpy2,!symengine_py,!sage_sws2rst" ARG TARGETS_OPTIONAL="ptest" $RUN make SAGE_SPKG="sage-spkg -y -o" \${USE_MAKEFLAGS} \${TARGETS_OPTIONAL} || echo "(error ignored)" $ENDRUN From 9e5e095234d21c4e73f26d2bde11429ab30cfc8c Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 30 Sep 2021 15:45:11 -0700 Subject: [PATCH 176/359] tox.ini: Update SAGE_CHECK_PACKAGES for removed packages --- tox.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tox.ini b/tox.ini index 9bd5ece819d..d565133513b 100644 --- a/tox.ini +++ b/tox.ini @@ -577,8 +577,8 @@ commands = local: config*) ;; \ local: *) make -k V=0 base-toolchain ;; \ local: esac && \ - local: make -k V=0 SAGE_CHECK=warn SAGE_CHECK_PACKAGES="!cython,!r,!python3,!nose,!gap,!cysignals,!linbox,!git,!ppl,!cmake,!networkx,!rpy2,!symengine_py,!sage_sws2rst" {env:TARGETS_PRE:} {posargs:build} && \ - local: ( [ -z "{env:TARGETS_OPTIONAL:}" ] || make -k V=0 SAGE_CHECK=warn SAGE_CHECK_PACKAGES="!cython,!r,!python3,!nose,!gap,!cysignals,!linbox,!git,!ppl,!cmake,!networkx,!rpy2,!symengine_py,!sage_sws2rst" {env:TARGETS_OPTIONAL:} || echo "(error ignored)" ) ' + local: make -k V=0 SAGE_CHECK=warn SAGE_CHECK_PACKAGES="!cython,!r,!python3,!gap,!cysignals,!linbox,!git,!ppl,!cmake,!networkx,!rpy2,!symengine_py,!sage_sws2rst" {env:TARGETS_PRE:} {posargs:build} && \ + local: ( [ -z "{env:TARGETS_OPTIONAL:}" ] || make -k V=0 SAGE_CHECK=warn SAGE_CHECK_PACKAGES="!cython,!r,!python3,!gap,!cysignals,!linbox,!git,!ppl,!cmake,!networkx,!rpy2,!symengine_py,!sage_sws2rst" {env:TARGETS_OPTIONAL:} || echo "(error ignored)" ) ' [testenv:check_configure] ## Test that configure behaves properly From b3fcbd895c490dc48e8b0d33c3d11811881e3461 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 30 Sep 2021 17:48:48 -0700 Subject: [PATCH 177/359] build/pkgs/symengine[_py]: Update to 0.8.1 --- build/pkgs/symengine/checksums.ini | 6 +++--- build/pkgs/symengine/package-version.txt | 2 +- build/pkgs/symengine_py/checksums.ini | 6 +++--- build/pkgs/symengine_py/package-version.txt | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/build/pkgs/symengine/checksums.ini b/build/pkgs/symengine/checksums.ini index b5600d35000..712c4eddb90 100644 --- a/build/pkgs/symengine/checksums.ini +++ b/build/pkgs/symengine/checksums.ini @@ -1,5 +1,5 @@ tarball=symengine-VERSION.tar.gz -sha1=a4d30b3c417c3939383384b95c8b3c248e4e413e -md5=72b8f1442fd3084c96e59d9fe87eec1a -cksum=3356860163 +sha1=87a0104d8682cb2f192d8b4bf3435a514bdb6f4c +md5=967b913b365eda9fb30ecb3f1ded46f2 +cksum=2359123828 upstream_url=https://github.com/symengine/symengine/releases/download/vVERSION/symengine-VERSION.tar.gz diff --git a/build/pkgs/symengine/package-version.txt b/build/pkgs/symengine/package-version.txt index faef31a4357..6f4eebdf6f6 100644 --- a/build/pkgs/symengine/package-version.txt +++ b/build/pkgs/symengine/package-version.txt @@ -1 +1 @@ -0.7.0 +0.8.1 diff --git a/build/pkgs/symengine_py/checksums.ini b/build/pkgs/symengine_py/checksums.ini index 00b39b8e687..3b0db282ffa 100644 --- a/build/pkgs/symengine_py/checksums.ini +++ b/build/pkgs/symengine_py/checksums.ini @@ -1,5 +1,5 @@ tarball=symengine.py-VERSION.tar.gz -sha1=8535fea222d85c5afefc5122dd5d43d91aa4ebb0 -md5=0167a0081410be856edc8ee245005576 -cksum=4011943203 +sha1=16da67020baf6ab95cd517f58618fa7af1c8fc5e +md5=1c365dd039f8568b732c39fa4c9a7cf4 +cksum=3244910588 upstream_url=https://github.com/symengine/symengine.py/archive/vVERSION.tar.gz diff --git a/build/pkgs/symengine_py/package-version.txt b/build/pkgs/symengine_py/package-version.txt index 5d8391e20f4..6f4eebdf6f6 100644 --- a/build/pkgs/symengine_py/package-version.txt +++ b/build/pkgs/symengine_py/package-version.txt @@ -1 +1 @@ -0.7.0.post2 +0.8.1 From c4faa5fe075435c45a2e2456a687bb442acd009c Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 30 Sep 2021 18:07:03 -0700 Subject: [PATCH 178/359] build/pkgs/symengine/patches/1749.patch: Remove --- build/pkgs/symengine/patches/1749.patch | 44 ------------------------- 1 file changed, 44 deletions(-) delete mode 100644 build/pkgs/symengine/patches/1749.patch diff --git a/build/pkgs/symengine/patches/1749.patch b/build/pkgs/symengine/patches/1749.patch deleted file mode 100644 index 40ff66b1856..00000000000 --- a/build/pkgs/symengine/patches/1749.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 713c096527291b24a8bee47895859f202b6eaa92 Mon Sep 17 00:00:00 2001 -From: Isuru Fernando -Date: Sat, 20 Mar 2021 13:33:17 -0500 -Subject: [PATCH] Check for flint-arb - ---- - cmake/FindARB.cmake | 2 +- - cmake/LibFindMacros.cmake | 4 ++-- - 2 files changed, 3 insertions(+), 3 deletions(-) - -diff --git a/cmake/FindARB.cmake b/cmake/FindARB.cmake -index 770da3133..281c5beae 100644 ---- a/cmake/FindARB.cmake -+++ b/cmake/FindARB.cmake -@@ -1,7 +1,7 @@ - include(LibFindMacros) - - libfind_include(arb.h arb) --libfind_library(arb arb) -+libfind_library(arb arb flint-arb) - - set(ARB_LIBRARIES ${ARB_LIBRARY}) - set(ARB_INCLUDE_DIRS ${ARB_INCLUDE_DIR}) -diff --git a/cmake/LibFindMacros.cmake b/cmake/LibFindMacros.cmake -index 68fcaa426..06aa3f5ba 100644 ---- a/cmake/LibFindMacros.cmake -+++ b/cmake/LibFindMacros.cmake -@@ -28,7 +28,7 @@ function (libfind_library libname pkg) - - find_library(${LIBNAME}_LIBRARY - NAMES -- ${libname} -+ ${libname} ${ARGN} - ) - - if (NOT TARGET ${libname}) -@@ -42,6 +42,6 @@ function (libfind_include HEADER pkg) - - find_path(${PKG}_INCLUDE_DIR - NAMES -- ${HEADER} -+ ${HEADER} ${ARGN} - ) - endfunction() From f929448e8e1effe764fc557c78706aefd72cf0f7 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 30 Sep 2021 18:07:34 -0700 Subject: [PATCH 179/359] build/pkgs/symengine_py: Switch from nose to pytest --- build/pkgs/symengine_py/dependencies | 2 +- build/pkgs/symengine_py/spkg-check.in | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build/pkgs/symengine_py/dependencies b/build/pkgs/symengine_py/dependencies index 1b773295978..a48b85c68e8 100644 --- a/build/pkgs/symengine_py/dependencies +++ b/build/pkgs/symengine_py/dependencies @@ -1,4 +1,4 @@ -symengine $(PYTHON) | cmake cython $(PYTHON_TOOLCHAIN) $(and $(filter-out no,$(SAGE_CHECK_symengine_py)), nose) +symengine $(PYTHON) | cmake cython $(PYTHON_TOOLCHAIN) $(and $(filter-out no,$(SAGE_CHECK_symengine_py)), pytest) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/symengine_py/spkg-check.in b/build/pkgs/symengine_py/spkg-check.in index fba8e388486..ac32958383b 100644 --- a/build/pkgs/symengine_py/spkg-check.in +++ b/build/pkgs/symengine_py/spkg-check.in @@ -1,3 +1,3 @@ cd src -nosetests symengine/tests -v +python3 -m pytest -s -v symengine/tests/test_*.py From 8f1b81693da0065a9daa12bd9c4b98edc601a583 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 30 Sep 2021 21:05:29 -0700 Subject: [PATCH 180/359] build/pkgs/perl_cpan_polymake_prereq/distros: Add info for Term::ReadKey --- build/pkgs/perl_cpan_polymake_prereq/distros/cpan.txt | 1 + build/pkgs/perl_cpan_polymake_prereq/distros/fedora.txt | 1 + build/pkgs/perl_cpan_polymake_prereq/distros/freebsd.txt | 1 + build/pkgs/perl_cpan_polymake_prereq/distros/gentoo.txt | 1 + 4 files changed, 4 insertions(+) diff --git a/build/pkgs/perl_cpan_polymake_prereq/distros/cpan.txt b/build/pkgs/perl_cpan_polymake_prereq/distros/cpan.txt index fbd93fc89a2..131aebf6d3d 100644 --- a/build/pkgs/perl_cpan_polymake_prereq/distros/cpan.txt +++ b/build/pkgs/perl_cpan_polymake_prereq/distros/cpan.txt @@ -4,3 +4,4 @@ XML::LibXSLT File::Slurp JSON SVG +Term::ReadKey diff --git a/build/pkgs/perl_cpan_polymake_prereq/distros/fedora.txt b/build/pkgs/perl_cpan_polymake_prereq/distros/fedora.txt index 89a8a7622bf..c7390e63993 100644 --- a/build/pkgs/perl_cpan_polymake_prereq/distros/fedora.txt +++ b/build/pkgs/perl_cpan_polymake_prereq/distros/fedora.txt @@ -2,6 +2,7 @@ perl-ExtUtils-Embed perl-File-Slurp perl-JSON perl-Term-ReadLine-Gnu +perl-Term-ReadKey perl-XML-Writer perl-XML-LibXML perl-XML-LibXSLT diff --git a/build/pkgs/perl_cpan_polymake_prereq/distros/freebsd.txt b/build/pkgs/perl_cpan_polymake_prereq/distros/freebsd.txt index 9b2b62bccd9..43a596433c9 100644 --- a/build/pkgs/perl_cpan_polymake_prereq/distros/freebsd.txt +++ b/build/pkgs/perl_cpan_polymake_prereq/distros/freebsd.txt @@ -4,3 +4,4 @@ textproc/p5-XML-LibXSLT devel/p5-File-Slurp converters/p5-JSON textproc/p5-SVG +devel/p5-Term-ReadKey diff --git a/build/pkgs/perl_cpan_polymake_prereq/distros/gentoo.txt b/build/pkgs/perl_cpan_polymake_prereq/distros/gentoo.txt index 67835e72530..b4803c6fdac 100644 --- a/build/pkgs/perl_cpan_polymake_prereq/distros/gentoo.txt +++ b/build/pkgs/perl_cpan_polymake_prereq/distros/gentoo.txt @@ -3,5 +3,6 @@ XML-LibXML XML-LibXSLT File-Slurp dev-perl/Term-ReadLine-Gnu +dev-perl/TermReadKey JSON SVG From 654e6ea327c74225ecc5633e074285517bf0f038 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 30 Sep 2021 21:06:20 -0700 Subject: [PATCH 181/359] build/pkgs/{perl_term_readline_gnu,polymake}: Change from experimental to optional --- build/pkgs/perl_term_readline_gnu/type | 2 +- build/pkgs/polymake/type | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build/pkgs/perl_term_readline_gnu/type b/build/pkgs/perl_term_readline_gnu/type index 9839eb20815..134d9bc32d5 100644 --- a/build/pkgs/perl_term_readline_gnu/type +++ b/build/pkgs/perl_term_readline_gnu/type @@ -1 +1 @@ -experimental +optional diff --git a/build/pkgs/polymake/type b/build/pkgs/polymake/type index 9839eb20815..134d9bc32d5 100644 --- a/build/pkgs/polymake/type +++ b/build/pkgs/polymake/type @@ -1 +1 @@ -experimental +optional From bcfe1634895aa509599ed5d0ddb214703c9cff3c Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 30 Sep 2021 21:06:35 -0700 Subject: [PATCH 182/359] build/pkgs/polymake: Update to 4.5 --- build/pkgs/polymake/checksums.ini | 6 +++--- build/pkgs/polymake/package-version.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/pkgs/polymake/checksums.ini b/build/pkgs/polymake/checksums.ini index e059b0e2bbd..081ea86bc52 100644 --- a/build/pkgs/polymake/checksums.ini +++ b/build/pkgs/polymake/checksums.ini @@ -1,5 +1,5 @@ tarball=polymake-VERSION-minimal.tar.bz2 -sha1=5370b16300ff8aed4eb5fa6bb5232d25935e6303 -md5=8f6a8e87e3b8bf5ccf22f26790a4dd1a -cksum=1398515202 +sha1=d50dff3f2124a22563cc468f104c360b81a2c59d +md5=8785d6fca67ef7becad6600dad0fefaf +cksum=1451222436 upstream_url=https://polymake.org/lib/exe/fetch.php/download/polymake-VERSION-minimal.tar.bz2 diff --git a/build/pkgs/polymake/package-version.txt b/build/pkgs/polymake/package-version.txt index 515be8f918d..4caecc733e6 100644 --- a/build/pkgs/polymake/package-version.txt +++ b/build/pkgs/polymake/package-version.txt @@ -1 +1 @@ -4.4 +4.5 From 9d2674b8d443f0524f60f0777c59775cc6fb658e Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 30 Sep 2021 21:24:39 -0700 Subject: [PATCH 183/359] src/sage/interfaces/polymake.py: Mark some more doctests '# optional - polymake_expect' --- src/sage/interfaces/polymake.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sage/interfaces/polymake.py b/src/sage/interfaces/polymake.py index 8ac83e87ad6..06092472a17 100644 --- a/src/sage/interfaces/polymake.py +++ b/src/sage/interfaces/polymake.py @@ -2174,17 +2174,17 @@ def _eval_line(self, line, allow_use_file=True, wait_for_prompt=True, restart_if work in an interactive session and often in doc tests, too. However, sometimes it hangs, and therefore we remove it from the tests, for now:: - sage: c = polymake.cube(15) # optional - polymake - sage: polymake.eval('print {}->F_VECTOR;'.format(c.name()), timeout=1) # not tested # optional - polymake + sage: c = polymake.cube(15) # optional - polymake_expect + sage: polymake.eval('print {}->F_VECTOR;'.format(c.name()), timeout=1) # not tested # optional - polymake_expect Traceback (most recent call last): ... RuntimeError: Polymake fails to respond timely We verify that after the timeout, polymake is still able to give answers:: - sage: c # optional - polymake + sage: c # optional - polymake_expect cube of dimension 15 - sage: c.N_VERTICES # optional - polymake + sage: c.N_VERTICES # optional - polymake_expect 32768 Note, however, that the recovery after a timeout is not perfect. From 9e74b6a96bbd946a6944a5e078e411dc0a412cf3 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 28 Sep 2021 18:31:15 -0700 Subject: [PATCH 184/359] sage.rings.abc: Add IntegerModRing, Order; use them in sage.matrix, sage.modules --- src/sage/matrix/matrix0.pyx | 4 ++-- src/sage/modules/free_module.py | 6 +++--- src/sage/rings/abc.pyx | 15 +++++++++++++++ src/sage/rings/finite_rings/integer_mod_ring.py | 2 +- src/sage/rings/number_field/order.py | 3 ++- 5 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/sage/matrix/matrix0.pyx b/src/sage/matrix/matrix0.pyx index 41b8da5f415..92c87e3a2ec 100644 --- a/src/sage/matrix/matrix0.pyx +++ b/src/sage/matrix/matrix0.pyx @@ -44,7 +44,7 @@ from sage.categories.integral_domains import IntegralDomains from sage.rings.ring cimport CommutativeRing from sage.rings.ring import is_Ring -from sage.rings.finite_rings.integer_mod_ring import is_IntegerModRing +import sage.rings.abc from sage.rings.integer_ring import is_IntegerRing import sage.modules.free_module @@ -5749,7 +5749,7 @@ cdef class Matrix(sage.structure.element.Matrix): R = self.base_ring() if algorithm is None and R in _Fields: return ~self - elif algorithm is None and is_IntegerModRing(R): + elif algorithm is None and isinstance(R, sage.rings.abc.IntegerModRing): # Finite fields are handled above. # This is "easy" in that we either get an error or # the right answer. Note that of course there diff --git a/src/sage/modules/free_module.py b/src/sage/modules/free_module.py index 57c10114174..4ff7ec743a1 100644 --- a/src/sage/modules/free_module.py +++ b/src/sage/modules/free_module.py @@ -172,7 +172,7 @@ import sage.rings.ring as ring import sage.rings.integer_ring import sage.rings.rational_field -import sage.rings.finite_rings.integer_mod_ring +import sage.rings.abc import sage.rings.infinity import sage.rings.integer from sage.categories.principal_ideal_domains import PrincipalIdealDomains @@ -253,7 +253,7 @@ def create_object(self, version, key): elif base_ring in PrincipalIdealDomains(): return FreeModule_ambient_pid(base_ring, rank, sparse=sparse) - elif isinstance(base_ring, sage.rings.number_field.order.Order) \ + elif isinstance(base_ring, sage.rings.abc.Order) \ and base_ring.is_maximal() and base_ring.class_number() == 1: return FreeModule_ambient_pid(base_ring, rank, sparse=sparse) @@ -7434,7 +7434,7 @@ def element_class(R, is_sparse): elif sage.rings.rational_field.is_RationalField(R) and not is_sparse: from .vector_rational_dense import Vector_rational_dense return Vector_rational_dense - elif sage.rings.finite_rings.integer_mod_ring.is_IntegerModRing(R) and not is_sparse: + elif isinstance(R, sage.rings.abc.IntegerModRing) and not is_sparse: from .vector_mod2_dense import Vector_mod2_dense if R.order() == 2: return Vector_mod2_dense diff --git a/src/sage/rings/abc.pyx b/src/sage/rings/abc.pyx index c65e03d9ed0..147dcb4f089 100644 --- a/src/sage/rings/abc.pyx +++ b/src/sage/rings/abc.pyx @@ -32,3 +32,18 @@ cdef class ComplexDoubleField(Field): """ pass + + +class IntegerModRing: + r""" + Abstract base class for :class:`~sage.rings.finite_rings.integer_mod_ring.IntegerModRing_generic`. + """ + + pass + +class Order: + r""" + Abstract base class for :class:`~sage.rings.number_field.order.Order`. + """ + + pass diff --git a/src/sage/rings/finite_rings/integer_mod_ring.py b/src/sage/rings/finite_rings/integer_mod_ring.py index c704b2a2eb7..c225d412a11 100644 --- a/src/sage/rings/finite_rings/integer_mod_ring.py +++ b/src/sage/rings/finite_rings/integer_mod_ring.py @@ -297,7 +297,7 @@ def _unit_gens_primepowercase(p, r): @richcmp_method -class IntegerModRing_generic(quotient_ring.QuotientRing_generic): +class IntegerModRing_generic(quotient_ring.QuotientRing_generic, IntegerModRing): """ The ring of integers modulo `N`. diff --git a/src/sage/rings/number_field/order.py b/src/sage/rings/number_field/order.py index 56ef3d550bb..ec128df7834 100644 --- a/src/sage/rings/number_field/order.py +++ b/src/sage/rings/number_field/order.py @@ -47,6 +47,7 @@ from sage.rings.ring import IntegralDomain from sage.structure.sequence import Sequence from sage.rings.integer_ring import ZZ +import sage.rings.abc from sage.structure.element import is_Element from .number_field_element import OrderElement_absolute, OrderElement_relative @@ -126,7 +127,7 @@ def EquationOrder(f, names, **kwds): return K.order(K.gens()) -class Order(IntegralDomain): +class Order(IntegralDomain, sage.rings.abc.Order): r""" An order in a number field. From 8ef2b356025c3bc055f3bed1d63bce65956cb221 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 28 Sep 2021 19:08:25 -0700 Subject: [PATCH 185/359] sage.structure, sage.rings, sage.matrix: Use sage.rings.abc for IntegerModRing --- src/sage/matrix/matrix2.pyx | 9 +++++---- src/sage/matrix/matrix_space.py | 4 ++-- src/sage/rings/finite_rings/finite_field_base.pyx | 4 ++-- src/sage/structure/parent.pyx | 4 ++-- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/sage/matrix/matrix2.pyx b/src/sage/matrix/matrix2.pyx index d4a8ec9d3a1..74e01aa7241 100644 --- a/src/sage/matrix/matrix2.pyx +++ b/src/sage/matrix/matrix2.pyx @@ -95,6 +95,7 @@ from sage.rings.real_mpfr import RealField from sage.rings.complex_mpfr import ComplexField from sage.rings.finite_rings.integer_mod_ring import IntegerModRing from sage.misc.derivative import multi_derivative +import sage.rings.abc from sage.arith.numerical_approx cimport digits_to_bits from copy import copy @@ -822,8 +823,7 @@ cdef class Matrix(Matrix1): if not K.is_integral_domain(): # The non-integral-domain case is handled almost entirely # separately. - from sage.rings.finite_rings.integer_mod_ring import is_IntegerModRing - if is_IntegerModRing(K): + if isinstance(K, sage.rings.abc.IntegerModRing): from sage.libs.pari import pari A = pari(self.lift()) b = pari(B).lift() @@ -1985,7 +1985,6 @@ cdef class Matrix(Matrix1): sage: A.determinant() == B.determinant() True """ - from sage.rings.finite_rings.integer_mod_ring import is_IntegerModRing from sage.symbolic.ring import is_SymbolicExpressionRing cdef Py_ssize_t n @@ -2031,7 +2030,7 @@ cdef class Matrix(Matrix1): return d # Special case for Z/nZ or GF(p): - if is_IntegerModRing(R) and self.is_dense(): + if isinstance(R, sage.rings.abc.IntegerModRing) and self.is_dense(): import sys # If the characteristic is prime and smaller than a machine # word, use PARI. @@ -14723,6 +14722,8 @@ cdef class Matrix(Matrix1): for i from 0 <= i < size: PyList_Append(M,f(PyList_GET_ITEM(L,i))) + from sage.rings.finite_rings.integer_mod_ring import IntegerModRing + return MatrixSpace(IntegerModRing(2), nrows=self._nrows,ncols=self._ncols).matrix(M) diff --git a/src/sage/matrix/matrix_space.py b/src/sage/matrix/matrix_space.py index 47766db0c46..eabba820926 100644 --- a/src/sage/matrix/matrix_space.py +++ b/src/sage/matrix/matrix_space.py @@ -236,7 +236,7 @@ def get_matrix_class(R, nrows, ncols, sparse, implementation): except ImportError: pass - if sage.rings.finite_rings.integer_mod_ring.is_IntegerModRing(R): + if isinstance(R, sage.rings.abc.IntegerModRing): from . import matrix_modn_dense_double, matrix_modn_dense_float if R.order() < matrix_modn_dense_float.MAX_MODULUS: return matrix_modn_dense_float.Matrix_modn_dense_float @@ -326,7 +326,7 @@ def get_matrix_class(R, nrows, ncols, sparse, implementation): if implementation is not None: raise ValueError("cannot choose an implementation for sparse matrices") - if sage.rings.finite_rings.integer_mod_ring.is_IntegerModRing(R) and R.order() < matrix_modn_sparse.MAX_MODULUS: + if isinstance(R, sage.rings.abc.IntegerModRing) and R.order() < matrix_modn_sparse.MAX_MODULUS: return matrix_modn_sparse.Matrix_modn_sparse if sage.rings.rational_field.is_RationalField(R): diff --git a/src/sage/rings/finite_rings/finite_field_base.pyx b/src/sage/rings/finite_rings/finite_field_base.pyx index 91f69730fee..f3183df44aa 100644 --- a/src/sage/rings/finite_rings/finite_field_base.pyx +++ b/src/sage/rings/finite_rings/finite_field_base.pyx @@ -40,6 +40,7 @@ from sage.misc.persist import register_unpickle_override from sage.misc.cachefunc import cached_method from sage.misc.prandom import randrange from sage.rings.integer cimport Integer +import sage.rings.abc from sage.misc.superseded import deprecation_cython as deprecation # Copied from sage.misc.fast_methods, used in __hash__() below. @@ -1342,10 +1343,9 @@ cdef class FiniteField(Field): False """ from sage.rings.integer_ring import ZZ - from sage.rings.finite_rings.integer_mod_ring import is_IntegerModRing if R is int or R is long or R is ZZ: return True - if is_IntegerModRing(R) and self.characteristic().divides(R.characteristic()): + if isinstance(R, sage.rings.abc.IntegerModRing) and self.characteristic().divides(R.characteristic()): return R.hom((self.one(),), check=False) if is_FiniteField(R): if R is self: diff --git a/src/sage/structure/parent.pyx b/src/sage/structure/parent.pyx index 4559972c94f..9d7527b913a 100644 --- a/src/sage/structure/parent.pyx +++ b/src/sage/structure/parent.pyx @@ -2642,8 +2642,8 @@ cdef class Parent(sage.structure.category_object.CategoryObject): elif self_on_left and op is operator.pow: S_is_int = parent_is_integers(S) if not S_is_int: - from sage.rings.finite_rings.integer_mod_ring import is_IntegerModRing - if is_IntegerModRing(S): + from sage.rings.abc import IntegerModRing + if isinstance(S, IntegerModRing): # We allow powering by an IntegerMod by treating it # as an integer. # From 335cd3e8f0b6b16195c5b59cfa806582b61248fa Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 30 Sep 2021 21:45:17 -0700 Subject: [PATCH 186/359] Replace all uses of is_IntegerModRing by isinstance(..., sage.rings.abc.IntegerModRing) --- src/sage/libs/singular/ring.pyx | 4 ++-- src/sage/matrix/matrix_rational_dense.pyx | 4 ++-- src/sage/rings/polynomial/multi_polynomial_ideal.py | 4 ++-- src/sage/rings/polynomial/multi_polynomial_libsingular.pyx | 4 ++-- src/sage/rings/polynomial/polynomial_element.pyx | 5 ++--- src/sage/rings/polynomial/polynomial_ring_constructor.py | 4 ++-- src/sage/rings/polynomial/polynomial_singular_interface.py | 6 +++--- src/sage/schemes/elliptic_curves/constructor.py | 4 ++-- src/sage/schemes/elliptic_curves/ell_generic.py | 4 ++-- src/sage/symbolic/ring.pyx | 4 ++-- 10 files changed, 21 insertions(+), 22 deletions(-) diff --git a/src/sage/libs/singular/ring.pyx b/src/sage/libs/singular/ring.pyx index 63b63070cd2..2f9ece4d055 100644 --- a/src/sage/libs/singular/ring.pyx +++ b/src/sage/libs/singular/ring.pyx @@ -31,7 +31,7 @@ from sage.libs.singular.decl cimport rDefault, GFInfo, ZnmInfo, nInitChar, AlgEx from sage.rings.integer cimport Integer from sage.rings.integer_ring cimport IntegerRing_class from sage.rings.integer_ring import ZZ -from sage.rings.finite_rings.integer_mod_ring import is_IntegerModRing +import sage.rings.abc from sage.rings.number_field.number_field_base cimport NumberField from sage.rings.rational_field import RationalField from sage.rings.finite_rings.finite_field_base import FiniteField as FiniteField_generic @@ -324,7 +324,7 @@ cdef ring *singular_ring_new(base_ring, n, names, term_order) except NULL: _ring = rDefault (_cf ,nvars, _names, nblcks, _order, _block0, _block1, _wvhdl) - elif is_IntegerModRing(base_ring): + elif isinstance(base_ring, sage.rings.abc.IntegerModRing): ch = base_ring.characteristic() if ch < 2: diff --git a/src/sage/matrix/matrix_rational_dense.pyx b/src/sage/matrix/matrix_rational_dense.pyx index d67529c0a7e..3432de8c349 100644 --- a/src/sage/matrix/matrix_rational_dense.pyx +++ b/src/sage/matrix/matrix_rational_dense.pyx @@ -109,7 +109,7 @@ from sage.rings.integer cimport Integer from sage.rings.ring import is_Ring from sage.rings.integer_ring import ZZ, is_IntegerRing from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF -from sage.rings.finite_rings.integer_mod_ring import is_IntegerModRing +import sage.rings.abc from sage.rings.rational_field import QQ from sage.arith.all import gcd @@ -1487,7 +1487,7 @@ cdef class Matrix_rational_dense(Matrix_dense): return A from .matrix_modn_dense_double import MAX_MODULUS - if is_IntegerModRing(R) and R.order() < MAX_MODULUS: + if isinstance(R, sage.rings.abc.IntegerModRing) and R.order() < MAX_MODULUS: b = R.order() A, d = self._clear_denom() if not b.gcd(d).is_one(): diff --git a/src/sage/rings/polynomial/multi_polynomial_ideal.py b/src/sage/rings/polynomial/multi_polynomial_ideal.py index da88a329bc6..65e5e7ee7a1 100644 --- a/src/sage/rings/polynomial/multi_polynomial_ideal.py +++ b/src/sage/rings/polynomial/multi_polynomial_ideal.py @@ -249,6 +249,7 @@ from sage.misc.method_decorator import MethodDecorator from sage.rings.integer_ring import ZZ +import sage.rings.abc import sage.rings.polynomial.toy_buchberger as toy_buchberger import sage.rings.polynomial.toy_variety as toy_variety import sage.rings.polynomial.toy_d_basis as toy_d_basis @@ -4288,7 +4289,6 @@ def groebner_basis(self, algorithm='', deg_bound=None, mult_bound=None, prot=Fal sage: I.groebner_basis('magma:GroebnerBasis') # optional - magma [a + (-60)*c^3 + 158/7*c^2 + 8/7*c - 1, b + 30*c^3 + (-79/7)*c^2 + 3/7*c, c^4 + (-10/21)*c^3 + 1/84*c^2 + 1/84*c] """ - from sage.rings.finite_rings.integer_mod_ring import is_IntegerModRing from sage.rings.polynomial.multi_polynomial_sequence import PolynomialSequence from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing @@ -4331,7 +4331,7 @@ def groebner_basis(self, algorithm='', deg_bound=None, mult_bound=None, prot=Fal deg_bound=deg_bound, mult_bound=mult_bound, prot=prot, *args, **kwds)] elif (R.term_order().is_global() - and is_IntegerModRing(B) + and isinstance(B, sage.rings.abc.IntegerModRing) and not B.is_field()): verbose("Warning: falling back to very slow toy implementation.", level=0) diff --git a/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx b/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx index ec706f3129d..9380bffc850 100644 --- a/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx +++ b/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx @@ -221,6 +221,7 @@ from sage.rings.polynomial.polydict cimport ETuple from sage.rings.polynomial.polynomial_ring import is_PolynomialRing # base ring imports +import sage.rings.abc from sage.rings.finite_rings.finite_field_prime_modn import FiniteField_prime_modn from sage.rings.rational cimport Rational from sage.rings.rational_field import QQ @@ -229,7 +230,6 @@ from sage.rings.real_mpfr import is_RealField from sage.rings.integer_ring import is_IntegerRing, ZZ from sage.rings.integer cimport Integer from sage.rings.integer import GCD_list -from sage.rings.finite_rings.integer_mod_ring import is_IntegerModRing from sage.rings.number_field.number_field_base cimport NumberField from sage.structure.element import coerce_binop @@ -1407,7 +1407,7 @@ cdef class MPolynomialRing_libsingular(MPolynomialRing_base): elif is_IntegerRing(base_ring): self.__singular = singular.ring("(integer)", _vars, order=order) - elif is_IntegerModRing(base_ring): + elif isinstance(base_ring, sage.rings.abc.IntegerModRing): ch = base_ring.characteristic() if ch.is_power_of(2): exp = ch.nbits() -1 diff --git a/src/sage/rings/polynomial/polynomial_element.pyx b/src/sage/rings/polynomial/polynomial_element.pyx index f7807221d55..1e948372613 100644 --- a/src/sage/rings/polynomial/polynomial_element.pyx +++ b/src/sage/rings/polynomial/polynomial_element.pyx @@ -101,7 +101,6 @@ from sage.structure.element cimport (parent, have_same_parent, from sage.rings.rational_field import QQ, is_RationalField from sage.rings.integer_ring import ZZ, is_IntegerRing -from sage.rings.finite_rings.integer_mod_ring import is_IntegerModRing from sage.rings.integer cimport Integer, smallInteger from sage.libs.gmp.mpz cimport * from sage.rings.fraction_field import is_FractionField @@ -4446,7 +4445,7 @@ cdef class Polynomial(CommutativeAlgebraElement): n = None - if is_IntegerModRing(R) or is_IntegerRing(R): + if isinstance(R, sage.rings.abc.IntegerModRing) or is_IntegerRing(R): try: G = list(self._pari_with_name().factor()) except PariError: @@ -8124,7 +8123,7 @@ cdef class Polynomial(CommutativeAlgebraElement): if K.is_finite(): if multiplicities: raise NotImplementedError("root finding with multiplicities for this polynomial not implemented (try the multiplicities=False option)") - elif is_IntegerModRing(K): + elif isinstance(K, sage.rings.abc.IntegerModRing): # handling via the chinese remainders theorem N = K.cardinality() primes = N.prime_divisors() diff --git a/src/sage/rings/polynomial/polynomial_ring_constructor.py b/src/sage/rings/polynomial/polynomial_ring_constructor.py index c88f6705ccd..603bdaff2ec 100644 --- a/src/sage/rings/polynomial/polynomial_ring_constructor.py +++ b/src/sage/rings/polynomial/polynomial_ring_constructor.py @@ -27,9 +27,9 @@ import sage.rings.ring as ring import sage.rings.padics.padic_base_leaves as padic_base_leaves +import sage.rings.abc from sage.rings.integer import Integer from sage.rings.finite_rings.finite_field_base import is_FiniteField -from sage.rings.finite_rings.integer_mod_ring import is_IntegerModRing from sage.misc.cachefunc import weak_cached_function @@ -694,7 +694,7 @@ def _single_variate(base_ring, name, sparse=None, implementation=None, order=Non # Specialized implementations specialized = None - if is_IntegerModRing(base_ring): + if isinstance(base_ring, sage.rings.abc.IntegerModRing): n = base_ring.order() if n.is_prime(): specialized = polynomial_ring.PolynomialRing_dense_mod_p diff --git a/src/sage/rings/polynomial/polynomial_singular_interface.py b/src/sage/rings/polynomial/polynomial_singular_interface.py index 61777d5556a..d8b537789be 100644 --- a/src/sage/rings/polynomial/polynomial_singular_interface.py +++ b/src/sage/rings/polynomial/polynomial_singular_interface.py @@ -38,13 +38,13 @@ ###################################################################### import sage.rings.fraction_field +import sage.rings.abc import sage.rings.number_field as number_field from sage.interfaces.all import singular from sage.rings.complex_mpfr import is_ComplexField from sage.rings.real_mpfr import is_RealField from sage.rings.complex_double import is_ComplexDoubleField -from sage.rings.finite_rings.integer_mod_ring import is_IntegerModRing from sage.rings.real_double import is_RealDoubleField from sage.rings.rational_field import is_RationalField from sage.rings.function_field.function_field import RationalFunctionField @@ -336,7 +336,7 @@ def _singular_init_(self, singular=singular): gen = str(base_ring.gen()) self.__singular = singular.ring( "(%s,%s)"%(base_ring.characteristic(),gen), _vars, order=order, check=False) - elif is_IntegerModRing(base_ring): + elif isinstance(base_ring, sage.rings.abc.IntegerModRing): ch = base_ring.characteristic() if ch.is_power_of(2): exp = ch.nbits() -1 @@ -388,7 +388,7 @@ def can_convert_to_singular(R): if (base_ring is ZZ or sage.rings.finite_rings.finite_field_constructor.is_FiniteField(base_ring) or is_RationalField(base_ring) - or is_IntegerModRing(base_ring) + or isinstance(base_ring, sage.rings.abc.IntegerModRing) or is_RealField(base_ring) or is_ComplexField(base_ring) or is_RealDoubleField(base_ring) diff --git a/src/sage/schemes/elliptic_curves/constructor.py b/src/sage/schemes/elliptic_curves/constructor.py index e9320cc174b..90bc4519082 100644 --- a/src/sage/schemes/elliptic_curves/constructor.py +++ b/src/sage/schemes/elliptic_curves/constructor.py @@ -25,7 +25,7 @@ import sage.rings.all as rings -from sage.rings.finite_rings.integer_mod_ring import is_IntegerModRing +import sage.rings.abc from sage.rings.polynomial.multi_polynomial_ring import is_MPolynomialRing from sage.rings.finite_rings.finite_field_constructor import is_FiniteField from sage.rings.number_field.number_field import is_NumberField @@ -464,7 +464,7 @@ def create_object(self, version, key, **kwds): elif rings.is_pAdicField(R): from .ell_padic_field import EllipticCurve_padic_field return EllipticCurve_padic_field(R, x) - elif is_FiniteField(R) or (is_IntegerModRing(R) and R.characteristic().is_prime()): + elif is_FiniteField(R) or (isinstance(R, sage.rings.abc.IntegerModRing) and R.characteristic().is_prime()): from .ell_finite_field import EllipticCurve_finite_field return EllipticCurve_finite_field(R, x) elif R in _Fields: diff --git a/src/sage/schemes/elliptic_curves/ell_generic.py b/src/sage/schemes/elliptic_curves/ell_generic.py index 912496bca28..b5207f513f0 100644 --- a/src/sage/schemes/elliptic_curves/ell_generic.py +++ b/src/sage/schemes/elliptic_curves/ell_generic.py @@ -46,6 +46,7 @@ import math +import sage.rings.abc from sage.rings.all import PolynomialRing from sage.rings.polynomial.polynomial_ring import polygen, polygens import sage.groups.additive_abelian.additive_abelian_group as groups @@ -156,8 +157,7 @@ def __init__(self, K, ainvs): # EllipticCurvePoint_finite_field for finite rings, so that we # can do some arithmetic on points over Z/NZ, for teaching # purposes. - from sage.rings.finite_rings.integer_mod_ring import is_IntegerModRing - if is_IntegerModRing(K): + if isinstance(K, sage.rings.abc.IntegerModRing): self._point = ell_point.EllipticCurvePoint_finite_field _point = ell_point.EllipticCurvePoint diff --git a/src/sage/symbolic/ring.pyx b/src/sage/symbolic/ring.pyx index ffe8d7443f2..9bc5c1db7a1 100644 --- a/src/sage/symbolic/ring.pyx +++ b/src/sage/symbolic/ring.pyx @@ -47,6 +47,7 @@ from sage.structure.element cimport Element from sage.categories.morphism cimport Morphism from sage.structure.coerce cimport is_numpy_type +import sage.rings.abc from sage.rings.integer_ring import ZZ # is_SymbolicVariable used to be defined here; re-export it @@ -205,7 +206,6 @@ cdef class SymbolicRing(CommutativeRing): from sage.rings.real_mpfr import mpfr_prec_min from sage.rings.fraction_field import is_FractionField - from sage.rings.finite_rings.integer_mod_ring import is_IntegerModRing from sage.rings.real_mpfi import is_RealIntervalField from sage.rings.complex_interval_field import is_ComplexIntervalField from sage.rings.real_arb import RealBallField @@ -234,7 +234,7 @@ cdef class SymbolicRing(CommutativeRing): or is_RealIntervalField(R) or is_ComplexIntervalField(R) or isinstance(R, RealBallField) or isinstance(R, ComplexBallField) - or is_IntegerModRing(R) or is_FiniteField(R)): + or isinstance(R, sage.rings.abc.IntegerModRing) or is_FiniteField(R)): return True elif isinstance(R, GenericSymbolicSubring): return True From f596395836a4c6e3f7a42b56acc4a805c8633abf Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 28 Sep 2021 21:14:44 -0700 Subject: [PATCH 187/359] sage.rings.finite_rings.integer_mod_ring: Fixup --- src/sage/rings/finite_rings/integer_mod_ring.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/sage/rings/finite_rings/integer_mod_ring.py b/src/sage/rings/finite_rings/integer_mod_ring.py index c225d412a11..27ea7f424fc 100644 --- a/src/sage/rings/finite_rings/integer_mod_ring.py +++ b/src/sage/rings/finite_rings/integer_mod_ring.py @@ -64,6 +64,7 @@ from sage.arith.all import factor, primitive_root, CRT_basis import sage.rings.ring as ring +import sage.rings.abc from . import integer_mod import sage.rings.integer as integer import sage.rings.integer_ring as integer_ring @@ -297,7 +298,7 @@ def _unit_gens_primepowercase(p, r): @richcmp_method -class IntegerModRing_generic(quotient_ring.QuotientRing_generic, IntegerModRing): +class IntegerModRing_generic(quotient_ring.QuotientRing_generic, sage.rings.abc.IntegerModRing): """ The ring of integers modulo `N`. From 00de6e6d69b40c7e0c9ad207628854292b237bdb Mon Sep 17 00:00:00 2001 From: dcoudert Date: Fri, 1 Oct 2021 17:25:34 +0200 Subject: [PATCH 188/359] trac #14657: better documentation for set_embedding --- src/sage/graphs/generic_graph.py | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/src/sage/graphs/generic_graph.py b/src/sage/graphs/generic_graph.py index 6a966a01e3f..12f265e0316 100644 --- a/src/sage/graphs/generic_graph.py +++ b/src/sage/graphs/generic_graph.py @@ -2470,14 +2470,23 @@ def set_embedding(self, embedding): """ Set a combinatorial embedding dictionary to ``_embedding`` attribute. - Dictionary is organized with vertex labels as keys and a list of each - vertex's neighbors in clockwise order. + The dictionary ``embedding`` represents a combinatorial embedding of + ``self`` and is organized as a mapping from vertex labels to list of + vertex neighbors in clockwise order. - Dictionary is error-checked for validity. + Parameter ``embedding`` is error-checked for validity. + + .. WARNING:: + + Combinatorial embeddings are defined for simple graphs only (i.e., + without loops or multiple edges). Therefore, an error is raised when + this method is used for a graph with loops or multiple edges. INPUT: - - ``embedding`` -- a dictionary + - ``embedding`` -- dictionary representing a combinatorial embedding of + ``self``. Format: "{v1: [v2,v3], v2: [v1], v3: [v1]}" (clockwise + ordering of neighbors at each vertex). EXAMPLES:: @@ -2487,7 +2496,21 @@ def set_embedding(self, embedding): Traceback (most recent call last): ... ValueError: vertices in ['s'] from the embedding do not belong to the graph + + TESTS:: + + sage: G = Graph([(0, 0)], loops=True) + sage: G.set_embedding({0: [0]}) + Traceback (most recent call last): + ... + ValueError: This method is not known to work on graphs with loops. Perhaps this method can be updated to handle them, but in the meantime if you want to use it please disallow loops using allow_loops(). + sage: G = Graph([(0, 1), (0, 1)], multiedges=True) + sage: G.set_embedding({0: [1], 1: [0]}) + Traceback (most recent call last): + ... + ValueError: This method is not known to work on graphs with multiedges. Perhaps this method can be updated to handle them, but in the meantime if you want to use it please disallow multiedges using allow_multiple_edges(). """ + self._scream_if_not_simple() self._check_embedding_validity(embedding, boolean=False) self._embedding = embedding From af06e5b43bd15181de7b1f6123dda5839f248699 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 1 Oct 2021 09:02:22 -0700 Subject: [PATCH 189/359] is_IntegerModRing: Deprecate --- src/sage/rings/finite_rings/integer_mod_ring.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/sage/rings/finite_rings/integer_mod_ring.py b/src/sage/rings/finite_rings/integer_mod_ring.py index 27ea7f424fc..28fb2736491 100644 --- a/src/sage/rings/finite_rings/integer_mod_ring.py +++ b/src/sage/rings/finite_rings/integer_mod_ring.py @@ -244,11 +244,18 @@ def is_IntegerModRing(x): """ Return ``True`` if ``x`` is an integer modulo ring. + This function is deprecated. Use :func:`isinstance` with + :class:`sage.rings.abc.IntegerModRing` instead. + EXAMPLES:: sage: from sage.rings.finite_rings.integer_mod_ring import is_IntegerModRing sage: R = IntegerModRing(17) sage: is_IntegerModRing(R) + doctest:warning... + DeprecationWarning: the function is_IntegerModRing is deprecated. + Use isinstance(..., sage.rings.abc.IntegerModRing) instead. + See https://trac.sagemath.org/32606 for details. True sage: is_IntegerModRing(GF(13)) True @@ -259,6 +266,9 @@ def is_IntegerModRing(x): sage: is_IntegerModRing(ZZ) False """ + from sage.misc.superseded import deprecation + deprecation(32606, "the function is_IntegerModRing is deprecated. " + "Use isinstance(..., sage.rings.abc.IntegerModRing) instead.") return isinstance(x, IntegerModRing_generic) From 1a845fa1d975fa76396b3c48c2441b41b043c829 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 1 Oct 2021 09:04:59 -0700 Subject: [PATCH 190/359] src/sage/geometry/polyhedron/parent.py: Add missing import --- src/sage/geometry/polyhedron/parent.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sage/geometry/polyhedron/parent.py b/src/sage/geometry/polyhedron/parent.py index 002c93e9dfb..0091b5e12fb 100644 --- a/src/sage/geometry/polyhedron/parent.py +++ b/src/sage/geometry/polyhedron/parent.py @@ -14,6 +14,7 @@ from sage.structure.unique_representation import UniqueRepresentation from sage.modules.free_module import FreeModule, is_FreeModule from sage.misc.cachefunc import cached_method, cached_function +from sage.misc.lazy_import import lazy_import from sage.rings.all import ZZ, QQ, RDF, CommutativeRing from sage.categories.fields import Fields from sage.categories.rings import Rings From 015b89911e606112327f57949e3bce7af1a0595b Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 1 Oct 2021 10:23:51 -0700 Subject: [PATCH 191/359] build/bin/sage-print-system-package-command: Handle cpan --- build/bin/sage-print-system-package-command | 3 +++ 1 file changed, 3 insertions(+) diff --git a/build/bin/sage-print-system-package-command b/build/bin/sage-print-system-package-command index 618c88174e0..6be76bdaf5f 100755 --- a/build/bin/sage-print-system-package-command +++ b/build/bin/sage-print-system-package-command @@ -149,6 +149,9 @@ case $system:$command in pip:install) [ -n "$system_packages" ] && print_shell_command "sage -pip install $system_packages" ;; + cpan:install) + [ -n "$system_packages" ] && print_shell_command "cpan -i $system_packages" + ;; repology:install) if [ -n "$system_packages" ]; then links="" From fc0e37c7e30db6bc11f6c88f2941ac1529549908 Mon Sep 17 00:00:00 2001 From: Isuru Fernando Date: Fri, 1 Oct 2021 10:31:59 -0700 Subject: [PATCH 192/359] fix symengine_py tests --- build/pkgs/symengine_py/spkg-check.in | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/build/pkgs/symengine_py/spkg-check.in b/build/pkgs/symengine_py/spkg-check.in index ac32958383b..5ead50de889 100644 --- a/build/pkgs/symengine_py/spkg-check.in +++ b/build/pkgs/symengine_py/spkg-check.in @@ -1,3 +1,7 @@ cd src -python3 -m pytest -s -v symengine/tests/test_*.py +# since the module is not built in place, go to a new directory +mkdir empty +cd empty + +python3 ../bin/test_python.py From 27a265c12b0df142f0b08a5875ea81482d80a361 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 1 Oct 2021 12:07:52 -0700 Subject: [PATCH 193/359] src/sage/geometry/polyhedron/parent.py: Fixup --- src/sage/geometry/polyhedron/parent.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/geometry/polyhedron/parent.py b/src/sage/geometry/polyhedron/parent.py index 0091b5e12fb..7228c64b3ea 100644 --- a/src/sage/geometry/polyhedron/parent.py +++ b/src/sage/geometry/polyhedron/parent.py @@ -1129,7 +1129,7 @@ def _make_Line(self, polyhedron, data): from sage.geometry.polyhedron.backend_cdd import Polyhedron_QQ_cdd -lazy_import('sage.geometry.polyhedron.backend_cdd_rdf', Polyhedron_RDF_cdd) +lazy_import('sage.geometry.polyhedron.backend_cdd_rdf', 'Polyhedron_RDF_cdd') from sage.geometry.polyhedron.backend_ppl import Polyhedron_ZZ_ppl, Polyhedron_QQ_ppl from sage.geometry.polyhedron.backend_normaliz import Polyhedron_normaliz, Polyhedron_ZZ_normaliz, Polyhedron_QQ_normaliz from sage.geometry.polyhedron.backend_polymake import Polyhedron_polymake From 73aabd22000d7703710df29ad89434d790d4e6b6 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 1 Oct 2021 17:52:30 -0700 Subject: [PATCH 194/359] src/sage/sets/condition_set.py: Fix up import --- src/sage/sets/condition_set.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sage/sets/condition_set.py b/src/sage/sets/condition_set.py index b9373e65fad..c779ed9b356 100644 --- a/src/sage/sets/condition_set.py +++ b/src/sage/sets/condition_set.py @@ -295,6 +295,7 @@ def arguments(self): sage: args[0].parent() Symbolic Ring """ + from sage.symbolic.ring import SR return SR.var(self.variable_names()) def _element_constructor_(self, *args, **kwds): From 1b2bdbb5c295085f08fe4350ea417f20c8d23d4f Mon Sep 17 00:00:00 2001 From: Isuru Fernando Date: Fri, 1 Oct 2021 19:30:26 -0700 Subject: [PATCH 195/359] Fix getting string representation of sage objects --- ...tring-representation-of-sage-objects.patch | 118 ++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 build/pkgs/symengine_py/patches/0001-Fix-getting-string-representation-of-sage-objects.patch diff --git a/build/pkgs/symengine_py/patches/0001-Fix-getting-string-representation-of-sage-objects.patch b/build/pkgs/symengine_py/patches/0001-Fix-getting-string-representation-of-sage-objects.patch new file mode 100644 index 00000000000..78c71610b53 --- /dev/null +++ b/build/pkgs/symengine_py/patches/0001-Fix-getting-string-representation-of-sage-objects.patch @@ -0,0 +1,118 @@ +From 68c90c14ae3e779b88a513195cc89db599d10efb Mon Sep 17 00:00:00 2001 +From: Isuru Fernando +Date: Fri, 1 Oct 2021 19:25:07 -0700 +Subject: [PATCH] Fix getting string representation of sage objects + +--- + symengine/lib/pywrapper.cpp | 17 ++++++----------- + symengine/lib/symengine_wrapper.pyx | 9 ++++++--- + symengine/tests/test_sage.py | 10 +++------- + symengine/tests/test_sympy_conv.py | 1 + + 4 files changed, 16 insertions(+), 21 deletions(-) + +diff --git a/symengine/lib/pywrapper.cpp b/symengine/lib/pywrapper.cpp +index ca7b7c1..c321ea3 100644 +--- a/symengine/lib/pywrapper.cpp ++++ b/symengine/lib/pywrapper.cpp +@@ -175,17 +175,12 @@ RCP PyNumber::eval(long bits) const { + } + + std::string PyNumber::__str__() const { +- PyObject* temp; +- std::string str; +-#if PY_MAJOR_VERSION > 2 +- temp = PyUnicode_AsUTF8String(pyobject_); +- str = std::string(PyBytes_AsString(temp)); +-#else +- temp = PyObject_Str(pyobject_); +- str = std::string(PyString_AsString(temp)); +-#endif +- Py_XDECREF(temp); +- return str; ++ Py_ssize_t size; ++ PyObject *pystr = PyObject_Str(pyobject_); ++ const char* data = PyUnicode_AsUTF8AndSize(pystr, &size); ++ std::string result = std::string(data, size); ++ Py_XDECREF(pystr); ++ return result; + } + + // PyFunctionClass +diff --git a/symengine/lib/symengine_wrapper.pyx b/symengine/lib/symengine_wrapper.pyx +index d178afe..d18c058 100644 +--- a/symengine/lib/symengine_wrapper.pyx ++++ b/symengine/lib/symengine_wrapper.pyx +@@ -2690,7 +2690,7 @@ class FunctionSymbol(Function): + def _sage_(self): + import sage.all as sage + name = self.get_name() +- return sage.function(name, *self.args_as_sage()) ++ return sage.function(name)(*self.args_as_sage()) + + def func(self, *values): + name = self.get_name() +@@ -2711,7 +2711,7 @@ cdef rcp_const_basic pynumber_to_symengine(PyObject* o1): + + cdef PyObject* symengine_to_sage(rcp_const_basic o1): + import sage.all as sage +- t = sage.SR(c2py(o1)._sage_()) ++ t = c2py(o1)._sage_() + Py_XINCREF(t) + return (t) + +@@ -2765,7 +2765,10 @@ cdef class PyNumber(Number): + + def _sage_(self): + import sage.all as sage +- return sage.SR(self.pyobject()) ++ res = self.pyobject() ++ if hasattr(res, '_sage_'): ++ return res._sage_() ++ return res + + def pyobject(self): + return deref(symengine.rcp_static_cast_PyNumber(self.thisptr)).get_py_object() +diff --git a/symengine/tests/test_sage.py b/symengine/tests/test_sage.py +index 3b994ab..e364bd6 100644 +--- a/symengine/tests/test_sage.py ++++ b/symengine/tests/test_sage.py +@@ -66,9 +66,9 @@ def test_sage_conversions(): + assert cos(x1)._sage_() == sage.cos(x) + assert cos(x1) == sympify(sage.cos(x)) + +- assert function_symbol('f', x1, y1)._sage_() == sage.function('f', x, y) ++ assert function_symbol('f', x1, y1)._sage_() == sage.function('f')(x, y) + assert (function_symbol('f', 2 * x1, x1 + y1).diff(x1)._sage_() == +- sage.function('f', 2 * x, x + y).diff(x)) ++ sage.function('f')(2 * x, x + y).diff(x)) + + assert LambertW(x1) == LambertW(x) + assert LambertW(x1)._sage_() == sage.lambert_w(x) +@@ -142,11 +142,7 @@ def test_sage_conversions(): + b = b + 8 + assert isinstance(b, PyNumber) + assert b._sage_() == a +- +- a = a + x +- b = b + x +- assert isinstance(b, Add) +- assert b._sage_() == a ++ assert str(a) == str(b) + + # Sage Function + e = x1 + wrap_sage_function(sage.log_gamma(x)) +diff --git a/symengine/tests/test_sympy_conv.py b/symengine/tests/test_sympy_conv.py +index 3f8b152..ee070a8 100644 +--- a/symengine/tests/test_sympy_conv.py ++++ b/symengine/tests/test_sympy_conv.py +@@ -760,6 +760,7 @@ def test_pynumber(): + assert isinstance(b, PyNumber) + assert b == a # Check equality via SymEngine + assert a == b # Check equality via SymPy ++ assert str(a) == str(b) + + a = 1 - a + b = 1 - b +-- +2.7.4 + From 6dd3e5bc36d46fb8482163dde0f7dec1c9fefa6c Mon Sep 17 00:00:00 2001 From: Isuru Fernando Date: Sat, 2 Oct 2021 06:52:11 -0700 Subject: [PATCH 196/359] update version for a rebuild --- build/pkgs/symengine_py/package-version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/pkgs/symengine_py/package-version.txt b/build/pkgs/symengine_py/package-version.txt index 6f4eebdf6f6..25329dc9cba 100644 --- a/build/pkgs/symengine_py/package-version.txt +++ b/build/pkgs/symengine_py/package-version.txt @@ -1 +1 @@ -0.8.1 +0.8.1.p0 From a16530020d7b48e53616880f4987139d1fac749c Mon Sep 17 00:00:00 2001 From: Kwankyu Lee Date: Sat, 2 Oct 2021 23:33:26 +0900 Subject: [PATCH 197/359] Speed up ideal multiplication --- src/sage/rings/function_field/ideal.py | 122 ++++++++++++++++++++----- 1 file changed, 99 insertions(+), 23 deletions(-) diff --git a/src/sage/rings/function_field/ideal.py b/src/sage/rings/function_field/ideal.py index 4230b3780a0..3dbadab335c 100644 --- a/src/sage/rings/function_field/ideal.py +++ b/src/sage/rings/function_field/ideal.py @@ -99,6 +99,8 @@ from sage.structure.factorization import Factorization from sage.structure.unique_representation import UniqueRepresentation +from sage.arith.power import generic_power + from sage.modules.free_module_element import vector from sage.categories.monoids import Monoids @@ -1228,6 +1230,12 @@ def __init__(self, ring, hnf, denominator=1): # for fast multiplication with other ideal. self._kummer_form = None + # tuple of at most two gens: + # the first gen is an element of the base ring of the maximal order + # the second gen is the vector form of an element of the maximal order + # if the second gen is zero, the tuple has only the first gen. + self._gens_two_vecs = None + def __bool__(self): """ Test if this ideal is zero. @@ -1514,6 +1522,20 @@ def _mul_(self, other): elif other._kummer_form is not None: p, q = other._kummer_form vecs = list(p * self._hnf) + [mul(q, v) for v in self._hnf] + elif self._gens_two_vecs is not None: + if len(self._gens_two_vecs) == 1: + g1, = self._gens_two_vecs + vecs = list(g1 * other._hnf) + else: + g1, g2 = self._gens_two_vecs + vecs = list(g1 * other._hnf) + [mul(g2, v) for v in other._hnf] + elif other._gens_two_vecs is not None: + if len(other._gens_two_vecs) == 1: + g1, = other._gens_two_vecs + vecs = list(g1 * self._hnf) + else: + g1, g2 = other._gens_two_vecs + vecs = list(g1 * self._hnf) + [mul(g2, v) for v in self._hnf] else: vecs = [mul(r1,r2) for r1 in self._hnf for r2 in other._hnf] @@ -2138,6 +2160,53 @@ def __init__(self, ring, hnf, denominator=1): """ FunctionFieldIdeal_polymod.__init__(self, ring, hnf, denominator) + def __pow__(self, mod): + """ + Return ``self`` to the power of ``mod``. + + If a two-generators representation of ``self`` is known, it is used + to speed up powering. + + EXAMPLES:: + + sage: K. = FunctionField(GF(2)); _. = K[] + sage: L. = K.extension(Y^7 - x^3*Y - x) + sage: O = L.maximal_order() + sage: I = O.ideal(y) + sage: J = O.ideal(x + y) + sage: S = I / J + sage: S^100 == I^100 / J^100 + True + sage: _ = S.gens_two() + sage: S^100 == I^100 / J^100 # faster + True + """ + if mod > 2 and self._gens_two_vecs is not None: + O = self._ring + mul = O._mul_vecs + R = self._hnf.base_ring() + n = self._hnf.ncols() + + I = matrix.identity(R, n) + + if len(self._gens_two_vecs) == 1: + p, = self._gens_two_vecs + ppow = p**mod + J = [ppow * v for v in I] + else: + p, q = self._gens_two_vecs + if len(self._gens_two.cache) == 2: + _, q = self._gens_two.cache + else: + q = sum(e1 * e2 for e1,e2 in zip(O.basis(), q)) + ppow = p**mod + qpow = O._coordinate_vector(q**mod) + J = [ppow * v for v in I] + [mul(qpow,v) for v in I] + + return O._ideal_from_vectors_and_denominator(J, self._denominator**mod) + + return generic_power(self, mod) + def gens(self): """ Return a set of generators of this ideal. @@ -2171,26 +2240,6 @@ def gens_two(self): If the ideal is principal, one generator *may* be returned. - ALGORITHM: - - At most two generators are required to generate ideals in - Dedekind domains. - - Lemma 4.7.9, algorithm 4.7.10, and exercise 4.29 of [Coh1993]_ - tell us that for an integral ideal `I` in a number field, if - we pick `a` such that `\gcd(N(I), N(a)/N(I)) = 1`, then `a` - and `N(I)` generate the ideal. `N()` is the norm, and this - result (presumably) generalizes to function fields. - - After computing `N(I)`, we search exhaustively to find `a`. - - .. TODO:: - - Always return a single generator for a principal ideal. - - Testing for principality is not trivial. Algorithm 6.5.10 - of [Coh1993]_ could probably be adapted for function fields. - EXAMPLES:: sage: K. = FunctionField(GF(2)); _. = K[] @@ -2224,6 +2273,26 @@ def _gens_two(self): Return a set of two generators of the integral ideal, that is the denominator times this fractional ideal. + ALGORITHM: + + At most two generators are required to generate ideals in + Dedekind domains. + + Lemma 4.7.9, algorithm 4.7.10, and exercise 4.29 of [Coh1993]_ + tell us that for an integral ideal `I` in a number field, if + we pick `a` such that `\gcd(N(I), N(a)/N(I)) = 1`, then `a` + and `N(I)` generate the ideal. `N()` is the norm, and this + result (presumably) generalizes to function fields. + + After computing `N(I)`, we search exhaustively to find `a`. + + .. TODO:: + + Always return a single generator for a principal ideal. + + Testing for principality is not trivial. Algorithm 6.5.10 + of [Coh1993]_ could probably be adapted for function fields. + EXAMPLES:: sage: K. = FunctionField(GF(4)); _. = K[] @@ -2247,8 +2316,10 @@ def _gens_two(self): g1 = F(_g1) g2 = sum([c1*c2 for c1,c2 in zip(_g2, O.basis())]) if g2: + self._gens_two_vecs = (_g1, _g2) return (g1,g2) else: + self._gens_two_vecs = (_g1,) return (g1,) ### start to search for two generators @@ -2260,14 +2331,16 @@ def _gens_two(self): norm *= e if norm.is_constant(): # unit ideal + self._gens_two_vecs = (1,) return (F(1),) # one generator; see .ideal_below() - l = hnf[0][0] - p = l.degree() - l = F(l) + _l = hnf[0][0] + p = _l.degree() + l = F(_l) if self._hnf == O.ideal(l)._hnf: # principal ideal + self._gens_two_vecs = (_l,) return (l,) R = hnf.base_ring() @@ -2286,6 +2359,7 @@ def check(alpha): # Trial 1: search for alpha among generators for alpha in basis: if check(alpha): + self._gens_two_vecs = (_l, O._coordinate_vector(alpha)) return (l, alpha) # Trial 2: exhaustive search for alpha using only polynomials @@ -2295,6 +2369,7 @@ def check(alpha): for g in G: alpha = sum([R(c1)*c2 for c1,c2 in zip(g, basis)]) if check(alpha): + self._gens_two_vecs = (_l, O._coordinate_vector(alpha)) return (l, alpha) # Trial 3: exhaustive search for alpha using all polynomials @@ -2312,6 +2387,7 @@ def check(alpha): alpha = sum([c1*c2 for c1,c2 in zip(g, basis)]) if check(alpha): + self._gens_two_vecs = (_l, O._coordinate_vector(alpha)) return (l, alpha) # should not reach here From 608148900e8764bb654ddcdcdb15a1e890acba94 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 2 Oct 2021 10:17:24 -0700 Subject: [PATCH 198/359] git grep -l -E 'is_(Real|Complex)(Double)?Field' | xargs sed -E -i.bak 's/^from sage[.]rings.*import is_((Real|Complex)(Double)?Field) *$/import sage.rings.abc/;s/is_((Real|Complex)(Double)?Field)[(]([^)]*)[)]/isinstance(\4, sage.rings.abc.\1)/g;' --- .../arithmetic_dynamics/projective_ds.py | 2 +- src/sage/functions/orthogonal_polys.py | 12 +++--- src/sage/functions/special.py | 2 +- src/sage/matrix/misc.pyx | 2 +- src/sage/modular/dirichlet.py | 12 +++--- src/sage/modules/free_module.py | 4 +- src/sage/probability/random_variable.py | 2 +- src/sage/quadratic_forms/special_values.py | 4 +- src/sage/rings/complex_double.pyx | 6 +-- src/sage/rings/complex_mpfr.pyx | 4 +- src/sage/rings/number_field/number_field.py | 6 +-- .../number_field/number_field_element.pyx | 2 +- .../multi_polynomial_libsingular.pyx | 8 ++-- .../rings/polynomial/polynomial_element.pyx | 40 +++++++++---------- src/sage/rings/polynomial/polynomial_ring.py | 4 +- .../polynomial_singular_interface.py | 24 +++++------ src/sage/rings/real_double.pyx | 6 +-- src/sage/rings/real_mpfr.pyx | 6 +-- src/sage/schemes/elliptic_curves/ell_field.py | 8 ++-- .../elliptic_curves/ell_number_field.py | 2 +- src/sage/schemes/elliptic_curves/ell_point.py | 8 ++-- .../schemes/elliptic_curves/period_lattice.py | 14 +++---- src/sage/schemes/plane_conics/con_field.py | 8 ++-- .../plane_conics/con_rational_field.py | 6 +-- src/sage/symbolic/expression.pyx | 6 +-- 25 files changed, 99 insertions(+), 99 deletions(-) diff --git a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py index 164c4c35f47..e5f2b9225cf 100644 --- a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py +++ b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py @@ -2065,7 +2065,7 @@ def canonical_height(self, P, **kwds): # it uses Real or Complex Double Field in place of RealField(prec) or ComplexField(prec) # the function is_RealField does not identify RDF as real, so we test for that ourselves. for v in emb: - if is_RealField(v.codomain()) or v.codomain() is RDF: + if isinstance(v.codomain(, sage.rings.abc.RealField)) or v.codomain() is RDF: dv = R.one() else: dv = R(2) diff --git a/src/sage/functions/orthogonal_polys.py b/src/sage/functions/orthogonal_polys.py index 9b5636f3fdc..c879cd6c8fe 100644 --- a/src/sage/functions/orthogonal_polys.py +++ b/src/sage/functions/orthogonal_polys.py @@ -304,8 +304,8 @@ from sage.misc.latex import latex from sage.rings.all import ZZ, QQ, RR, CC from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing -from sage.rings.real_mpfr import is_RealField -from sage.rings.complex_mpfr import is_ComplexField +import sage.rings.abc +import sage.rings.abc from sage.symbolic.function import BuiltinFunction, GinacFunction from sage.symbolic.expression import Expression @@ -672,7 +672,7 @@ def _evalf_(self, n, x, **kwds): except KeyError: real_parent = parent(x) - if not is_RealField(real_parent) and not is_ComplexField(real_parent): + if not isinstance(real_parent, sage.rings.abc.RealField) and not isinstance(real_parent, sage.rings.abc.ComplexField): # parent is not a real or complex field: figure out a good parent if x in RR: x = RR(x) @@ -681,7 +681,7 @@ def _evalf_(self, n, x, **kwds): x = CC(x) real_parent = CC - if not is_RealField(real_parent) and not is_ComplexField(real_parent): + if not isinstance(real_parent, sage.rings.abc.RealField) and not isinstance(real_parent, sage.rings.abc.ComplexField): raise TypeError("cannot evaluate chebyshev_T with parent {}".format(real_parent)) from sage.libs.mpmath.all import call as mpcall @@ -1031,7 +1031,7 @@ def _evalf_(self, n, x, **kwds): except KeyError: real_parent = parent(x) - if not is_RealField(real_parent) and not is_ComplexField(real_parent): + if not isinstance(real_parent, sage.rings.abc.RealField) and not isinstance(real_parent, sage.rings.abc.ComplexField): # parent is not a real or complex field: figure out a good parent if x in RR: x = RR(x) @@ -1040,7 +1040,7 @@ def _evalf_(self, n, x, **kwds): x = CC(x) real_parent = CC - if not is_RealField(real_parent) and not is_ComplexField(real_parent): + if not isinstance(real_parent, sage.rings.abc.RealField) and not isinstance(real_parent, sage.rings.abc.ComplexField): raise TypeError("cannot evaluate chebyshev_U with parent {}".format(real_parent)) from sage.libs.mpmath.all import call as mpcall diff --git a/src/sage/functions/special.py b/src/sage/functions/special.py index d48208a21d0..c409631f392 100644 --- a/src/sage/functions/special.py +++ b/src/sage/functions/special.py @@ -365,7 +365,7 @@ def elliptic_j(z, prec=53): CC = z.parent() from sage.rings.complex_mpfr import is_ComplexField - if not is_ComplexField(CC): + if not isinstance(CC, sage.rings.abc.ComplexField): CC = ComplexField(prec) try: z = CC(z) diff --git a/src/sage/matrix/misc.pyx b/src/sage/matrix/misc.pyx index 9008edf5920..a70a9a0f711 100644 --- a/src/sage/matrix/misc.pyx +++ b/src/sage/matrix/misc.pyx @@ -510,7 +510,7 @@ def hadamard_row_bound_mpfr(Matrix A): ... OverflowError: cannot convert float infinity to integer """ - if not is_RealField(A.base_ring()): + if not isinstance(A.base_ring(, sage.rings.abc.RealField)): raise TypeError("A must have base field an mpfr real field.") cdef RealNumber a, b diff --git a/src/sage/modular/dirichlet.py b/src/sage/modular/dirichlet.py index 53492ad517f..f71ef1e6f17 100644 --- a/src/sage/modular/dirichlet.py +++ b/src/sage/modular/dirichlet.py @@ -68,7 +68,7 @@ from sage.categories.map import Map from sage.rings.rational_field import is_RationalField -from sage.rings.complex_mpfr import is_ComplexField +import sage.rings.abc from sage.rings.qqbar import is_AlgebraicField from sage.rings.ring import is_Ring @@ -1153,7 +1153,7 @@ def _pari_init_(self): # now compute the input for pari (list of exponents) P = self.parent() - if is_ComplexField(P.base_ring()): + if isinstance(P.base_ring(, sage.rings.abc.ComplexField)): zeta = P.zeta() zeta_argument = zeta.argument() v = [int(x.argument() / zeta_argument) for x in values_on_gens] @@ -1345,7 +1345,7 @@ def gauss_sum(self, a=1): K = G.base_ring() chi = self m = G.modulus() - if is_ComplexField(K): + if isinstance(K, sage.rings.abc.ComplexField): return self.gauss_sum_numerical(a=a) elif is_AlgebraicField(K): L = K @@ -1422,7 +1422,7 @@ def gauss_sum_numerical(self, prec=53, a=1): """ G = self.parent() K = G.base_ring() - if is_ComplexField(K): + if isinstance(K, sage.rings.abc.ComplexField): def phi(t): return t @@ -2138,7 +2138,7 @@ def element(self): """ P = self.parent() M = P._module - if is_ComplexField(P.base_ring()): + if isinstance(P.base_ring(, sage.rings.abc.ComplexField)): zeta = P.zeta() zeta_argument = zeta.argument() v = M([int(round(x.argument() / zeta_argument)) @@ -2607,7 +2607,7 @@ def _zeta_powers(self): w = [a] zeta = self.zeta() zeta_order = self.zeta_order() - if is_ComplexField(R): + if isinstance(R, sage.rings.abc.ComplexField): for i in range(1, zeta_order): a = a * zeta a._set_multiplicative_order(zeta_order / gcd(zeta_order, i)) diff --git a/src/sage/modules/free_module.py b/src/sage/modules/free_module.py index 57c10114174..6288e77cf76 100644 --- a/src/sage/modules/free_module.py +++ b/src/sage/modules/free_module.py @@ -7443,9 +7443,9 @@ def element_class(R, is_sparse): return Vector_modn_dense else: return free_module_element.FreeModuleElement_generic_dense - elif sage.rings.real_double.is_RealDoubleField(R) and not is_sparse: + elif sage.rings.real_double.isinstance(R, sage.rings.abc.RealDoubleField) and not is_sparse: return sage.modules.vector_real_double_dense.Vector_real_double_dense - elif sage.rings.complex_double.is_ComplexDoubleField(R) and not is_sparse: + elif sage.rings.complex_double.isinstance(R, sage.rings.abc.ComplexDoubleField) and not is_sparse: return sage.modules.vector_complex_double_dense.Vector_complex_double_dense elif sage.symbolic.ring.is_SymbolicExpressionRing(R) and not is_sparse: import sage.modules.vector_symbolic_dense diff --git a/src/sage/probability/random_variable.py b/src/sage/probability/random_variable.py index 5355636aa56..ea2c4c86b2f 100644 --- a/src/sage/probability/random_variable.py +++ b/src/sage/probability/random_variable.py @@ -338,7 +338,7 @@ def __init__(self, X, P, codomain=None, check=False): """ if codomain is None: codomain = RealField() - if not is_RealField(codomain) and not is_RationalField(codomain): + if not isinstance(codomain, sage.rings.abc.RealField) and not is_RationalField(codomain): raise TypeError("Argument codomain (= %s) must be the reals or rationals" % codomain) if check: one = sum(P.values()) diff --git a/src/sage/quadratic_forms/special_values.py b/src/sage/quadratic_forms/special_values.py index 47f8ec3008f..5c7e3a1ccfe 100644 --- a/src/sage/quadratic_forms/special_values.py +++ b/src/sage/quadratic_forms/special_values.py @@ -15,7 +15,7 @@ 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.rings.real_mpfr import is_RealField +import sage.rings.abc from sage.symbolic.constants import pi, I # ---------------- The Gamma Function ------------------ @@ -278,7 +278,7 @@ def quadratic_L_function__numerical(n, d, num_terms=1000): ....: print("Oops! We have a problem at d = {}: exact = {}, numerical = {}".format(d, RR(quadratic_L_function__exact(1, d)), RR(quadratic_L_function__numerical(1, d)))) """ # Set the correct precision if it is given (for n). - if is_RealField(n.parent()): + if isinstance(n.parent(, sage.rings.abc.RealField)): R = n.parent() else: R = RealField() diff --git a/src/sage/rings/complex_double.pyx b/src/sage/rings/complex_double.pyx index 3c47faf4344..7621cc043c2 100644 --- a/src/sage/rings/complex_double.pyx +++ b/src/sage/rings/complex_double.pyx @@ -111,16 +111,16 @@ from sage.structure.richcmp cimport rich_to_bool cimport gmpy2 gmpy2.import_gmpy2() -def is_ComplexDoubleField(x): +def isinstance(x, sage.rings.abc.ComplexDoubleField): """ Return ``True`` if ``x`` is the complex double field. EXAMPLES:: sage: from sage.rings.complex_double import is_ComplexDoubleField - sage: is_ComplexDoubleField(CDF) + sage: isinstance(CDF, sage.rings.abc.ComplexDoubleField) True - sage: is_ComplexDoubleField(ComplexField(53)) + sage: isinstance(ComplexField(53, sage.rings.abc.ComplexDoubleField)) False """ return isinstance(x, ComplexDoubleField_class) diff --git a/src/sage/rings/complex_mpfr.pyx b/src/sage/rings/complex_mpfr.pyx index d121e29d537..d3d32b69de5 100644 --- a/src/sage/rings/complex_mpfr.pyx +++ b/src/sage/rings/complex_mpfr.pyx @@ -157,7 +157,7 @@ def is_ComplexNumber(x): """ return isinstance(x, ComplexNumber) -def is_ComplexField(x): +def isinstance(x, sage.rings.abc.ComplexField): """ Check if ``x`` is a :class:`complex field `. @@ -543,7 +543,7 @@ class ComplexField_class(ring.Field): RR = self._real_field() if RR.has_coerce_map_from(S): return RRtoCC(RR, self) * RR._internal_coerce_map_from(S) - if is_ComplexField(S): + if isinstance(S, sage.rings.abc.ComplexField): if self._prec <= S._prec: return self._generic_coerce_map(S) else: diff --git a/src/sage/rings/number_field/number_field.py b/src/sage/rings/number_field/number_field.py index 3ad7ffa26ef..bc626635105 100644 --- a/src/sage/rings/number_field/number_field.py +++ b/src/sage/rings/number_field/number_field.py @@ -9949,12 +9949,12 @@ def hilbert_symbol(self, a, b, P = None): from sage.rings.complex_interval_field import is_ComplexIntervalField from sage.rings.real_mpfr import is_RealField from sage.rings.all import (AA, CDF, QQbar, RDF) - if is_ComplexField(codom) or is_ComplexIntervalField(codom) or \ + if isinstance(codom, sage.rings.abc.ComplexField) or is_ComplexIntervalField(codom) or \ codom is CDF or codom is QQbar: if P(self.gen()).imag() == 0: raise ValueError("Possibly real place (=%s) given as complex embedding in hilbert_symbol. Is it real or complex?" % P) return 1 - if is_RealField(codom) or codom is RDF or codom is AA: + if isinstance(codom, sage.rings.abc.RealField) or codom is RDF or codom is AA: if P(a) > 0 or P(b) > 0: return 1 return -1 @@ -12317,7 +12317,7 @@ def refine_embedding(e, prec=None): return e # We first compute all the embeddings at the new precision: - if sage.rings.real_mpfr.is_RealField(RC) or RC in (RDF, RLF): + if sage.rings.real_mpfr.isinstance(RC, sage.rings.abc.RealField) or RC in (RDF, RLF): if prec == Infinity: elist = K.embeddings(sage.rings.qqbar.AA) else: diff --git a/src/sage/rings/number_field/number_field_element.pyx b/src/sage/rings/number_field/number_field_element.pyx index 37af865e4f5..4ee3d048f07 100644 --- a/src/sage/rings/number_field/number_field_element.pyx +++ b/src/sage/rings/number_field/number_field_element.pyx @@ -3946,7 +3946,7 @@ cdef class NumberFieldElement(FieldElement): return Kv.zero() ht = a.log() from sage.rings.real_mpfr import is_RealField - if weighted and not is_RealField(Kv): + if weighted and not isinstance(Kv, sage.rings.abc.RealField): ht*=2 return ht diff --git a/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx b/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx index ec706f3129d..f32e42d83f3 100644 --- a/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx +++ b/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx @@ -224,8 +224,8 @@ from sage.rings.polynomial.polynomial_ring import is_PolynomialRing from sage.rings.finite_rings.finite_field_prime_modn import FiniteField_prime_modn from sage.rings.rational cimport Rational from sage.rings.rational_field import QQ -from sage.rings.complex_mpfr import is_ComplexField -from sage.rings.real_mpfr import is_RealField +import sage.rings.abc +import sage.rings.abc from sage.rings.integer_ring import is_IntegerRing, ZZ from sage.rings.integer cimport Integer from sage.rings.integer import GCD_list @@ -1366,14 +1366,14 @@ cdef class MPolynomialRing_libsingular(MPolynomialRing_base): base_ring = self.base_ring() - if is_RealField(base_ring): + if isinstance(base_ring, sage.rings.abc.RealField): # singular converts to bits from base_10 in mpr_complex.cc by: # size_t bits = 1 + (size_t) ((float)digits * 3.5); precision = base_ring.precision() digits = ceil((2*precision - 2)/7.0) self.__singular = singular.ring("(real,%d,0)"%digits, _vars, order=order) - elif is_ComplexField(base_ring): + elif isinstance(base_ring, sage.rings.abc.ComplexField): # singular converts to bits from base_10 in mpr_complex.cc by: # size_t bits = 1 + (size_t) ((float)digits * 3.5); precision = base_ring.precision() diff --git a/src/sage/rings/polynomial/polynomial_element.pyx b/src/sage/rings/polynomial/polynomial_element.pyx index dabc030c828..70f026179a4 100644 --- a/src/sage/rings/polynomial/polynomial_element.pyx +++ b/src/sage/rings/polynomial/polynomial_element.pyx @@ -7912,25 +7912,25 @@ cdef class Polynomial(CommutativeAlgebraElement): late_import() - input_fp = (is_RealField(K) - or is_ComplexField(K) - or is_RealDoubleField(K) - or is_ComplexDoubleField(K)) - output_fp = (is_RealField(L) - or is_ComplexField(L) - or is_RealDoubleField(L) - or is_ComplexDoubleField(L)) - input_complex = (is_ComplexField(K) - or is_ComplexDoubleField(K)) - output_complex = (is_ComplexField(L) - or is_ComplexDoubleField(L)) + input_fp = (isinstance(K, sage.rings.abc.RealField) + or isinstance(K, sage.rings.abc.ComplexField) + or isinstance(K, sage.rings.abc.RealDoubleField) + or isinstance(K, sage.rings.abc.ComplexDoubleField)) + output_fp = (isinstance(L, sage.rings.abc.RealField) + or isinstance(L, sage.rings.abc.ComplexField) + or isinstance(L, sage.rings.abc.RealDoubleField) + or isinstance(L, sage.rings.abc.ComplexDoubleField)) + input_complex = (isinstance(K, sage.rings.abc.ComplexField) + or isinstance(K, sage.rings.abc.ComplexDoubleField)) + output_complex = (isinstance(L, sage.rings.abc.ComplexField) + or isinstance(L, sage.rings.abc.ComplexDoubleField)) input_gaussian = (isinstance(K, NumberField_quadratic) and list(K.polynomial()) == [1, 0, 1]) if input_fp and output_fp: # allow for possibly using a fast but less reliable # floating point algorithm from numpy - low_prec = is_RealDoubleField(K) or is_ComplexDoubleField(K) + low_prec = isinstance(K, sage.rings.abc.RealDoubleField) or isinstance(K, sage.rings.abc.ComplexDoubleField) if algorithm is None: if low_prec: algorithm = 'either' @@ -7943,8 +7943,8 @@ cdef class Polynomial(CommutativeAlgebraElement): # We should support GSL, too. We could also support PARI's # old Newton-iteration algorithm. - input_arbprec = (is_RealField(K) or - is_ComplexField(K)) + input_arbprec = (isinstance(K, sage.rings.abc.RealField) or + isinstance(K, sage.rings.abc.ComplexField)) if algorithm == 'numpy' or algorithm == 'either': if K.prec() > 53 and L.prec() > 53: @@ -8082,7 +8082,7 @@ cdef class Polynomial(CommutativeAlgebraElement): # If we want the complex roots, and the input is not # floating point, we convert to a real polynomial # (except when the input coefficients are Gaussian rationals). - if is_ComplexDoubleField(L): + if isinstance(L, sage.rings.abc.ComplexDoubleField): real_field = RDF else: real_field = RealField(L.prec()) @@ -8250,7 +8250,7 @@ cdef class Polynomial(CommutativeAlgebraElement): True """ K = self.base_ring() - if is_RealField(K) or is_RealDoubleField(K): + if isinstance(K, sage.rings.abc.RealField) or isinstance(K, sage.rings.abc.RealDoubleField): return self.roots(multiplicities=False) return self.roots(ring=RR, multiplicities=False) @@ -8292,11 +8292,11 @@ cdef class Polynomial(CommutativeAlgebraElement): True """ K = self.base_ring() - if is_RealField(K): + if isinstance(K, sage.rings.abc.RealField): return self.roots(ring=ComplexField(K.prec()), multiplicities=False) - if is_RealDoubleField(K): + if isinstance(K, sage.rings.abc.RealDoubleField): return self.roots(ring=CDF, multiplicities=False) - if is_ComplexField(K) or is_ComplexDoubleField(K): + if isinstance(K, sage.rings.abc.ComplexField) or isinstance(K, sage.rings.abc.ComplexDoubleField): return self.roots(multiplicities=False) return self.roots(ring=CC, multiplicities=False) diff --git a/src/sage/rings/polynomial/polynomial_ring.py b/src/sage/rings/polynomial/polynomial_ring.py index 7cef097c1a8..b480bd09ff0 100644 --- a/src/sage/rings/polynomial/polynomial_ring.py +++ b/src/sage/rings/polynomial/polynomial_ring.py @@ -165,7 +165,7 @@ from sage.misc.cachefunc import cached_method from sage.misc.lazy_attribute import lazy_attribute -from sage.rings.real_mpfr import is_RealField +import sage.rings.abc from sage.rings.fraction_field_element import FractionFieldElement from sage.rings.finite_rings.element_base import FiniteRingElement @@ -1995,7 +1995,7 @@ def __init__(self, base_ring, name="x", sparse=False, element_class=None, catego else: from sage.rings.polynomial.polynomial_number_field import Polynomial_relative_number_field_dense element_class = Polynomial_relative_number_field_dense - elif is_RealField(base_ring): + elif isinstance(base_ring, sage.rings.abc.RealField): element_class = PolynomialRealDense elif isinstance(base_ring, sage.rings.complex_arb.ComplexBallField): from sage.rings.polynomial.polynomial_complex_arb import Polynomial_complex_arb diff --git a/src/sage/rings/polynomial/polynomial_singular_interface.py b/src/sage/rings/polynomial/polynomial_singular_interface.py index 61777d5556a..256bb0997cc 100644 --- a/src/sage/rings/polynomial/polynomial_singular_interface.py +++ b/src/sage/rings/polynomial/polynomial_singular_interface.py @@ -41,11 +41,11 @@ import sage.rings.number_field as number_field from sage.interfaces.all import singular -from sage.rings.complex_mpfr import is_ComplexField -from sage.rings.real_mpfr import is_RealField -from sage.rings.complex_double import is_ComplexDoubleField +import sage.rings.abc +import sage.rings.abc +import sage.rings.abc from sage.rings.finite_rings.integer_mod_ring import is_IntegerModRing -from sage.rings.real_double import is_RealDoubleField +import sage.rings.abc from sage.rings.rational_field import is_RationalField from sage.rings.function_field.function_field import RationalFunctionField from sage.rings.finite_rings.finite_field_base import is_FiniteField @@ -257,26 +257,26 @@ def _singular_init_(self, singular=singular): base_ring = self.base_ring() - if is_RealField(base_ring): + if isinstance(base_ring, sage.rings.abc.RealField): # singular converts to bits from base_10 in mpr_complex.cc by: # size_t bits = 1 + (size_t) ((float)digits * 3.5); precision = base_ring.precision() digits = sage.arith.all.integer_ceil((2*precision - 2)/7.0) self.__singular = singular.ring("(real,%d,0)"%digits, _vars, order=order, check=False) - elif is_ComplexField(base_ring): + elif isinstance(base_ring, sage.rings.abc.ComplexField): # singular converts to bits from base_10 in mpr_complex.cc by: # size_t bits = 1 + (size_t) ((float)digits * 3.5); precision = base_ring.precision() digits = sage.arith.all.integer_ceil((2*precision - 2)/7.0) self.__singular = singular.ring("(complex,%d,0,I)"%digits, _vars, order=order, check=False) - elif is_RealDoubleField(base_ring): + elif isinstance(base_ring, sage.rings.abc.RealDoubleField): # singular converts to bits from base_10 in mpr_complex.cc by: # size_t bits = 1 + (size_t) ((float)digits * 3.5); self.__singular = singular.ring("(real,15,0)", _vars, order=order, check=False) - elif is_ComplexDoubleField(base_ring): + elif isinstance(base_ring, sage.rings.abc.ComplexDoubleField): # singular converts to bits from base_10 in mpr_complex.cc by: # size_t bits = 1 + (size_t) ((float)digits * 3.5); self.__singular = singular.ring("(complex,15,0,I)", _vars, order=order, check=False) @@ -389,10 +389,10 @@ def can_convert_to_singular(R): or sage.rings.finite_rings.finite_field_constructor.is_FiniteField(base_ring) or is_RationalField(base_ring) or is_IntegerModRing(base_ring) - or is_RealField(base_ring) - or is_ComplexField(base_ring) - or is_RealDoubleField(base_ring) - or is_ComplexDoubleField(base_ring)): + or isinstance(base_ring, sage.rings.abc.RealField) + or isinstance(base_ring, sage.rings.abc.ComplexField) + or isinstance(base_ring, sage.rings.abc.RealDoubleField) + or isinstance(base_ring, sage.rings.abc.ComplexDoubleField)): return True elif base_ring.is_prime_field(): return base_ring.characteristic() <= 2147483647 diff --git a/src/sage/rings/real_double.pyx b/src/sage/rings/real_double.pyx index a967e8f9e7e..750adf89b72 100644 --- a/src/sage/rings/real_double.pyx +++ b/src/sage/rings/real_double.pyx @@ -73,16 +73,16 @@ from sage.arith.constants cimport * cimport gmpy2 -def is_RealDoubleField(x): +def isinstance(x, sage.rings.abc.RealDoubleField): """ Returns ``True`` if ``x`` is the field of real double precision numbers. EXAMPLES:: sage: from sage.rings.real_double import is_RealDoubleField - sage: is_RealDoubleField(RDF) + sage: isinstance(RDF, sage.rings.abc.RealDoubleField) True - sage: is_RealDoubleField(RealField(53)) + sage: isinstance(RealField(53, sage.rings.abc.RealDoubleField)) False """ return isinstance(x, RealDoubleField_class) diff --git a/src/sage/rings/real_mpfr.pyx b/src/sage/rings/real_mpfr.pyx index 69568a5fb9d..cb9851fc8f9 100644 --- a/src/sage/rings/real_mpfr.pyx +++ b/src/sage/rings/real_mpfr.pyx @@ -5896,15 +5896,15 @@ def create_RealNumber(s, int base=10, int pad=0, rnd="RNDN", int min_prec=53): return RealLiteral(R, s, base) -def is_RealField(x): +def isinstance(x, sage.rings.abc.RealField): """ Returns ``True`` if ``x`` is technically of a Python real field type. EXAMPLES:: - sage: sage.rings.real_mpfr.is_RealField(RR) + sage: sage.rings.real_mpfr.isinstance(RR, sage.rings.abc.RealField) True - sage: sage.rings.real_mpfr.is_RealField(CC) + sage: sage.rings.real_mpfr.isinstance(CC, sage.rings.abc.RealField) False """ return isinstance(x, RealField_class) diff --git a/src/sage/schemes/elliptic_curves/ell_field.py b/src/sage/schemes/elliptic_curves/ell_field.py index bd7a8027b0c..55bd2790b08 100644 --- a/src/sage/schemes/elliptic_curves/ell_field.py +++ b/src/sage/schemes/elliptic_curves/ell_field.py @@ -13,8 +13,8 @@ #***************************************************************************** import sage.rings.all as rings -from sage.rings.complex_mpfr import is_ComplexField -from sage.rings.real_mpfr import is_RealField +import sage.rings.abc +import sage.rings.abc from sage.schemes.elliptic_curves.ell_point import EllipticCurvePoint_field from sage.schemes.curves.projective_curve import ProjectivePlaneCurve_field @@ -1069,9 +1069,9 @@ def isogenies_prime_degree(self, l=None, max_l=31): ValueError: 4 is not prime. """ F = self.base_ring() - if is_RealField(F): + if isinstance(F, sage.rings.abc.RealField): raise NotImplementedError("This code could be implemented for general real fields, but has not been yet.") - if is_ComplexField(F): + if isinstance(F, sage.rings.abc.ComplexField): raise NotImplementedError("This code could be implemented for general complex fields, but has not been yet.") if F is rings.QQbar: raise NotImplementedError("This code could be implemented for QQbar, but has not been yet.") diff --git a/src/sage/schemes/elliptic_curves/ell_number_field.py b/src/sage/schemes/elliptic_curves/ell_number_field.py index 821d2e96639..322b24f9540 100644 --- a/src/sage/schemes/elliptic_curves/ell_number_field.py +++ b/src/sage/schemes/elliptic_curves/ell_number_field.py @@ -2616,7 +2616,7 @@ def real_components(self, embedding): try: if not embedding.domain() is self.base_field(): raise ValueError("invalid embedding specified: should have domain {}".format(self.base_field())) - if not is_RealField(embedding.codomain()): + if not isinstance(embedding.codomain(, sage.rings.abc.RealField)): raise ValueError("invalid embedding specified: should be real") except AttributeError: raise ValueError("invalid embedding") diff --git a/src/sage/schemes/elliptic_curves/ell_point.py b/src/sage/schemes/elliptic_curves/ell_point.py index 7edafee118a..068ea589b3d 100644 --- a/src/sage/schemes/elliptic_curves/ell_point.py +++ b/src/sage/schemes/elliptic_curves/ell_point.py @@ -125,7 +125,7 @@ from sage.rings.padics.precision_error import PrecisionError import sage.rings.all as rings -from sage.rings.real_mpfr import is_RealField +import sage.rings.abc from sage.rings.integer import Integer from sage.rings.integer_ring import ZZ import sage.groups.generic as generic @@ -2219,7 +2219,7 @@ def is_on_identity_component(self, embedding=None): e = embedding # It is also trivially true if we have a complex embedding if e is not None: - if not is_RealField(e.codomain()): + if not isinstance(e.codomain(, sage.rings.abc.RealField)): return True # find a suitable embedding if none was supplied: @@ -2232,7 +2232,7 @@ def is_on_identity_component(self, embedding=None): e = K.embeddings(rings.ComplexField())[0] # If there is only one component, the result is True: - if not is_RealField(e.codomain()): # complex embedding + if not isinstance(e.codomain(, sage.rings.abc.RealField)): # complex embedding return True if e(E.discriminant()) < 0: # only one component return True @@ -3237,7 +3237,7 @@ def elliptic_logarithm(self, embedding=None, precision=100, L = E.period_lattice(emb) - if algorithm == 'sage' or not is_RealField(emb.codomain): + if algorithm == 'sage' or not isinstance(emb.codomain, sage.rings.abc.RealField): return L.elliptic_logarithm(self, precision) if algorithm != 'pari': diff --git a/src/sage/schemes/elliptic_curves/period_lattice.py b/src/sage/schemes/elliptic_curves/period_lattice.py index fe1899f647c..974f560c4db 100644 --- a/src/sage/schemes/elliptic_curves/period_lattice.py +++ b/src/sage/schemes/elliptic_curves/period_lattice.py @@ -100,7 +100,7 @@ from sage.modules.free_module import FreeModule_generic_pid from sage.rings.all import ZZ, QQ, RealField, ComplexField, QQbar, AA -from sage.rings.real_mpfr import is_RealField +import sage.rings.abc from sage.rings.complex_mpfr import ComplexNumber, is_ComplexField from sage.rings.real_mpfr import RealNumber as RealNumber from sage.rings.number_field.number_field import refine_embedding @@ -1169,11 +1169,11 @@ def coordinates(self, z, rounding=None): (12, 23) """ C = z.parent() - if is_RealField(C): + if isinstance(C, sage.rings.abc.RealField): C = ComplexField(C.precision()) z = C(z) else: - if is_ComplexField(C): + if isinstance(C, sage.rings.abc.ComplexField): pass else: try: @@ -1233,10 +1233,10 @@ def reduce(self, z): 0.958696500380444 """ C = z.parent() - if is_RealField(C): + if isinstance(C, sage.rings.abc.RealField): C = ComplexField(C.precision()) z = C(z) - elif is_ComplexField(C): + elif isinstance(C, sage.rings.abc.ComplexField): pass else: try: @@ -1789,12 +1789,12 @@ def elliptic_exponential(self, z, to_curve=True): """ C = z.parent() z_is_real = False - if is_RealField(C): + if isinstance(C, sage.rings.abc.RealField): z_is_real = True C = ComplexField(C.precision()) z = C(z) else: - if is_ComplexField(C): + if isinstance(C, sage.rings.abc.ComplexField): z_is_real = z.is_real() else: try: diff --git a/src/sage/schemes/plane_conics/con_field.py b/src/sage/schemes/plane_conics/con_field.py index 04ee419f880..ad2273cc99d 100644 --- a/src/sage/schemes/plane_conics/con_field.py +++ b/src/sage/schemes/plane_conics/con_field.py @@ -26,8 +26,8 @@ from sage.rings.all import PolynomialRing -from sage.rings.complex_mpfr import is_ComplexField -from sage.rings.real_mpfr import is_RealField +import sage.rings.abc +import sage.rings.abc from sage.modules.free_module_element import vector from sage.structure.sequence import Sequence @@ -517,7 +517,7 @@ def has_rational_point(self, point = False, if algorithm != 'default': raise ValueError("Unknown algorithm: %s" % algorithm) - if is_ComplexField(B): + if isinstance(B, sage.rings.abc.ComplexField): if point: [_,_,_,d,e,f] = self._coefficients if d == 0: @@ -525,7 +525,7 @@ def has_rational_point(self, point = False, return True, self.point([0, ((e**2-4*d*f).sqrt()-e)/(2*d), 1], check = False) return True - if is_RealField(B): + if isinstance(B, sage.rings.abc.RealField): D, T = self.diagonal_matrix() [a, b, c] = [D[0,0], D[1,1], D[2,2]] if a == 0: diff --git a/src/sage/schemes/plane_conics/con_rational_field.py b/src/sage/schemes/plane_conics/con_rational_field.py index e8b1d824cbd..4ff7cc39a61 100644 --- a/src/sage/schemes/plane_conics/con_rational_field.py +++ b/src/sage/schemes/plane_conics/con_rational_field.py @@ -26,7 +26,7 @@ from sage.rings.all import (PolynomialRing, ZZ, QQ) -from sage.rings.real_mpfr import is_RealField +import sage.rings.abc from sage.structure.sequence import Sequence from sage.schemes.projective.projective_space import ProjectiveSpace @@ -230,11 +230,11 @@ def is_locally_solvable(self, p) -> bool: return True a = -abc[0] / abc[2] b = -abc[1] / abc[2] - if is_RealField(p) or isinstance(p, InfinityElement): + if isinstance(p, sage.rings.abc.RealField) or isinstance(p, InfinityElement): p = -1 elif isinstance(p, Map) and p.category_for().is_subcategory(Rings()): # p is a morphism of Rings - if p.domain() is QQ and is_RealField(p.codomain()): + if p.domain() is QQ and isinstance(p.codomain(, sage.rings.abc.RealField)): p = -1 else: raise TypeError("p (=%s) needs to be a prime of base field " diff --git a/src/sage/symbolic/expression.pyx b/src/sage/symbolic/expression.pyx index de4720f90a7..beab2ce78ca 100644 --- a/src/sage/symbolic/expression.pyx +++ b/src/sage/symbolic/expression.pyx @@ -395,7 +395,7 @@ from sage.misc.latex import latex_variable_name from sage.rings.infinity import AnInfinity, infinity, minus_infinity, unsigned_infinity from sage.rings.integer_ring import ZZ from sage.rings.real_mpfr import RR -from sage.rings.complex_mpfr import is_ComplexField +import sage.rings.abc from sage.misc.decorators import rename_keyword from sage.structure.dynamic_class import dynamic_class from sage.structure.element cimport CommutativeRingElement @@ -13830,7 +13830,7 @@ cdef unsigned sage_domain_to_ginac_domain(object domain) except? 3474701533: return domain_real elif domain == 'positive': return domain_positive - elif is_ComplexField(domain) or domain == 'complex': + elif isinstance(domain, sage.rings.abc.ComplexField) or domain == 'complex': return domain_complex elif domain is ZZ or domain == 'integer': return domain_integer @@ -13844,7 +13844,7 @@ cdef void send_sage_domain_to_maxima(Expression v, object domain) except +: assume(v, 'real') elif domain == 'positive': assume(v>0) - elif is_ComplexField(domain) or domain == 'complex': + elif isinstance(domain, sage.rings.abc.ComplexField) or domain == 'complex': assume(v, 'complex') elif domain is ZZ or domain == 'integer': assume(v, 'integer') From 28e328a995088c574c1e1ab3fc31f613d273b725 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 2 Oct 2021 11:05:20 -0700 Subject: [PATCH 199/359] Remove repeated imports of sage.rings.abc --- src/sage/functions/orthogonal_polys.py | 1 - src/sage/modules/free_module.py | 4 ++-- src/sage/rings/polynomial/multi_polynomial_libsingular.pyx | 1 - src/sage/rings/polynomial/polynomial_singular_interface.py | 3 --- src/sage/schemes/elliptic_curves/ell_field.py | 1 - src/sage/schemes/plane_conics/con_field.py | 1 - 6 files changed, 2 insertions(+), 9 deletions(-) diff --git a/src/sage/functions/orthogonal_polys.py b/src/sage/functions/orthogonal_polys.py index c879cd6c8fe..67c0381b541 100644 --- a/src/sage/functions/orthogonal_polys.py +++ b/src/sage/functions/orthogonal_polys.py @@ -305,7 +305,6 @@ from sage.rings.all import ZZ, QQ, RR, CC from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing import sage.rings.abc -import sage.rings.abc from sage.symbolic.function import BuiltinFunction, GinacFunction from sage.symbolic.expression import Expression diff --git a/src/sage/modules/free_module.py b/src/sage/modules/free_module.py index 6288e77cf76..57c10114174 100644 --- a/src/sage/modules/free_module.py +++ b/src/sage/modules/free_module.py @@ -7443,9 +7443,9 @@ def element_class(R, is_sparse): return Vector_modn_dense else: return free_module_element.FreeModuleElement_generic_dense - elif sage.rings.real_double.isinstance(R, sage.rings.abc.RealDoubleField) and not is_sparse: + elif sage.rings.real_double.is_RealDoubleField(R) and not is_sparse: return sage.modules.vector_real_double_dense.Vector_real_double_dense - elif sage.rings.complex_double.isinstance(R, sage.rings.abc.ComplexDoubleField) and not is_sparse: + elif sage.rings.complex_double.is_ComplexDoubleField(R) and not is_sparse: return sage.modules.vector_complex_double_dense.Vector_complex_double_dense elif sage.symbolic.ring.is_SymbolicExpressionRing(R) and not is_sparse: import sage.modules.vector_symbolic_dense diff --git a/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx b/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx index f32e42d83f3..03f8015f7ea 100644 --- a/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx +++ b/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx @@ -225,7 +225,6 @@ from sage.rings.finite_rings.finite_field_prime_modn import FiniteField_prime_mo from sage.rings.rational cimport Rational from sage.rings.rational_field import QQ import sage.rings.abc -import sage.rings.abc from sage.rings.integer_ring import is_IntegerRing, ZZ from sage.rings.integer cimport Integer from sage.rings.integer import GCD_list diff --git a/src/sage/rings/polynomial/polynomial_singular_interface.py b/src/sage/rings/polynomial/polynomial_singular_interface.py index 256bb0997cc..0a472405790 100644 --- a/src/sage/rings/polynomial/polynomial_singular_interface.py +++ b/src/sage/rings/polynomial/polynomial_singular_interface.py @@ -42,10 +42,7 @@ from sage.interfaces.all import singular import sage.rings.abc -import sage.rings.abc -import sage.rings.abc from sage.rings.finite_rings.integer_mod_ring import is_IntegerModRing -import sage.rings.abc from sage.rings.rational_field import is_RationalField from sage.rings.function_field.function_field import RationalFunctionField from sage.rings.finite_rings.finite_field_base import is_FiniteField diff --git a/src/sage/schemes/elliptic_curves/ell_field.py b/src/sage/schemes/elliptic_curves/ell_field.py index 55bd2790b08..d972c4e1fc9 100644 --- a/src/sage/schemes/elliptic_curves/ell_field.py +++ b/src/sage/schemes/elliptic_curves/ell_field.py @@ -14,7 +14,6 @@ import sage.rings.all as rings import sage.rings.abc -import sage.rings.abc from sage.schemes.elliptic_curves.ell_point import EllipticCurvePoint_field from sage.schemes.curves.projective_curve import ProjectivePlaneCurve_field diff --git a/src/sage/schemes/plane_conics/con_field.py b/src/sage/schemes/plane_conics/con_field.py index ad2273cc99d..0d5eb412034 100644 --- a/src/sage/schemes/plane_conics/con_field.py +++ b/src/sage/schemes/plane_conics/con_field.py @@ -26,7 +26,6 @@ from sage.rings.all import PolynomialRing -import sage.rings.abc import sage.rings.abc from sage.modules.free_module_element import vector From 45cc21ad1afb7c06cc2a61a65adeeb9b2e8664f9 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 2 Oct 2021 11:07:17 -0700 Subject: [PATCH 200/359] is_Real[Double]Field, is_Complex[Double]Field: Undo automatic edits, deprecate --- src/sage/rings/complex_double.pyx | 12 +++++++++--- src/sage/rings/complex_mpfr.pyx | 11 +++++++++-- src/sage/rings/real_double.pyx | 12 +++++++++--- src/sage/rings/real_mpfr.pyx | 12 +++++++++--- 4 files changed, 36 insertions(+), 11 deletions(-) diff --git a/src/sage/rings/complex_double.pyx b/src/sage/rings/complex_double.pyx index 7621cc043c2..a1a2ae29a29 100644 --- a/src/sage/rings/complex_double.pyx +++ b/src/sage/rings/complex_double.pyx @@ -111,18 +111,24 @@ from sage.structure.richcmp cimport rich_to_bool cimport gmpy2 gmpy2.import_gmpy2() -def isinstance(x, sage.rings.abc.ComplexDoubleField): + +def is_ComplexDoubleField(x): """ Return ``True`` if ``x`` is the complex double field. + This function is deprecated. Use :func:`isinstance` with + :class:`~sage.rings.abc.ComplexDoubleField` instead. + EXAMPLES:: sage: from sage.rings.complex_double import is_ComplexDoubleField - sage: isinstance(CDF, sage.rings.abc.ComplexDoubleField) + sage: is_ComplexDoubleField(CDF) True - sage: isinstance(ComplexField(53, sage.rings.abc.ComplexDoubleField)) + sage: is_ComplexDoubleField(ComplexField(53)) False """ + from sage.misc.superseded import deprecation + deprecation(32610, 'is_ComplexDoubleField is deprecated; use isinstance(..., sage.rings.abc.ComplexDoubleField) instead') return isinstance(x, ComplexDoubleField_class) diff --git a/src/sage/rings/complex_mpfr.pyx b/src/sage/rings/complex_mpfr.pyx index d3d32b69de5..e3d73b4a268 100644 --- a/src/sage/rings/complex_mpfr.pyx +++ b/src/sage/rings/complex_mpfr.pyx @@ -157,10 +157,14 @@ def is_ComplexNumber(x): """ return isinstance(x, ComplexNumber) -def isinstance(x, sage.rings.abc.ComplexField): + +def is_ComplexField(x): """ Check if ``x`` is a :class:`complex field `. + This function is deprecated. Use :func:`isinstance` with + :class:`~sage.rings.abc.ComplexField` instead. + EXAMPLES:: sage: from sage.rings.complex_mpfr import is_ComplexField as is_CF @@ -171,8 +175,11 @@ def isinstance(x, sage.rings.abc.ComplexField): sage: is_CF(CC) True """ + from sage.misc.superseded import deprecation + deprecation(32610, 'is_ComplexField is deprecated; use isinstance(..., sage.rings.abc.ComplexField) instead') return isinstance(x, ComplexField_class) + cache = {} def ComplexField(prec=53, names=None): """ @@ -543,7 +550,7 @@ class ComplexField_class(ring.Field): RR = self._real_field() if RR.has_coerce_map_from(S): return RRtoCC(RR, self) * RR._internal_coerce_map_from(S) - if isinstance(S, sage.rings.abc.ComplexField): + if isinstance(S, ComplexField_class): if self._prec <= S._prec: return self._generic_coerce_map(S) else: diff --git a/src/sage/rings/real_double.pyx b/src/sage/rings/real_double.pyx index 750adf89b72..5be63115735 100644 --- a/src/sage/rings/real_double.pyx +++ b/src/sage/rings/real_double.pyx @@ -73,20 +73,26 @@ from sage.arith.constants cimport * cimport gmpy2 -def isinstance(x, sage.rings.abc.RealDoubleField): +def is_RealDoubleField(x): """ Returns ``True`` if ``x`` is the field of real double precision numbers. + This function is deprecated. Use :func:`isinstance` with + :class:`~sage.rings.abc.RealDoubleField` instead. + EXAMPLES:: sage: from sage.rings.real_double import is_RealDoubleField - sage: isinstance(RDF, sage.rings.abc.RealDoubleField) + sage: is_RealDoubleField(RDF) True - sage: isinstance(RealField(53, sage.rings.abc.RealDoubleField)) + sage: is_RealDoubleField(RealField(53)) False """ + from sage.misc.superseded import deprecation + deprecation(32610, 'is_RealDoubleField is deprecated; use isinstance(..., sage.rings.abc.RealDoubleField) instead') return isinstance(x, RealDoubleField_class) + cdef class RealDoubleField_class(Field): """ An approximation to the field of real numbers using double diff --git a/src/sage/rings/real_mpfr.pyx b/src/sage/rings/real_mpfr.pyx index cb9851fc8f9..f0d2eb5919b 100644 --- a/src/sage/rings/real_mpfr.pyx +++ b/src/sage/rings/real_mpfr.pyx @@ -5896,19 +5896,25 @@ def create_RealNumber(s, int base=10, int pad=0, rnd="RNDN", int min_prec=53): return RealLiteral(R, s, base) -def isinstance(x, sage.rings.abc.RealField): +def is_RealField(x): """ Returns ``True`` if ``x`` is technically of a Python real field type. + This function is deprecated. Use :func:`isinstance` with + :class:`~sage.rings.abc.RealField` instead. + EXAMPLES:: - sage: sage.rings.real_mpfr.isinstance(RR, sage.rings.abc.RealField) + sage: sage.rings.real_mpfr.is_RealField(RR) True - sage: sage.rings.real_mpfr.isinstance(CC, sage.rings.abc.RealField) + sage: sage.rings.real_mpfr.is_RealField(CC) False """ + from sage.misc.superseded import deprecation + deprecation(32610, 'is_RealField is deprecated; use isinstance(..., sage.rings.abc.RealField) instead') return isinstance(x, RealField_class) + def is_RealNumber(x): """ Return ``True`` if ``x`` is of type :class:`RealNumber`, meaning that it From e003603ebb665c064a459f55b9ad4731d9900424 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 2 Oct 2021 11:08:33 -0700 Subject: [PATCH 201/359] sage.dynamics: Fix up replacement of is_{Real,Complex}[Double]Field --- src/sage/dynamics/arithmetic_dynamics/projective_ds.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py index e5f2b9225cf..3c56fd3885b 100644 --- a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py +++ b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py @@ -88,8 +88,8 @@ class initialization directly. from sage.rings.qqbar import QQbar, number_field_elements_from_algebraics from sage.rings.quotient_ring import QuotientRing_generic from sage.rings.rational_field import QQ -from sage.rings.real_double import RDF -from sage.rings.real_mpfr import (RealField, is_RealField) +import sage.rings.abc +from sage.rings.real_mpfr import RealField from sage.schemes.generic.morphism import SchemeMorphism_polynomial from sage.schemes.projective.projective_subscheme import AlgebraicScheme_subscheme_projective from sage.schemes.projective.projective_morphism import ( @@ -2062,10 +2062,10 @@ def canonical_height(self, P, **kwds): # Archimedean local heights # :: WARNING: If places is fed the default Sage precision of 53 bits, - # it uses Real or Complex Double Field in place of RealField(prec) or ComplexField(prec) - # the function is_RealField does not identify RDF as real, so we test for that ourselves. + # it uses Real or Complex Double Field in place of RealField(prec) or ComplexField(prec). + # RDF is an instance of a separate class. for v in emb: - if isinstance(v.codomain(, sage.rings.abc.RealField)) or v.codomain() is RDF: + if isinstance(v.codomain(), (sage.rings.abc.RealField, sage.rings.abc.RealDoubleField)): dv = R.one() else: dv = R(2) From 4adc553551b756d2cb177055359a55c6bd4691e6 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 2 Oct 2021 11:08:50 -0700 Subject: [PATCH 202/359] sage.functions: Fix up replacement of is_{Real,Complex}[Double]Field --- src/sage/functions/orthogonal_polys.py | 8 ++++---- src/sage/functions/special.py | 4 +--- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/sage/functions/orthogonal_polys.py b/src/sage/functions/orthogonal_polys.py index 67c0381b541..0e965c57da6 100644 --- a/src/sage/functions/orthogonal_polys.py +++ b/src/sage/functions/orthogonal_polys.py @@ -671,7 +671,7 @@ def _evalf_(self, n, x, **kwds): except KeyError: real_parent = parent(x) - if not isinstance(real_parent, sage.rings.abc.RealField) and not isinstance(real_parent, sage.rings.abc.ComplexField): + if not isinstance(real_parent, (sage.rings.abc.RealField, sage.rings.abc.ComplexField)): # parent is not a real or complex field: figure out a good parent if x in RR: x = RR(x) @@ -680,7 +680,7 @@ def _evalf_(self, n, x, **kwds): x = CC(x) real_parent = CC - if not isinstance(real_parent, sage.rings.abc.RealField) and not isinstance(real_parent, sage.rings.abc.ComplexField): + if not isinstance(real_parent, (sage.rings.abc.RealField, sage.rings.abc.ComplexField)): raise TypeError("cannot evaluate chebyshev_T with parent {}".format(real_parent)) from sage.libs.mpmath.all import call as mpcall @@ -1030,7 +1030,7 @@ def _evalf_(self, n, x, **kwds): except KeyError: real_parent = parent(x) - if not isinstance(real_parent, sage.rings.abc.RealField) and not isinstance(real_parent, sage.rings.abc.ComplexField): + if not isinstance(real_parent, (sage.rings.abc.RealField, sage.rings.abc.ComplexField)): # parent is not a real or complex field: figure out a good parent if x in RR: x = RR(x) @@ -1039,7 +1039,7 @@ def _evalf_(self, n, x, **kwds): x = CC(x) real_parent = CC - if not isinstance(real_parent, sage.rings.abc.RealField) and not isinstance(real_parent, sage.rings.abc.ComplexField): + if not isinstance(real_parent, (sage.rings.abc.RealField, sage.rings.abc.ComplexField)): raise TypeError("cannot evaluate chebyshev_U with parent {}".format(real_parent)) from sage.libs.mpmath.all import call as mpcall diff --git a/src/sage/functions/special.py b/src/sage/functions/special.py index c409631f392..bc43c362141 100644 --- a/src/sage/functions/special.py +++ b/src/sage/functions/special.py @@ -159,7 +159,6 @@ # **************************************************************************** from sage.rings.integer import Integer -from sage.rings.complex_mpfr import ComplexField from sage.misc.latex import latex from sage.rings.all import ZZ from sage.symbolic.constants import pi @@ -362,10 +361,9 @@ def elliptic_j(z, prec=53): sage: (-elliptic_j(tau, 100).real().round())^(1/3) 640320 """ - CC = z.parent() - from sage.rings.complex_mpfr import is_ComplexField if not isinstance(CC, sage.rings.abc.ComplexField): + from sage.rings.complex_mpfr import ComplexField CC = ComplexField(prec) try: z = CC(z) From 5b988c69369a02eea230d61303742195f3ba4a36 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 2 Oct 2021 11:09:11 -0700 Subject: [PATCH 203/359] sage.schemes: Fix up replacement of is_{Real,Complex}[Double]Field --- src/sage/schemes/elliptic_curves/ell_number_field.py | 3 +-- src/sage/schemes/elliptic_curves/ell_point.py | 4 ++-- src/sage/schemes/elliptic_curves/period_lattice.py | 2 +- src/sage/schemes/plane_conics/con_rational_field.py | 2 +- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/sage/schemes/elliptic_curves/ell_number_field.py b/src/sage/schemes/elliptic_curves/ell_number_field.py index 322b24f9540..f0bcda573df 100644 --- a/src/sage/schemes/elliptic_curves/ell_number_field.py +++ b/src/sage/schemes/elliptic_curves/ell_number_field.py @@ -2612,11 +2612,10 @@ def real_components(self, embedding): ... ValueError: invalid embedding specified: should have domain ... """ - from sage.rings.real_mpfr import is_RealField try: if not embedding.domain() is self.base_field(): raise ValueError("invalid embedding specified: should have domain {}".format(self.base_field())) - if not isinstance(embedding.codomain(, sage.rings.abc.RealField)): + if not isinstance(embedding.codomain(), sage.rings.abc.RealField): raise ValueError("invalid embedding specified: should be real") except AttributeError: raise ValueError("invalid embedding") diff --git a/src/sage/schemes/elliptic_curves/ell_point.py b/src/sage/schemes/elliptic_curves/ell_point.py index 068ea589b3d..63b027eae62 100644 --- a/src/sage/schemes/elliptic_curves/ell_point.py +++ b/src/sage/schemes/elliptic_curves/ell_point.py @@ -2219,7 +2219,7 @@ def is_on_identity_component(self, embedding=None): e = embedding # It is also trivially true if we have a complex embedding if e is not None: - if not isinstance(e.codomain(, sage.rings.abc.RealField)): + if not isinstance(e.codomain(), sage.rings.abc.RealField): return True # find a suitable embedding if none was supplied: @@ -2232,7 +2232,7 @@ def is_on_identity_component(self, embedding=None): e = K.embeddings(rings.ComplexField())[0] # If there is only one component, the result is True: - if not isinstance(e.codomain(, sage.rings.abc.RealField)): # complex embedding + if not isinstance(e.codomain(), sage.rings.abc.RealField): # complex embedding return True if e(E.discriminant()) < 0: # only one component return True diff --git a/src/sage/schemes/elliptic_curves/period_lattice.py b/src/sage/schemes/elliptic_curves/period_lattice.py index 974f560c4db..01a96c37627 100644 --- a/src/sage/schemes/elliptic_curves/period_lattice.py +++ b/src/sage/schemes/elliptic_curves/period_lattice.py @@ -101,7 +101,7 @@ from sage.modules.free_module import FreeModule_generic_pid from sage.rings.all import ZZ, QQ, RealField, ComplexField, QQbar, AA import sage.rings.abc -from sage.rings.complex_mpfr import ComplexNumber, is_ComplexField +from sage.rings.complex_mpfr import ComplexNumber from sage.rings.real_mpfr import RealNumber as RealNumber from sage.rings.number_field.number_field import refine_embedding from sage.rings.infinity import Infinity diff --git a/src/sage/schemes/plane_conics/con_rational_field.py b/src/sage/schemes/plane_conics/con_rational_field.py index 4ff7cc39a61..d24bd59898c 100644 --- a/src/sage/schemes/plane_conics/con_rational_field.py +++ b/src/sage/schemes/plane_conics/con_rational_field.py @@ -234,7 +234,7 @@ def is_locally_solvable(self, p) -> bool: p = -1 elif isinstance(p, Map) and p.category_for().is_subcategory(Rings()): # p is a morphism of Rings - if p.domain() is QQ and isinstance(p.codomain(, sage.rings.abc.RealField)): + if p.domain() is QQ and isinstance(p.codomain(), sage.rings.abc.RealField): p = -1 else: raise TypeError("p (=%s) needs to be a prime of base field " From 402dbec95818340a31e0b1d1790fc5ba31690480 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 2 Oct 2021 11:10:11 -0700 Subject: [PATCH 204/359] sage.rings.number_field: Fix up replacement of is_{Real,Complex}[Double]Field --- src/sage/rings/number_field/number_field.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/sage/rings/number_field/number_field.py b/src/sage/rings/number_field/number_field.py index bc626635105..863fbd8aad8 100644 --- a/src/sage/rings/number_field/number_field.py +++ b/src/sage/rings/number_field/number_field.py @@ -9945,16 +9945,14 @@ def hilbert_symbol(self, a, b, P = None): if P.domain() is not self: raise ValueError("Domain of P (=%s) should be self (=%s) in self.hilbert_symbol" % (P, self)) codom = P.codomain() - from sage.rings.complex_mpfr import is_ComplexField from sage.rings.complex_interval_field import is_ComplexIntervalField - from sage.rings.real_mpfr import is_RealField - from sage.rings.all import (AA, CDF, QQbar, RDF) - if isinstance(codom, sage.rings.abc.ComplexField) or is_ComplexIntervalField(codom) or \ - codom is CDF or codom is QQbar: + from sage.rings.all import (AA, QQbar) + if isinstance(codom, (sage.rings.abc.ComplexField, sage.rings.abc.ComplexDoubleField) or is_ComplexIntervalField(codom) or \ + codom is QQbar: if P(self.gen()).imag() == 0: raise ValueError("Possibly real place (=%s) given as complex embedding in hilbert_symbol. Is it real or complex?" % P) return 1 - if isinstance(codom, sage.rings.abc.RealField) or codom is RDF or codom is AA: + if isinstance(codom, (sage.rings.abc.RealField, sage.rings.abc.RealDoubleField) or codom is AA: if P(a) > 0 or P(b) > 0: return 1 return -1 @@ -12317,7 +12315,7 @@ def refine_embedding(e, prec=None): return e # We first compute all the embeddings at the new precision: - if sage.rings.real_mpfr.isinstance(RC, sage.rings.abc.RealField) or RC in (RDF, RLF): + if isinstance(RC, (sage.rings.abc.RealField, sage.rings.abc.RealDoubleField)) or RC == RLF: if prec == Infinity: elist = K.embeddings(sage.rings.qqbar.AA) else: From e82709c128895eb1d9c0d127ee878c2830ffaef3 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 2 Oct 2021 11:10:24 -0700 Subject: [PATCH 205/359] sage.rings.polynomial: Fix up replacement of is_{Real,Complex}[Double]Field --- .../rings/polynomial/polynomial_element.pyx | 36 ++++++++----------- .../polynomial_singular_interface.py | 6 ++-- 2 files changed, 17 insertions(+), 25 deletions(-) diff --git a/src/sage/rings/polynomial/polynomial_element.pyx b/src/sage/rings/polynomial/polynomial_element.pyx index 70f026179a4..add33c68590 100644 --- a/src/sage/rings/polynomial/polynomial_element.pyx +++ b/src/sage/rings/polynomial/polynomial_element.pyx @@ -51,7 +51,7 @@ TESTS:: # https://www.gnu.org/licenses/ # **************************************************************************** -cdef is_FractionField, is_RealField, is_ComplexField +cdef is_FractionField cdef ZZ, QQ, RR, CC, RDF, CDF cimport cython @@ -64,6 +64,7 @@ import re from sage.cpython.wrapperdescr cimport wrapperdescr_fastcall import sage.rings.rational import sage.rings.integer +import sage.rings.abc from . import polynomial_ring import sage.rings.integer_ring import sage.rings.rational_field @@ -84,13 +85,13 @@ from sage.structure.richcmp cimport (richcmp, richcmp_item, from sage.interfaces.singular import singular as singular_default, is_SingularElement from sage.libs.all import pari, pari_gen, PariError -from sage.rings.real_mpfr import RealField, is_RealField, RR +from sage.rings.real_mpfr import RealField, RR -from sage.rings.complex_mpfr import is_ComplexField, ComplexField +from sage.rings.complex_mpfr import ComplexField CC = ComplexField() -from sage.rings.real_double import is_RealDoubleField, RDF -from sage.rings.complex_double import is_ComplexDoubleField, CDF +from sage.rings.real_double import RDF +from sage.rings.complex_double import CDF from sage.rings.real_mpfi import is_RealIntervalField from sage.structure.coerce cimport coercion_model @@ -7912,18 +7913,12 @@ cdef class Polynomial(CommutativeAlgebraElement): late_import() - input_fp = (isinstance(K, sage.rings.abc.RealField) - or isinstance(K, sage.rings.abc.ComplexField) - or isinstance(K, sage.rings.abc.RealDoubleField) - or isinstance(K, sage.rings.abc.ComplexDoubleField)) - output_fp = (isinstance(L, sage.rings.abc.RealField) - or isinstance(L, sage.rings.abc.ComplexField) - or isinstance(L, sage.rings.abc.RealDoubleField) - or isinstance(L, sage.rings.abc.ComplexDoubleField)) - input_complex = (isinstance(K, sage.rings.abc.ComplexField) - or isinstance(K, sage.rings.abc.ComplexDoubleField)) - output_complex = (isinstance(L, sage.rings.abc.ComplexField) - or isinstance(L, sage.rings.abc.ComplexDoubleField)) + input_fp = isinstance(K, (sage.rings.abc.RealField, sage.rings.abc.ComplexField, + sage.rings.abc.RealDoubleField, sage.rings.abc.ComplexDoubleField)) + output_fp = isinstance(L, (sage.rings.abc.RealField, sage.rings.abc.ComplexField, + sage.rings.abc.RealDoubleField, sage.rings.abc.ComplexDoubleField)) + input_complex = isinstance(K, (sage.rings.abc.ComplexField, sage.rings.abc.ComplexDoubleField)) + output_complex = isinstance(L, (sage.rings.abc.ComplexField, sage.rings.abc.ComplexDoubleField)) input_gaussian = (isinstance(K, NumberField_quadratic) and list(K.polynomial()) == [1, 0, 1]) @@ -7943,8 +7938,7 @@ cdef class Polynomial(CommutativeAlgebraElement): # We should support GSL, too. We could also support PARI's # old Newton-iteration algorithm. - input_arbprec = (isinstance(K, sage.rings.abc.RealField) or - isinstance(K, sage.rings.abc.ComplexField)) + input_arbprec = isinstance(K, (sage.rings.abc.RealField, sage.rings.abc.ComplexField)) if algorithm == 'numpy' or algorithm == 'either': if K.prec() > 53 and L.prec() > 53: @@ -8250,7 +8244,7 @@ cdef class Polynomial(CommutativeAlgebraElement): True """ K = self.base_ring() - if isinstance(K, sage.rings.abc.RealField) or isinstance(K, sage.rings.abc.RealDoubleField): + if isinstance(K, (sage.rings.abc.RealField, sage.rings.abc.RealDoubleField)): return self.roots(multiplicities=False) return self.roots(ring=RR, multiplicities=False) @@ -8296,7 +8290,7 @@ cdef class Polynomial(CommutativeAlgebraElement): return self.roots(ring=ComplexField(K.prec()), multiplicities=False) if isinstance(K, sage.rings.abc.RealDoubleField): return self.roots(ring=CDF, multiplicities=False) - if isinstance(K, sage.rings.abc.ComplexField) or isinstance(K, sage.rings.abc.ComplexDoubleField): + if isinstance(K, (sage.rings.abc.ComplexField, sage.rings.abc.ComplexDoubleField)): return self.roots(multiplicities=False) return self.roots(ring=CC, multiplicities=False) diff --git a/src/sage/rings/polynomial/polynomial_singular_interface.py b/src/sage/rings/polynomial/polynomial_singular_interface.py index 0a472405790..419eab22f40 100644 --- a/src/sage/rings/polynomial/polynomial_singular_interface.py +++ b/src/sage/rings/polynomial/polynomial_singular_interface.py @@ -386,10 +386,8 @@ def can_convert_to_singular(R): or sage.rings.finite_rings.finite_field_constructor.is_FiniteField(base_ring) or is_RationalField(base_ring) or is_IntegerModRing(base_ring) - or isinstance(base_ring, sage.rings.abc.RealField) - or isinstance(base_ring, sage.rings.abc.ComplexField) - or isinstance(base_ring, sage.rings.abc.RealDoubleField) - or isinstance(base_ring, sage.rings.abc.ComplexDoubleField)): + or isinstance(base_ring, (sage.rings.abc.RealField, sage.rings.abc.ComplexField, + sage.rings.abc.RealDoubleField, sage.rings.abc.ComplexDoubleField)): return True elif base_ring.is_prime_field(): return base_ring.characteristic() <= 2147483647 From 1d2956914662cf5b6390e381aa16a574cb804d58 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 2 Oct 2021 11:10:56 -0700 Subject: [PATCH 206/359] sage.{modular,quadratic_forms}: Fix up replacement of is_{Real,Complex}[Double]Field --- src/sage/modular/dirichlet.py | 4 ++-- src/sage/quadratic_forms/special_values.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sage/modular/dirichlet.py b/src/sage/modular/dirichlet.py index f71ef1e6f17..22c632c9789 100644 --- a/src/sage/modular/dirichlet.py +++ b/src/sage/modular/dirichlet.py @@ -1153,7 +1153,7 @@ def _pari_init_(self): # now compute the input for pari (list of exponents) P = self.parent() - if isinstance(P.base_ring(, sage.rings.abc.ComplexField)): + if isinstance(P.base_ring(), sage.rings.abc.ComplexField): zeta = P.zeta() zeta_argument = zeta.argument() v = [int(x.argument() / zeta_argument) for x in values_on_gens] @@ -2138,7 +2138,7 @@ def element(self): """ P = self.parent() M = P._module - if isinstance(P.base_ring(, sage.rings.abc.ComplexField)): + if isinstance(P.base_ring(), sage.rings.abc.ComplexField): zeta = P.zeta() zeta_argument = zeta.argument() v = M([int(round(x.argument() / zeta_argument)) diff --git a/src/sage/quadratic_forms/special_values.py b/src/sage/quadratic_forms/special_values.py index 5c7e3a1ccfe..e7b4c425866 100644 --- a/src/sage/quadratic_forms/special_values.py +++ b/src/sage/quadratic_forms/special_values.py @@ -9,7 +9,6 @@ from sage.combinat.combinat import bernoulli_polynomial from sage.misc.functional import denominator -from sage.rings.all import RealField from sage.arith.all import kronecker_symbol, bernoulli, factorial, fundamental_discriminant from sage.rings.infinity import infinity from sage.rings.integer_ring import ZZ @@ -278,9 +277,10 @@ def quadratic_L_function__numerical(n, d, num_terms=1000): ....: print("Oops! We have a problem at d = {}: exact = {}, numerical = {}".format(d, RR(quadratic_L_function__exact(1, d)), RR(quadratic_L_function__numerical(1, d)))) """ # Set the correct precision if it is given (for n). - if isinstance(n.parent(, sage.rings.abc.RealField)): + if isinstance(n.parent(), sage.rings.abc.RealField): R = n.parent() else: + from sage.rings.real_mpfr import RealField R = RealField() if n < 0: From a4ad3d4a21062fe99408d71d49bd8e21e10c63c4 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 2 Oct 2021 11:11:08 -0700 Subject: [PATCH 207/359] sage.matrix: Fix up replacement of is_{Real,Complex}[Double]Field --- src/sage/matrix/misc.pyx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/matrix/misc.pyx b/src/sage/matrix/misc.pyx index a70a9a0f711..c7fc1c70161 100644 --- a/src/sage/matrix/misc.pyx +++ b/src/sage/matrix/misc.pyx @@ -40,7 +40,7 @@ from sage.rings.rational_field import QQ from sage.rings.integer cimport Integer from sage.arith.all import previous_prime, CRT_basis -from sage.rings.real_mpfr import is_RealField +from sage.rings.real_mpfr cimport RealField_class from sage.rings.real_mpfr cimport RealNumber @@ -510,7 +510,7 @@ def hadamard_row_bound_mpfr(Matrix A): ... OverflowError: cannot convert float infinity to integer """ - if not isinstance(A.base_ring(, sage.rings.abc.RealField)): + if not isinstance(A.base_ring(), RealField_class): raise TypeError("A must have base field an mpfr real field.") cdef RealNumber a, b From f8d734d38c8f956581c08fedddc04ef156d8c562 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 2 Oct 2021 11:58:47 -0700 Subject: [PATCH 208/359] tox.ini, build/bin/write-dockerfile.sh: Re-enable networkx, symengine_py SAGE_CHECK --- build/bin/write-dockerfile.sh | 8 ++++---- tox.ini | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/build/bin/write-dockerfile.sh b/build/bin/write-dockerfile.sh index aa7050b203b..bd709957ef1 100755 --- a/build/bin/write-dockerfile.sh +++ b/build/bin/write-dockerfile.sh @@ -219,7 +219,7 @@ ARG NUMPROC=8 ENV MAKE="make -j\${NUMPROC}" ARG USE_MAKEFLAGS="-k V=0" ENV SAGE_CHECK=warn -ENV SAGE_CHECK_PACKAGES="!cython,!r,!python3,!gap,!cysignals,!linbox,!git,!ppl,!cmake,!networkx,!rpy2,!symengine_py,!sage_sws2rst" +ENV SAGE_CHECK_PACKAGES="!cython,!r,!python3,!gap,!cysignals,!linbox,!git,!ppl,!cmake,!rpy2,!sage_sws2rst" #:toolchain: $RUN make \${USE_MAKEFLAGS} base-toolchain $ENDRUN @@ -228,7 +228,7 @@ ARG NUMPROC=8 ENV MAKE="make -j\${NUMPROC}" ARG USE_MAKEFLAGS="-k V=0" ENV SAGE_CHECK=warn -ENV SAGE_CHECK_PACKAGES="!gfan,!cython,!r,!python3,!gap,!cysignals,!linbox,!git,!ppl,!cmake,!networkx,!rpy2,!symengine_py,!sage_sws2rst" +ENV SAGE_CHECK_PACKAGES="!gfan,!cython,!r,!python3,!gap,!cysignals,!linbox,!git,!ppl,!cmake,!rpy2,!sage_sws2rst" #:make: ARG TARGETS_PRE="all-sage-local" $RUN make SAGE_SPKG="sage-spkg -y -o" \${USE_MAKEFLAGS} \${TARGETS_PRE} $ENDRUN @@ -238,7 +238,7 @@ ARG NUMPROC=8 ENV MAKE="make -j\${NUMPROC}" ARG USE_MAKEFLAGS="-k V=0" ENV SAGE_CHECK=warn -ENV SAGE_CHECK_PACKAGES="!gfan,!cython,!r,!python3,!gap,!cysignals,!linbox,!git,!ppl,!cmake,!networkx,!rpy2,!symengine_py,!sage_sws2rst" +ENV SAGE_CHECK_PACKAGES="!gfan,!cython,!r,!python3,!gap,!cysignals,!linbox,!git,!ppl,!cmake,!rpy2,!sage_sws2rst" ADD src src ARG TARGETS="build" $RUN make SAGE_SPKG="sage-spkg -y -o" \${USE_MAKEFLAGS} \${TARGETS} $ENDRUN @@ -248,7 +248,7 @@ ARG NUMPROC=8 ENV MAKE="make -j\${NUMPROC}" ARG USE_MAKEFLAGS="-k V=0" ENV SAGE_CHECK=warn -ENV SAGE_CHECK_PACKAGES="!gfan,!cython,!r,!python3,!gap,!cysignals,!linbox,!git,!ppl,!cmake,!networkx,!rpy2,!symengine_py,!sage_sws2rst" +ENV SAGE_CHECK_PACKAGES="!gfan,!cython,!r,!python3,!gap,!cysignals,!linbox,!git,!ppl,!cmake,!rpy2,!sage_sws2rst" ARG TARGETS_OPTIONAL="ptest" $RUN make SAGE_SPKG="sage-spkg -y -o" \${USE_MAKEFLAGS} \${TARGETS_OPTIONAL} || echo "(error ignored)" $ENDRUN diff --git a/tox.ini b/tox.ini index d565133513b..d119fdfbd82 100644 --- a/tox.ini +++ b/tox.ini @@ -577,8 +577,8 @@ commands = local: config*) ;; \ local: *) make -k V=0 base-toolchain ;; \ local: esac && \ - local: make -k V=0 SAGE_CHECK=warn SAGE_CHECK_PACKAGES="!cython,!r,!python3,!gap,!cysignals,!linbox,!git,!ppl,!cmake,!networkx,!rpy2,!symengine_py,!sage_sws2rst" {env:TARGETS_PRE:} {posargs:build} && \ - local: ( [ -z "{env:TARGETS_OPTIONAL:}" ] || make -k V=0 SAGE_CHECK=warn SAGE_CHECK_PACKAGES="!cython,!r,!python3,!gap,!cysignals,!linbox,!git,!ppl,!cmake,!networkx,!rpy2,!symengine_py,!sage_sws2rst" {env:TARGETS_OPTIONAL:} || echo "(error ignored)" ) ' + local: make -k V=0 SAGE_CHECK=warn SAGE_CHECK_PACKAGES="!cython,!r,!python3,!gap,!cysignals,!linbox,!git,!ppl,!cmake,!rpy2,!sage_sws2rst" {env:TARGETS_PRE:} {posargs:build} && \ + local: ( [ -z "{env:TARGETS_OPTIONAL:}" ] || make -k V=0 SAGE_CHECK=warn SAGE_CHECK_PACKAGES="!cython,!r,!python3,!gap,!cysignals,!linbox,!git,!ppl,!cmake,!rpy2,!sage_sws2rst" {env:TARGETS_OPTIONAL:} || echo "(error ignored)" ) ' [testenv:check_configure] ## Test that configure behaves properly From c7aa947e4bd2437c872477176eab735d2d835f9e Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 2 Oct 2021 12:40:48 -0700 Subject: [PATCH 209/359] sage.probability: Fix up replacement of is_{Real,Complex}[Double]Field --- src/sage/probability/random_variable.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/sage/probability/random_variable.py b/src/sage/probability/random_variable.py index ea2c4c86b2f..bdb666dfeab 100644 --- a/src/sage/probability/random_variable.py +++ b/src/sage/probability/random_variable.py @@ -18,7 +18,6 @@ from sage.structure.parent import Parent from sage.functions.log import log from sage.functions.all import sqrt -from sage.rings.real_mpfr import (RealField, is_RealField) from sage.rings.rational_field import is_RationalField from sage.sets.set import Set from pprint import pformat @@ -83,6 +82,7 @@ def __init__(self, X, f, codomain=None, check=False): if check: raise NotImplementedError("Not implemented") if codomain is None: + from sage.rings.real_mpfr import RealField RR = RealField() else: RR = codomain @@ -337,6 +337,7 @@ def __init__(self, X, P, codomain=None, check=False): 1.50000000000000 """ if codomain is None: + from sage.rings.real_mpfr import RealField codomain = RealField() if not isinstance(codomain, sage.rings.abc.RealField) and not is_RationalField(codomain): raise TypeError("Argument codomain (= %s) must be the reals or rationals" % codomain) From b8691cc3154217d0ec0fa555403d6e88d31fd275 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 2 Oct 2021 12:41:03 -0700 Subject: [PATCH 210/359] src/sage/rings/number_field/number_field_element.pyx: Remove unused import --- src/sage/rings/number_field/number_field_element.pyx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/sage/rings/number_field/number_field_element.pyx b/src/sage/rings/number_field/number_field_element.pyx index 4ee3d048f07..67d8274d4c6 100644 --- a/src/sage/rings/number_field/number_field_element.pyx +++ b/src/sage/rings/number_field/number_field_element.pyx @@ -3945,7 +3945,6 @@ cdef class NumberFieldElement(FieldElement): if a <= Kv.one(): return Kv.zero() ht = a.log() - from sage.rings.real_mpfr import is_RealField if weighted and not isinstance(Kv, sage.rings.abc.RealField): ht*=2 return ht From abbe26dcc98ef905e3b70d1ef6cfd874181345df Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 2 Oct 2021 12:46:28 -0700 Subject: [PATCH 211/359] src/sage/modules/free_module.py: Remove another use of is_... functions --- src/sage/modules/free_module.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/sage/modules/free_module.py b/src/sage/modules/free_module.py index 57c10114174..c28a31707a7 100644 --- a/src/sage/modules/free_module.py +++ b/src/sage/modules/free_module.py @@ -170,6 +170,7 @@ from sage.modules.module import Module import sage.rings.finite_rings.finite_field_constructor as finite_field import sage.rings.ring as ring +import sage.rings.abc import sage.rings.integer_ring import sage.rings.rational_field import sage.rings.finite_rings.integer_mod_ring @@ -7443,9 +7444,9 @@ def element_class(R, is_sparse): return Vector_modn_dense else: return free_module_element.FreeModuleElement_generic_dense - elif sage.rings.real_double.is_RealDoubleField(R) and not is_sparse: + elif isinstance(R, sage.rings.abc.RealDoubleField) and not is_sparse: return sage.modules.vector_real_double_dense.Vector_real_double_dense - elif sage.rings.complex_double.is_ComplexDoubleField(R) and not is_sparse: + elif isinstance(R, sage.rings.abc.ComplexDoubleField) and not is_sparse: return sage.modules.vector_complex_double_dense.Vector_complex_double_dense elif sage.symbolic.ring.is_SymbolicExpressionRing(R) and not is_sparse: import sage.modules.vector_symbolic_dense From 65e9b9833bc8e4e837f775c8b867755271dedbe4 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 2 Oct 2021 14:07:52 -0700 Subject: [PATCH 212/359] src/sage/rings/polynomial/polynomial_singular_interface.py: Fixup --- src/sage/rings/polynomial/polynomial_singular_interface.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/rings/polynomial/polynomial_singular_interface.py b/src/sage/rings/polynomial/polynomial_singular_interface.py index 419eab22f40..2fd1ac24b2b 100644 --- a/src/sage/rings/polynomial/polynomial_singular_interface.py +++ b/src/sage/rings/polynomial/polynomial_singular_interface.py @@ -387,7 +387,7 @@ def can_convert_to_singular(R): or is_RationalField(base_ring) or is_IntegerModRing(base_ring) or isinstance(base_ring, (sage.rings.abc.RealField, sage.rings.abc.ComplexField, - sage.rings.abc.RealDoubleField, sage.rings.abc.ComplexDoubleField)): + sage.rings.abc.RealDoubleField, sage.rings.abc.ComplexDoubleField))): return True elif base_ring.is_prime_field(): return base_ring.characteristic() <= 2147483647 From 9096edb73bfa435e242635b5d5eb01b62aadd21a Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 2 Oct 2021 16:20:51 -0700 Subject: [PATCH 213/359] sage.features.sagemath: New --- src/sage/features/sagemath.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 src/sage/features/sagemath.py diff --git a/src/sage/features/sagemath.py b/src/sage/features/sagemath.py new file mode 100644 index 00000000000..32c6246b7fd --- /dev/null +++ b/src/sage/features/sagemath.py @@ -0,0 +1,28 @@ +r""" +Check for SageMath Python modules +""" +from . import PythonModule + + +class sage__combinat(PythonModule): + + def __init__(self): + PythonModule.__init__('sage.combinat.combinations') + + +class sage__graphs(PythonModule): + + def __init__(self): + PythonModule.__init__('sage.graphs.graph') + + +class sage__rings__real_double(PythonModule): + + def __init__(self): + PythonModule.__init__('sage.rings.real_double') + + +class sage__symbolic(PythonModule): + + def __init__(self): + PythonModule.__init__('sage.symbolic.expression', spkg="sagemath_symbolics") From a00d97a6da3193a8d12f7fb01488eb81ce13aa40 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 2 Oct 2021 16:24:14 -0700 Subject: [PATCH 214/359] src/sage/rings/number_field/number_field.py: Fixup --- src/sage/rings/number_field/number_field.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/rings/number_field/number_field.py b/src/sage/rings/number_field/number_field.py index 863fbd8aad8..f8cadacb0d0 100644 --- a/src/sage/rings/number_field/number_field.py +++ b/src/sage/rings/number_field/number_field.py @@ -9947,12 +9947,12 @@ def hilbert_symbol(self, a, b, P = None): codom = P.codomain() from sage.rings.complex_interval_field import is_ComplexIntervalField from sage.rings.all import (AA, QQbar) - if isinstance(codom, (sage.rings.abc.ComplexField, sage.rings.abc.ComplexDoubleField) or is_ComplexIntervalField(codom) or \ + if isinstance(codom, (sage.rings.abc.ComplexField, sage.rings.abc.ComplexDoubleField)) or is_ComplexIntervalField(codom) or \ codom is QQbar: if P(self.gen()).imag() == 0: raise ValueError("Possibly real place (=%s) given as complex embedding in hilbert_symbol. Is it real or complex?" % P) return 1 - if isinstance(codom, (sage.rings.abc.RealField, sage.rings.abc.RealDoubleField) or codom is AA: + if isinstance(codom, (sage.rings.abc.RealField, sage.rings.abc.RealDoubleField)) or codom is AA: if P(a) > 0 or P(b) > 0: return 1 return -1 From 2938e1387d002460ff7fdcc60e250799e47b6b4f Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 2 Oct 2021 17:05:06 -0700 Subject: [PATCH 215/359] src/sage/doctest/parsing.py: Allow . in optional tags --- src/sage/doctest/parsing.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/sage/doctest/parsing.py b/src/sage/doctest/parsing.py index 0be358f35be..7bceddde322 100644 --- a/src/sage/doctest/parsing.py +++ b/src/sage/doctest/parsing.py @@ -34,7 +34,7 @@ from .external import available_software float_regex = re.compile(r'\s*([+-]?\s*((\d*\.?\d+)|(\d+\.?))([eE][+-]?\d+)?)') -optional_regex = re.compile(r'(arb216|arb218|py2|py3|long time|not implemented|not tested|known bug)|([^ a-z]\s*optional\s*[:-]*((\s|\w)*))') +optional_regex = re.compile(r'(arb216|arb218|py2|py3|long time|not implemented|not tested|known bug)|([^ a-z]\s*optional\s*[:-]*((\s|\w|[.])*))') # Version 4.65 of glpk prints the warning "Long-step dual simplex will # be used" frequently. When Sage uses a system installation of glpk # which has not been patched, we need to ignore that message. @@ -316,6 +316,8 @@ def parse_optional_tags(string): {''} sage: sorted(list(parse_optional_tags("sage: #optional -- foo bar, baz"))) ['bar', 'foo'] + sage: parse_optional_tags("sage: #optional -- foo.bar, baz") + {'foo.bar'} sage: sorted(list(parse_optional_tags(" sage: factor(10^(10^10) + 1) # LoNg TiME, NoT TeSTED; OptioNAL -- P4cka9e"))) ['long time', 'not tested', 'p4cka9e'] sage: parse_optional_tags(" sage: raise RuntimeError # known bug") From 747b458420bffc389fdc1e3a1acec4148e818ba4 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 2 Oct 2021 17:05:46 -0700 Subject: [PATCH 216/359] sage.doctest.control, sage.features.sagemath: Provide/use optional tags --- src/sage/doctest/control.py | 3 +++ src/sage/features/sagemath.py | 28 ++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/src/sage/doctest/control.py b/src/sage/doctest/control.py index afb0d6cbcf1..c7d68478ff7 100644 --- a/src/sage/doctest/control.py +++ b/src/sage/doctest/control.py @@ -53,6 +53,9 @@ except ImportError: pass +from sage.features.sagemath import sage_optional_tags +auto_optional_tags |= sage_optional_tags() + class DocTestDefaults(SageObject): """ This class is used for doctesting the Sage doctest module. diff --git a/src/sage/features/sagemath.py b/src/sage/features/sagemath.py index 32c6246b7fd..c6d253a9c51 100644 --- a/src/sage/features/sagemath.py +++ b/src/sage/features/sagemath.py @@ -7,6 +7,9 @@ class sage__combinat(PythonModule): def __init__(self): + # sage.combinat will be a namespace package. + # Testing whether sage.combinat itself can be imported is meaningless. + # Hence, we test a Python module within the package. PythonModule.__init__('sage.combinat.combinations') @@ -26,3 +29,28 @@ class sage__symbolic(PythonModule): def __init__(self): PythonModule.__init__('sage.symbolic.expression', spkg="sagemath_symbolics") + + +def sage_optional_tags(): + """ + Return tags for conditionalizing doctests. + + These tags are named after Python packages/modules (e.g., :mod:`~sage.symbolic`), + not distribution packages (``sagemath-symbolics``). + + This is motivated by a separation of concerns: The author of a module that depends + on some functionality provided by a Python module usually already knows the + name of the Python module, so we do not want to force the author to also + know about the distribution package that provides the Python module. + + Instead, we associate distribution packages to Python modules in + :mod:`sage.features.sagemath` via the ``spkg`` parameter of :class:`PythonModule``. + """ + if sage__combinat().is_functional(): + yield 'sage.combinat' + if sage__graphs().is_functional(): + yield 'sage.graphs' + if sage__rings__real_double().is_functional(): + yield 'sage.rings.real_double' + if sage__symbolic().is_functional(): + yield 'sage.symbolic' From e3a541e039081242121e247b51c3fc42c963cd43 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 2 Oct 2021 17:13:22 -0700 Subject: [PATCH 217/359] Fixup --- src/sage/doctest/control.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/doctest/control.py b/src/sage/doctest/control.py index c7d68478ff7..42ed54ddb49 100644 --- a/src/sage/doctest/control.py +++ b/src/sage/doctest/control.py @@ -54,7 +54,7 @@ pass from sage.features.sagemath import sage_optional_tags -auto_optional_tags |= sage_optional_tags() +auto_optional_tags.update(sage_optional_tags()) class DocTestDefaults(SageObject): """ From 5e04a85c4dbe3663bab664b7356d255b5ddc1cf6 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 2 Oct 2021 17:16:55 -0700 Subject: [PATCH 218/359] src/sage/features/sagemath.py: Fixup --- src/sage/features/sagemath.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/sage/features/sagemath.py b/src/sage/features/sagemath.py index c6d253a9c51..57bb082c8c5 100644 --- a/src/sage/features/sagemath.py +++ b/src/sage/features/sagemath.py @@ -10,25 +10,25 @@ def __init__(self): # sage.combinat will be a namespace package. # Testing whether sage.combinat itself can be imported is meaningless. # Hence, we test a Python module within the package. - PythonModule.__init__('sage.combinat.combinations') + PythonModule.__init__(self, 'sage.combinat.combinations') class sage__graphs(PythonModule): def __init__(self): - PythonModule.__init__('sage.graphs.graph') + PythonModule.__init__(self, 'sage.graphs.graph') class sage__rings__real_double(PythonModule): def __init__(self): - PythonModule.__init__('sage.rings.real_double') + PythonModule.__init__(self, 'sage.rings.real_double') class sage__symbolic(PythonModule): def __init__(self): - PythonModule.__init__('sage.symbolic.expression', spkg="sagemath_symbolics") + PythonModule.__init__(self, 'sage.symbolic.expression', spkg="sagemath_symbolics") def sage_optional_tags(): @@ -46,11 +46,11 @@ def sage_optional_tags(): Instead, we associate distribution packages to Python modules in :mod:`sage.features.sagemath` via the ``spkg`` parameter of :class:`PythonModule``. """ - if sage__combinat().is_functional(): + if sage__combinat().is_present(): yield 'sage.combinat' - if sage__graphs().is_functional(): + if sage__graphs().is_present(): yield 'sage.graphs' - if sage__rings__real_double().is_functional(): + if sage__rings__real_double().is_present(): yield 'sage.rings.real_double' - if sage__symbolic().is_functional(): + if sage__symbolic().is_present(): yield 'sage.symbolic' From 66cf3e12e49e6d5b86bd6023edc2d9d92ee2b00e Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 2 Oct 2021 17:58:35 -0700 Subject: [PATCH 219/359] src/sage/doctest/control.py: Fixup handling of sage_optional_tags --- src/sage/doctest/control.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sage/doctest/control.py b/src/sage/doctest/control.py index 42ed54ddb49..05767a50876 100644 --- a/src/sage/doctest/control.py +++ b/src/sage/doctest/control.py @@ -40,7 +40,7 @@ from .external import external_software, available_software nodoctest_regex = re.compile(r'\s*(#+|%+|r"+|"+|\.\.)\s*nodoctest') -optionaltag_regex = re.compile(r'^\w+$') +optionaltag_regex = re.compile(r'^(\w|[.])+$') # Optional tags which are always automatically added @@ -53,9 +53,6 @@ except ImportError: pass -from sage.features.sagemath import sage_optional_tags -auto_optional_tags.update(sage_optional_tags()) - class DocTestDefaults(SageObject): """ This class is used for doctesting the Sage doctest module. @@ -374,6 +371,9 @@ def __init__(self, options, args): from sage.features import package_systems options.optional.update(system.name for system in package_systems()) + from sage.features.sagemath import sage_optional_tags + options.optional.update(sage_optional_tags()) + # Check that all tags are valid for o in options.optional: if not optionaltag_regex.search(o): From 13eed83e9ab842e4299d5cc81a0e97679856e5f5 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 2 Oct 2021 17:59:21 -0700 Subject: [PATCH 220/359] src/sage/doctest/parsing.py: Do not fail if RealIntervalField cannot be imported, just warn --- src/sage/doctest/parsing.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/sage/doctest/parsing.py b/src/sage/doctest/parsing.py index 0be358f35be..1591dd609cd 100644 --- a/src/sage/doctest/parsing.py +++ b/src/sage/doctest/parsing.py @@ -83,9 +83,19 @@ def RIFtol(*args): """ global _RIFtol if _RIFtol is None: - # We need to import from sage.all to avoid circular imports. - from sage.all import RealIntervalField - _RIFtol = RealIntervalField(1044) + try: + # We need to import from sage.all to avoid circular imports. + from sage.all import RealIntervalField + except ImportError: + from warnings import warn + warn("RealIntervalField not available, ignoring all tolerance specifications in doctests") + def fake_RIFtol(*args): + if len(args) == 2: + return (args[0] + args[1]) / 2 + return args[0] + _RIFtol = fake_RIFtol + else: + _RIFtol = RealIntervalField(1044) return _RIFtol(*args) # This is the correct pattern to match ISO/IEC 6429 ANSI escape sequences: From 1ec0c485ccaed52ce83ba66c479fadfa3ef9b167 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 2 Oct 2021 18:37:51 -0700 Subject: [PATCH 221/359] src/sage/features/sagemath.py: Add sage.rings.number_field --- src/sage/features/sagemath.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/sage/features/sagemath.py b/src/sage/features/sagemath.py index 57bb082c8c5..1172b6a3ff6 100644 --- a/src/sage/features/sagemath.py +++ b/src/sage/features/sagemath.py @@ -19,6 +19,12 @@ def __init__(self): PythonModule.__init__(self, 'sage.graphs.graph') +class sage__rings__number_field(PythonModule): + + def __init__(self): + PythonModule.__init__(self, 'sage.rings.number_field_element') + + class sage__rings__real_double(PythonModule): def __init__(self): @@ -50,6 +56,8 @@ def sage_optional_tags(): yield 'sage.combinat' if sage__graphs().is_present(): yield 'sage.graphs' + if sage__rings__number_field().is_present(): + yield 'sage.rings.number_field' if sage__rings__real_double().is_present(): yield 'sage.rings.real_double' if sage__symbolic().is_present(): From 6da082a7c611da789273d17686dd70d013fdd57a Mon Sep 17 00:00:00 2001 From: dcoudert Date: Sun, 3 Oct 2021 10:52:29 +0200 Subject: [PATCH 222/359] trac #17537: typo --- src/sage/graphs/convexity_properties.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/graphs/convexity_properties.pyx b/src/sage/graphs/convexity_properties.pyx index 19c1224cab3..c260daff32e 100644 --- a/src/sage/graphs/convexity_properties.pyx +++ b/src/sage/graphs/convexity_properties.pyx @@ -599,7 +599,7 @@ def geodetic_closure(G, S): cdef dict vertex_to_int = {u: i for i, u in enumerate(int_to_vertex)} cdef list S_int = [vertex_to_int[u] for u in S] - # Copy the graph has a short digraph + # Copy the graph as a short digraph cdef short_digraph sd init_short_digraph(sd, G, edge_labelled=False, vertex_list=int_to_vertex) From 5d190dd754444367f9728bc24d0f1616502aa3a2 Mon Sep 17 00:00:00 2001 From: Kwankyu Lee Date: Sun, 3 Oct 2021 18:05:26 +0900 Subject: [PATCH 223/359] Use raw docstring to prevent invalid escape warning --- src/sage/rings/function_field/ideal.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/rings/function_field/ideal.py b/src/sage/rings/function_field/ideal.py index 3dbadab335c..e1a96b3d171 100644 --- a/src/sage/rings/function_field/ideal.py +++ b/src/sage/rings/function_field/ideal.py @@ -2269,7 +2269,7 @@ def gens_two(self): @cached_method def _gens_two(self): - """ + r""" Return a set of two generators of the integral ideal, that is the denominator times this fractional ideal. From 0a77fa52ca71ec76aca7ad9a7867b66828e6c761 Mon Sep 17 00:00:00 2001 From: Kwankyu Lee Date: Sun, 3 Oct 2021 18:34:31 +0900 Subject: [PATCH 224/359] Drop use of _gens_two.cache --- src/sage/rings/function_field/ideal.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/sage/rings/function_field/ideal.py b/src/sage/rings/function_field/ideal.py index e1a96b3d171..8c40ae37398 100644 --- a/src/sage/rings/function_field/ideal.py +++ b/src/sage/rings/function_field/ideal.py @@ -2175,10 +2175,12 @@ def __pow__(self, mod): sage: I = O.ideal(y) sage: J = O.ideal(x + y) sage: S = I / J - sage: S^100 == I^100 / J^100 - True + sage: a = S^100 sage: _ = S.gens_two() - sage: S^100 == I^100 / J^100 # faster + sage: b = S^100 # faster + sage: b == I^100 / J^100 + True + sage: b == a True """ if mod > 2 and self._gens_two_vecs is not None: @@ -2195,10 +2197,7 @@ def __pow__(self, mod): J = [ppow * v for v in I] else: p, q = self._gens_two_vecs - if len(self._gens_two.cache) == 2: - _, q = self._gens_two.cache - else: - q = sum(e1 * e2 for e1,e2 in zip(O.basis(), q)) + q = sum(e1 * e2 for e1,e2 in zip(O.basis(), q)) ppow = p**mod qpow = O._coordinate_vector(q**mod) J = [ppow * v for v in I] + [mul(qpow,v) for v in I] From fa79b1020329a8a616be4a315451db2cc85c88f0 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 3 Oct 2021 09:45:38 -0700 Subject: [PATCH 225/359] Add missing imports of sage.rings.abc --- src/sage/functions/special.py | 1 + src/sage/probability/random_variable.py | 1 + 2 files changed, 2 insertions(+) diff --git a/src/sage/functions/special.py b/src/sage/functions/special.py index bc43c362141..63083a617a0 100644 --- a/src/sage/functions/special.py +++ b/src/sage/functions/special.py @@ -158,6 +158,7 @@ # https://www.gnu.org/licenses/ # **************************************************************************** +import sage.rings.abc from sage.rings.integer import Integer from sage.misc.latex import latex from sage.rings.all import ZZ diff --git a/src/sage/probability/random_variable.py b/src/sage/probability/random_variable.py index bdb666dfeab..47d108996f0 100644 --- a/src/sage/probability/random_variable.py +++ b/src/sage/probability/random_variable.py @@ -15,6 +15,7 @@ # https://www.gnu.org/licenses/ # **************************************************************************** +import sage.rings.abc from sage.structure.parent import Parent from sage.functions.log import log from sage.functions.all import sqrt From 94fd9c52828b628f2417aa85ce2fe694545424a6 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 3 Oct 2021 09:48:50 -0700 Subject: [PATCH 226/359] is_{Real,Complex}[Double]Field: In doctests, add deprecation warning to expected output --- src/sage/rings/complex_double.pyx | 4 ++++ src/sage/rings/complex_mpfr.pyx | 4 ++++ src/sage/rings/real_double.pyx | 4 ++++ src/sage/rings/real_mpfr.pyx | 4 ++++ 4 files changed, 16 insertions(+) diff --git a/src/sage/rings/complex_double.pyx b/src/sage/rings/complex_double.pyx index 6977939b789..7a2d45d1028 100644 --- a/src/sage/rings/complex_double.pyx +++ b/src/sage/rings/complex_double.pyx @@ -123,6 +123,10 @@ def is_ComplexDoubleField(x): sage: from sage.rings.complex_double import is_ComplexDoubleField sage: is_ComplexDoubleField(CDF) + doctest:warning... + DeprecationWarning: is_ComplexDoubleField is deprecated; + use isinstance(..., sage.rings.abc.ComplexDoubleField) instead + See https://trac.sagemath.org/32610 for details. True sage: is_ComplexDoubleField(ComplexField(53)) False diff --git a/src/sage/rings/complex_mpfr.pyx b/src/sage/rings/complex_mpfr.pyx index d51bbdbc469..3021ab5d177 100644 --- a/src/sage/rings/complex_mpfr.pyx +++ b/src/sage/rings/complex_mpfr.pyx @@ -169,6 +169,10 @@ def is_ComplexField(x): sage: from sage.rings.complex_mpfr import is_ComplexField as is_CF sage: is_CF(ComplexField()) + doctest:warning... + DeprecationWarning: is_ComplexField is deprecated; + use isinstance(..., sage.rings.abc.ComplexField) instead + See https://trac.sagemath.org/32610 for details. True sage: is_CF(ComplexField(12)) True diff --git a/src/sage/rings/real_double.pyx b/src/sage/rings/real_double.pyx index bccbc382bff..d3ad8ecfb0e 100644 --- a/src/sage/rings/real_double.pyx +++ b/src/sage/rings/real_double.pyx @@ -84,6 +84,10 @@ def is_RealDoubleField(x): sage: from sage.rings.real_double import is_RealDoubleField sage: is_RealDoubleField(RDF) + doctest:warning... + DeprecationWarning: is_RealDoubleField is deprecated; + use isinstance(..., sage.rings.abc.RealDoubleField) instead + See https://trac.sagemath.org/32610 for details. True sage: is_RealDoubleField(RealField(53)) False diff --git a/src/sage/rings/real_mpfr.pyx b/src/sage/rings/real_mpfr.pyx index cefe99b6c1c..bd9b7931463 100644 --- a/src/sage/rings/real_mpfr.pyx +++ b/src/sage/rings/real_mpfr.pyx @@ -5906,6 +5906,10 @@ def is_RealField(x): EXAMPLES:: sage: sage.rings.real_mpfr.is_RealField(RR) + doctest:warning... + DeprecationWarning: is_RealField is deprecated; + use isinstance(..., sage.rings.abc.RealField) instead + See https://trac.sagemath.org/32610 for details. True sage: sage.rings.real_mpfr.is_RealField(CC) False From dd7e96c442e45b509ee607a6cbd96f2ff7bbefdc Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 3 Oct 2021 14:45:50 -0700 Subject: [PATCH 227/359] src/sage/schemes/elliptic_curves/ell_number_field.py: Add missing import --- src/sage/schemes/elliptic_curves/ell_number_field.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sage/schemes/elliptic_curves/ell_number_field.py b/src/sage/schemes/elliptic_curves/ell_number_field.py index f0bcda573df..097ca89624d 100644 --- a/src/sage/schemes/elliptic_curves/ell_number_field.py +++ b/src/sage/schemes/elliptic_curves/ell_number_field.py @@ -85,6 +85,7 @@ # https://www.gnu.org/licenses/ # **************************************************************************** +import sage.rings.abc from .ell_field import EllipticCurve_field from .ell_generic import is_EllipticCurve from .ell_point import EllipticCurvePoint_number_field From 006374980e227e2e15b9324d3a3b47b2290d7570 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 3 Oct 2021 14:55:25 -0700 Subject: [PATCH 228/359] src/sage/features/sagemath.py: Add features for modules that were optional extensions --- src/sage/features/sagemath.py | 40 +++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/sage/features/sagemath.py b/src/sage/features/sagemath.py index 1172b6a3ff6..f18e5e79e88 100644 --- a/src/sage/features/sagemath.py +++ b/src/sage/features/sagemath.py @@ -19,6 +19,38 @@ def __init__(self): PythonModule.__init__(self, 'sage.graphs.graph') +class sage__graphs__bliss(PythonModule): + + def __init__(self): + # Currently part of sagemath_standard, conditionally built. + # Will be changed to spkg='sagemath_bliss' later + PythonModule.__init__(self, 'sage.graphs.bliss', spkg='bliss') + + +class sage__graphs__graph_decompositions__tdlib(PythonModule): + + def __init__(self): + # Currently part of sagemath_standard, conditionally built. + # Will be changed to spkg='sagemath_tdlib' later + PythonModule.__init__(self, 'sage.graphs.graph_decompositions.tdlib', spkg='tdlib') + + +class sage__graphs__mcqd(PythonModule): + + def __init__(self): + # Currently part of sagemath_standard, conditionally built. + # Will be changed to spkg='sagemath_mcqd' later + PythonModule.__init__(self, 'sage.graphs.mcqd', spkg='mcqd') + + +class sage__matrix__matrix_gfpn_dense(PythonModule): + + def __init__(self): + # Currently part of sagemath_standard, conditionally built. + # Will be changed to spkg='sagemath_meataxe' later + PythonModule.__init__(self, 'sage.matrix.matrix_gfpn_dense', spkg='meataxe') + + class sage__rings__number_field(PythonModule): def __init__(self): @@ -56,6 +88,14 @@ def sage_optional_tags(): yield 'sage.combinat' if sage__graphs().is_present(): yield 'sage.graphs' + if sage__graphs__bliss().is_present(): + yield 'sage.graphs.bliss' + if sage__graphs__graph_decompositions__tdlib().is_present(): + yield 'sage.graphs.graph_decompositions.tdlib' + if sage__graphs__mcqd().is_present(): + yield 'sage.graphs.mcqd' + if sage__matrix__matrix_gfpn_dense().is_present(): + yield 'sage.matrix.matrix_gfpn_dense' if sage__rings__number_field().is_present(): yield 'sage.rings.number_field' if sage__rings__real_double().is_present(): From d6c6e90f5d4e8653fcd776bc534aa06aa2effdd9 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 3 Oct 2021 17:26:27 -0700 Subject: [PATCH 229/359] sage.rings.abc: Add {Real,Complex}{Ball,Interval}Field --- src/sage/rings/abc.pyx | 32 ++++++++++++++++++++++++ src/sage/rings/complex_arb.pyx | 4 ++- src/sage/rings/complex_interval_field.py | 3 ++- src/sage/rings/real_arb.pyx | 3 ++- src/sage/rings/real_mpfi.pxd | 4 +-- src/sage/rings/real_mpfi.pyx | 2 +- 6 files changed, 42 insertions(+), 6 deletions(-) diff --git a/src/sage/rings/abc.pyx b/src/sage/rings/abc.pyx index c65e03d9ed0..66ad7030fc7 100644 --- a/src/sage/rings/abc.pyx +++ b/src/sage/rings/abc.pyx @@ -10,6 +10,22 @@ cdef class RealField(Field): pass +class RealBallField(Field): + r""" + Abstract base class for :class:`~sage.rings.real_arb.RealBallField`. + """ + + pass + + +cdef class RealIntervalField(Field): + r""" + Abstract base class for :class:`~sage.rings.real_mpfi.RealIntervalField_class`. + """ + + pass + + cdef class RealDoubleField(Field): r""" Abstract base class for :class:`~sage.rings.real_double.RealDoubleField_class`. @@ -26,6 +42,22 @@ cdef class ComplexField(Field): pass +class ComplexBallField(Field): + r""" + Abstract base class for :class:`~sage.rings.complex_arb.ComplexBallField`. + """ + + pass + + +class ComplexIntervalField(Field): + r""" + Abstract base class for :class:`~sage.rings.complex_interval_field.ComplexIntervalField_class`. + """ + + pass + + cdef class ComplexDoubleField(Field): r""" Abstract base class for :class:`~sage.rings.complex_double.ComplexDoubleField_class`. diff --git a/src/sage/rings/complex_arb.pyx b/src/sage/rings/complex_arb.pyx index 2fc0a3bb420..2e2643946da 100644 --- a/src/sage/rings/complex_arb.pyx +++ b/src/sage/rings/complex_arb.pyx @@ -147,6 +147,7 @@ from cysignals.signals cimport sig_on, sig_str, sig_off, sig_error import sage.categories.fields +cimport sage.rings.abc cimport sage.rings.rational from cpython.float cimport PyFloat_AS_DOUBLE @@ -301,7 +302,8 @@ cdef int acb_calc_func_callback(acb_ptr out, const acb_t inp, void * param, finally: sig_on() -class ComplexBallField(UniqueRepresentation, Field): + +class ComplexBallField(UniqueRepresentation, sage.rings.abc.ComplexBallField): r""" An approximation of the field of complex numbers using pairs of mid-rad intervals. diff --git a/src/sage/rings/complex_interval_field.py b/src/sage/rings/complex_interval_field.py index cee580b22a3..e046891c437 100644 --- a/src/sage/rings/complex_interval_field.py +++ b/src/sage/rings/complex_interval_field.py @@ -40,6 +40,7 @@ from .integer_ring import ZZ from .rational_field import QQ from .ring import Field +import sage.rings.abc from . import integer from . import complex_interval import weakref @@ -93,7 +94,7 @@ def ComplexIntervalField(prec=53, names=None): return C -class ComplexIntervalField_class(Field): +class ComplexIntervalField_class(sage.rings.abc.ComplexIntervalField): """ The field of complex (interval) numbers. diff --git a/src/sage/rings/real_arb.pyx b/src/sage/rings/real_arb.pyx index 66a9d7bda06..43b6b6da5fd 100644 --- a/src/sage/rings/real_arb.pyx +++ b/src/sage/rings/real_arb.pyx @@ -219,6 +219,7 @@ from sage.libs.mpfr cimport MPFR_RNDN, MPFR_RNDU, MPFR_RNDD, MPFR_RNDZ from sage.structure.element cimport Element, ModuleElement, RingElement from sage.rings.ring cimport Field +import sage.rings.abc from sage.rings.integer cimport Integer from sage.rings.rational cimport Rational from sage.rings.real_double cimport RealDoubleElement @@ -320,7 +321,7 @@ cdef int arb_to_mpfi(mpfi_t target, arb_t source, const long precision) except - mpfr_clear(right) -class RealBallField(UniqueRepresentation, Field): +class RealBallField(UniqueRepresentation, sage.rings.abc.RealBallField): r""" An approximation of the field of real numbers using mid-rad intervals, also known as balls. diff --git a/src/sage/rings/real_mpfi.pxd b/src/sage/rings/real_mpfi.pxd index c32dcc959d0..5466a5f575f 100644 --- a/src/sage/rings/real_mpfi.pxd +++ b/src/sage/rings/real_mpfi.pxd @@ -2,7 +2,7 @@ from sage.libs.mpfr.types cimport mpfr_prec_t from sage.libs.mpfi.types cimport mpfi_t from sage.rings.ring cimport Field - +cimport sage.rings.abc from sage.structure.element cimport RingElement from .rational cimport Rational @@ -10,7 +10,7 @@ from .real_mpfr cimport RealField_class cdef class RealIntervalFieldElement(RingElement) # forward decl -cdef class RealIntervalField_class(Field): +cdef class RealIntervalField_class(sage.rings.abc.RealIntervalField): cdef mpfr_prec_t __prec cdef bint sci_not # Cache RealField instances for the lower, upper, and middle bounds. diff --git a/src/sage/rings/real_mpfi.pyx b/src/sage/rings/real_mpfi.pyx index 2bfdc5f2512..ce83e1ddf4e 100644 --- a/src/sage/rings/real_mpfi.pyx +++ b/src/sage/rings/real_mpfi.pyx @@ -345,7 +345,7 @@ cpdef RealIntervalField_class RealIntervalField(prec=53, sci_not=False): return R -cdef class RealIntervalField_class(Field): +cdef class RealIntervalField_class(sage.rings.abc.RealIntervalField): """ Class of the real interval field. From 8964311a5e358b93a72381faa550e31e5d9ed90d Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Mon, 4 Oct 2021 09:26:51 +0900 Subject: [PATCH 230/359] Some cleanup and micro-optimizations to (skew) tableau. --- src/sage/combinat/lr_tableau.py | 5 +- src/sage/combinat/skew_tableau.py | 87 +++++++++++++++++------------- src/sage/combinat/tableau.py | 32 +++++------ src/sage/combinat/tableau_tuple.py | 2 +- 4 files changed, 71 insertions(+), 55 deletions(-) diff --git a/src/sage/combinat/lr_tableau.py b/src/sage/combinat/lr_tableau.py index 6d14d998066..a300846d8de 100644 --- a/src/sage/combinat/lr_tableau.py +++ b/src/sage/combinat/lr_tableau.py @@ -116,12 +116,12 @@ def check(self): Traceback (most recent call last): ... ValueError: [[1, 1, 2], [3, 3], [4]] is not an element of - Littlewood-Richardson Tableaux of shape [3, 2, 1] and weight ([2, 1], [2, 1]). + Littlewood-Richardson Tableaux of shape [3, 2, 1] and weight ([2, 1], [2, 1]) sage: LR([[1, 1, 2, 3], [3], [4]]) Traceback (most recent call last): ... ValueError: [[1, 1, 2, 3], [3], [4]] is not an element of - Littlewood-Richardson Tableaux of shape [3, 2, 1] and weight ([2, 1], [2, 1]). + Littlewood-Richardson Tableaux of shape [3, 2, 1] and weight ([2, 1], [2, 1]) sage: LR([[1, 1, 3], [3, 3], [4]]) Traceback (most recent call last): ... @@ -304,3 +304,4 @@ def _tableau_join(t1, t2, shift=0): """ return [[e1 for e1 in row1] + [e2+shift for e2 in row2 if e2 is not None] for (row1, row2) in zip_longest(t1, t2, fillvalue=[])] + diff --git a/src/sage/combinat/skew_tableau.py b/src/sage/combinat/skew_tableau.py index c04128ce691..99ef0d512e3 100644 --- a/src/sage/combinat/skew_tableau.py +++ b/src/sage/combinat/skew_tableau.py @@ -437,7 +437,8 @@ def size(self): sage: SkewTableau([[None, 2], [1, 3]]).size() 3 """ - return sum(len([x for x in row if x is not None]) for row in self) + one = ZZ.one() + return sum(one for row in self for x in row if x is not None) def conjugate(self): """ @@ -539,10 +540,8 @@ def to_permutation(self): [] """ from sage.combinat.permutation import Permutation - word = [] - for row in reversed(self): - word += [i for i in row if i is not None] - return Permutation(word) + perm = [i for row in reversed(self) for i in row if i is not None] + return Permutation(perm) def weight(self): r""" @@ -591,7 +590,7 @@ def weight(self): sage: all(by_word(t) == SkewTableau(t).weight() for t in SST) True """ - if len(self) == 0 or all(c is None for row in self for c in row): + if (not self) or all(c is None for row in self for c in row): return [] m = max(c for row in self for c in row if c is not None) if m is None: @@ -623,10 +622,7 @@ def is_standard(self): """ # Check to make sure that it is filled with 1...size w = [i for row in self for i in row if i is not None] - if sorted(w) != list(range(1, len(w) + 1)): - return False - else: - return self.is_semistandard() + return sorted(w) == list(range(1, len(w) + 1)) and self.is_semistandard() def is_semistandard(self): """ @@ -683,9 +679,8 @@ def to_tableau(self): if self.inner_size() != 0: raise ValueError("the inner size of the skew tableau must be 0") - else: - from sage.combinat.tableau import Tableau - return Tableau(self[:]) + from sage.combinat.tableau import Tableau + return Tableau(self[:]) def restrict(self, n): """ @@ -708,9 +703,8 @@ def restrict(self, n): sage: SkewTableau([[None,1],[1],[2]]).restrict(1) [[None, 1], [1]] """ - t = self[:] return SkewTableau([z for z in [[y for y in x if y is None or y <= n] - for x in t] if z]) + for x in self] if z]) def restriction_outer_shape(self, n): """ @@ -743,9 +737,10 @@ def restriction_outer_shape(self, n): sage: T.restriction_outer_shape(19) [4, 3, 1] """ - from sage.combinat.partition import Partition - res = [len([y for y in row if y is None or y <= n]) for row in self] - return Partition(res) + from sage.combinat.partition import _Partitions + one = ZZ.one() + res = [sum(one for y in row if y is None or y <= n) for row in self] + return _Partitions(res) def restriction_shape(self, n): """ @@ -821,7 +816,7 @@ def to_chain(self, max_entry=None): [[1]] """ if max_entry is None: - if len(self) == 0 or all(c is None for row in self for c in row): + if (not self) or all(c is None for row in self for c in row): max_entry = 0 else: max_entry = max(c for row in self for c in row if c is not None) @@ -1214,38 +1209,49 @@ def bender_knuth_involution(self, k, rows=None, check=True): EXAMPLES:: - sage: t = SkewTableau([[None,None,None,4,4,5,6,7],[None,2,4,6,7,7,7],[None,4,5,8,8,9],[None,6,7,10],[None,8,8,11],[None],[4]]) + sage: t = SkewTableau([[None,None,None,4,4,5,6,7],[None,2,4,6,7,7,7], + ....: [None,4,5,8,8,9],[None,6,7,10],[None,8,8,11],[None],[4]]) sage: t - [[None, None, None, 4, 4, 5, 6, 7], [None, 2, 4, 6, 7, 7, 7], [None, 4, 5, 8, 8, 9], [None, 6, 7, 10], [None, 8, 8, 11], [None], [4]] + [[None, None, None, 4, 4, 5, 6, 7], [None, 2, 4, 6, 7, 7, 7], + [None, 4, 5, 8, 8, 9], [None, 6, 7, 10], [None, 8, 8, 11], [None], [4]] sage: t.bender_knuth_involution(1) - [[None, None, None, 4, 4, 5, 6, 7], [None, 1, 4, 6, 7, 7, 7], [None, 4, 5, 8, 8, 9], [None, 6, 7, 10], [None, 8, 8, 11], [None], [4]] + [[None, None, None, 4, 4, 5, 6, 7], [None, 1, 4, 6, 7, 7, 7], + [None, 4, 5, 8, 8, 9], [None, 6, 7, 10], [None, 8, 8, 11], [None], [4]] sage: t.bender_knuth_involution(4) - [[None, None, None, 4, 5, 5, 6, 7], [None, 2, 4, 6, 7, 7, 7], [None, 5, 5, 8, 8, 9], [None, 6, 7, 10], [None, 8, 8, 11], [None], [5]] + [[None, None, None, 4, 5, 5, 6, 7], [None, 2, 4, 6, 7, 7, 7], + [None, 5, 5, 8, 8, 9], [None, 6, 7, 10], [None, 8, 8, 11], [None], [5]] sage: t.bender_knuth_involution(5) - [[None, None, None, 4, 4, 5, 6, 7], [None, 2, 4, 5, 7, 7, 7], [None, 4, 6, 8, 8, 9], [None, 5, 7, 10], [None, 8, 8, 11], [None], [4]] + [[None, None, None, 4, 4, 5, 6, 7], [None, 2, 4, 5, 7, 7, 7], + [None, 4, 6, 8, 8, 9], [None, 5, 7, 10], [None, 8, 8, 11], [None], [4]] sage: t.bender_knuth_involution(6) - [[None, None, None, 4, 4, 5, 6, 6], [None, 2, 4, 6, 6, 7, 7], [None, 4, 5, 8, 8, 9], [None, 6, 7, 10], [None, 8, 8, 11], [None], [4]] + [[None, None, None, 4, 4, 5, 6, 6], [None, 2, 4, 6, 6, 7, 7], + [None, 4, 5, 8, 8, 9], [None, 6, 7, 10], [None, 8, 8, 11], [None], [4]] sage: t.bender_knuth_involution(666) == t True sage: t.bender_knuth_involution(4, 2) == t True sage: t.bender_knuth_involution(4, 3) - [[None, None, None, 4, 4, 5, 6, 7], [None, 2, 4, 6, 7, 7, 7], [None, 5, 5, 8, 8, 9], [None, 6, 7, 10], [None, 8, 8, 11], [None], [4]] + [[None, None, None, 4, 4, 5, 6, 7], [None, 2, 4, 6, 7, 7, 7], + [None, 5, 5, 8, 8, 9], [None, 6, 7, 10], [None, 8, 8, 11], [None], [4]] The Bender--Knuth involution is an involution:: sage: t = SkewTableau([[None,3,4,4],[None,6,10],[7,7,11],[18]]) - sage: all(t.bender_knuth_involution(k).bender_knuth_involution(k) == t for k in range(1,4)) + sage: all(t.bender_knuth_involution(k).bender_knuth_involution(k) + ....: == t for k in range(1,4)) True The same for the single switches:: - sage: all(t.bender_knuth_involution(k, j).bender_knuth_involution(k, j) == t for k in range(1,5) for j in range(1, 5)) + sage: all(t.bender_knuth_involution(k, j).bender_knuth_involution(k, j) + ....: == t for k in range(1,5) for j in range(1, 5)) True Locality of the Bender--Knuth involutions:: - sage: all(t.bender_knuth_involution(k).bender_knuth_involution(l) == t.bender_knuth_involution(l).bender_knuth_involution(k) for k in range(1,5) for l in range(1,5) if abs(k - l) > 1) + sage: all(t.bender_knuth_involution(k).bender_knuth_involution(l) + ....: == t.bender_knuth_involution(l).bender_knuth_involution(k) + ....: for k in range(1,5) for l in range(1,5) if abs(k - l) > 1) True TESTS:: @@ -1494,7 +1500,7 @@ def cells_by_content(self, c): sage: s.cells_by_content(-2) [(2, 0)] """ - if len(self) == 0: + if not self: return [] if c >= 0: @@ -1704,8 +1710,10 @@ def __contains__(self, x): def from_expr(self, expr): """ - Return a :class:`SkewTableau` from a MuPAD-Combinat expr for a skew - tableau. The first list in ``expr`` is the inner shape of the skew + Return a :class:`SkewTableau` from a MuPAD-Combinat expr for + a skew tableau. + + The first list in ``expr`` is the inner shape of the skew tableau. The second list are the entries in the rows of the skew tableau from bottom to top. @@ -1735,7 +1743,7 @@ def from_chain(self, chain): [[None, 1, 2], [None, 3, 4], [5]] """ shape = chain[-1] - T = [[None for _ in range(r)] for r in shape] + T = [[None]*r for r in shape] for i in range(1, len(chain)): la = chain[i] mu = chain[i - 1] @@ -1760,11 +1768,16 @@ def from_shape_and_word(self, shape, word): sage: SkewTableaux().from_shape_and_word(shape, word) [[None, 1, 3], [None, 2], [4]] """ - st = [[None] * row_length for row_length in shape[0]] + outer, inner = shape + st = [[None] * row_length for row_length in outer] w_count = 0 - for i in reversed(range(len(shape[0]))): - for j in range(shape[0][i]): - if i >= len(shape[1]) or j >= shape[1][i]: + for i in reversed(range(len(inner), len(outer))): + for j in range(outer[i]): + st[i][j] = word[w_count] + w_count += 1 + for i in reversed(range(len(inner))): + for j in range(outer[i]): + if j >= inner[i]: st[i][j] = word[w_count] w_count += 1 return self.element_class(self, st) diff --git a/src/sage/combinat/tableau.py b/src/sage/combinat/tableau.py index ab24316debc..294110aeb70 100644 --- a/src/sage/combinat/tableau.py +++ b/src/sage/combinat/tableau.py @@ -175,11 +175,11 @@ class Tableau(ClonableList, metaclass=InheritComparisonClasscallMetaclass): sage: Tableau([[1],[2,3]]) Traceback (most recent call last): ... - ValueError: A tableau must be a list of iterables of weakly decreasing length. + ValueError: a tableau must be a list of iterables of weakly decreasing length sage: Tableau([1,2,3]) Traceback (most recent call last): ... - ValueError: A tableau must be a list of iterables. + ValueError: a tableau must be a list of iterables """ @staticmethod @@ -208,7 +208,7 @@ def __classcall_private__(cls, t): try: t = [tuple(_) for _ in t] except TypeError: - raise ValueError("A tableau must be a list of iterables.") + raise ValueError("a tableau must be a list of iterables") return Tableaux_all().element_class(Tableaux_all(), t) @@ -330,16 +330,16 @@ def check(self): sage: t = Tableau([[None, None, 1], [2, 4], [3, 4, 5]]) # indirect doctest Traceback (most recent call last): ... - ValueError: A tableau must be a list of iterables of weakly decreasing length. + ValueError: a tableau must be a list of iterables of weakly decreasing length """ # Check that it has partition shape. That's all we require from a # general tableau. - lens = [len(_) for _ in self] + lens = [len(row) for row in self] for (a, b) in zip(lens, lens[1:]): if a < b: - raise ValueError("A tableau must be a list of iterables of weakly decreasing length.") + raise ValueError("a tableau must be a list of iterables of weakly decreasing length") if lens and lens[-1] == 0: - raise ValueError("A tableau must not have empty rows.") + raise ValueError("a tableau must not have empty rows") def _repr_(self): """ @@ -4884,7 +4884,8 @@ def from_chain(chain): for j in range(len(chain[i - 1])): for k in range(chain[i - 1][j]): res[j][k] = i -1 - return Tableau(res) + T = Tableaux_all() + return T.element_class(T, res) def from_shape_and_word(shape, w, convention="French"): @@ -4919,7 +4920,7 @@ def from_shape_and_word(shape, w, convention="French"): sage: from_shape_and_word(shape, word) [[1, 3], [2], [4]] sage: word = Word(flatten(t)) - sage: from_shape_and_word(shape, word, convention = "English") + sage: from_shape_and_word(shape, word, convention="English") [[1, 3], [2], [4]] """ res = [] @@ -4927,11 +4928,12 @@ def from_shape_and_word(shape, w, convention="French"): if convention == "French": shape = reversed(shape) for l in shape: - res.append( list(w[j:j+l]) ) + res.append( tuple(w[j:j+l]) ) j += l if convention == "French": res.reverse() - return Tableau(res) + T = Tableaux_all() + return T.element_class(T, res) class IncreasingTableau(Tableau): @@ -5324,7 +5326,7 @@ class Tableaux(UniqueRepresentation, Parent): sage: Tableaux(3)([[1, 1]]) Traceback (most recent call last): ... - ValueError: [[1, 1]] is not an element of Tableaux of size 3. + ValueError: [[1, 1]] is not an element of Tableaux of size 3 sage: t0 = Tableau([[1]]) sage: t1 = Tableaux()([[1]]) @@ -5498,10 +5500,10 @@ def _element_constructor_(self, t): sage: T([[1,2]]) Traceback (most recent call last): ... - ValueError: [[1, 2]] is not an element of Tableaux of size 3. + ValueError: [[1, 2]] is not an element of Tableaux of size 3 """ if t not in self: - raise ValueError("%s is not an element of %s." % (t, self)) + raise ValueError("%s is not an element of %s" % (t, self)) return self.element_class(self, t) @@ -5541,7 +5543,7 @@ def __contains__(self, x): except TypeError: return False # any list of lists of partition shape is a tableau - return [len(_) for _ in x] in _Partitions + return [len(row) for row in x] in _Partitions else: return False diff --git a/src/sage/combinat/tableau_tuple.py b/src/sage/combinat/tableau_tuple.py index 9e8e689ac0f..ac3f23b1375 100644 --- a/src/sage/combinat/tableau_tuple.py +++ b/src/sage/combinat/tableau_tuple.py @@ -346,7 +346,7 @@ class TableauTuple(CombinatorialElement): sage: TableauTuple([[1],[2,3]]) Traceback (most recent call last): ... - ValueError: A tableau must be a list of iterables. + ValueError: a tableau must be a list of iterables sage: TestSuite( TableauTuple([ [[1,2],[3,4]], [[1,2],[3,4]] ]) ).run() sage: TestSuite( TableauTuple([ [[1,2],[3,4]], [], [[1,2],[3,4]] ]) ).run() From 7ce73e69d0042961c557756bbbbf25f4427445e9 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 3 Oct 2021 17:40:39 -0700 Subject: [PATCH 231/359] git grep -l -E 'is_(Real|Complex)(Interval|Ball)Field' | xargs sed -E -i.bak 's/^from sage[.]rings.*import is_((Real|Complex)(Interval|Ball)Field) *$/import sage.rings.abc/;s/is_((Real|Complex)(Interval|Ball)Field)[(]([^)]*)[)]/isinstance(\4, sage.rings.abc.\1)/g;' --- src/sage/rings/complex_interval_field.py | 2 +- src/sage/rings/number_field/number_field.py | 2 +- src/sage/rings/polynomial/polynomial_element.pyx | 8 ++++---- src/sage/rings/qqbar.py | 4 ++-- src/sage/rings/real_interval_absolute.pyx | 2 +- src/sage/rings/real_interval_field.py | 2 +- src/sage/rings/real_mpfi.pyx | 6 +++--- src/sage/symbolic/expression.pyx | 6 +++--- src/sage/symbolic/ring.pyx | 2 +- src/sage/symbolic/subring.py | 2 +- 10 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/sage/rings/complex_interval_field.py b/src/sage/rings/complex_interval_field.py index e046891c437..ff7830505d0 100644 --- a/src/sage/rings/complex_interval_field.py +++ b/src/sage/rings/complex_interval_field.py @@ -49,7 +49,7 @@ from sage.misc.cachefunc import cached_method -def is_ComplexIntervalField(x): +def isinstance(x, sage.rings.abc.ComplexIntervalField): """ Check if ``x`` is a :class:`ComplexIntervalField`. diff --git a/src/sage/rings/number_field/number_field.py b/src/sage/rings/number_field/number_field.py index 3ad7ffa26ef..1752d3fb214 100644 --- a/src/sage/rings/number_field/number_field.py +++ b/src/sage/rings/number_field/number_field.py @@ -9949,7 +9949,7 @@ def hilbert_symbol(self, a, b, P = None): from sage.rings.complex_interval_field import is_ComplexIntervalField from sage.rings.real_mpfr import is_RealField from sage.rings.all import (AA, CDF, QQbar, RDF) - if is_ComplexField(codom) or is_ComplexIntervalField(codom) or \ + if is_ComplexField(codom) or isinstance(codom, sage.rings.abc.ComplexIntervalField) or \ codom is CDF or codom is QQbar: if P(self.gen()).imag() == 0: raise ValueError("Possibly real place (=%s) given as complex embedding in hilbert_symbol. Is it real or complex?" % P) diff --git a/src/sage/rings/polynomial/polynomial_element.pyx b/src/sage/rings/polynomial/polynomial_element.pyx index f7807221d55..0d2cfda744d 100644 --- a/src/sage/rings/polynomial/polynomial_element.pyx +++ b/src/sage/rings/polynomial/polynomial_element.pyx @@ -92,7 +92,7 @@ CC = ComplexField() from sage.rings.real_double import RDF from sage.rings.complex_double import CDF -from sage.rings.real_mpfi import is_RealIntervalField +import sage.rings.abc from sage.structure.coerce cimport coercion_model from sage.structure.element import coerce_binop @@ -8030,7 +8030,7 @@ cdef class Polynomial(CommutativeAlgebraElement): # and complex root isolation and for p-adic factorization if (is_IntegerRing(K) or is_RationalField(K) or is_AlgebraicRealField(K)) and \ - (is_AlgebraicRealField(L) or is_RealIntervalField(L)): + (is_AlgebraicRealField(L) or isinstance(L, sage.rings.abc.RealIntervalField)): from sage.rings.polynomial.real_roots import real_roots @@ -8060,11 +8060,11 @@ cdef class Polynomial(CommutativeAlgebraElement): if (is_IntegerRing(K) or is_RationalField(K) or is_AlgebraicField_common(K) or input_gaussian) and \ - (is_ComplexIntervalField(L) or is_AlgebraicField_common(L)): + (isinstance(L, sage.rings.abc.ComplexIntervalField) or is_AlgebraicField_common(L)): from sage.rings.polynomial.complex_roots import complex_roots - if is_ComplexIntervalField(L): + if isinstance(L, sage.rings.abc.ComplexIntervalField): rts = complex_roots(self, min_prec=L.prec()) elif is_AlgebraicField(L): rts = complex_roots(self, retval='algebraic') diff --git a/src/sage/rings/qqbar.py b/src/sage/rings/qqbar.py index a63315f93b1..a36b5de3c72 100644 --- a/src/sage/rings/qqbar.py +++ b/src/sage/rings/qqbar.py @@ -5013,7 +5013,7 @@ def interval_exact(self, field): sage: (a - b).interval_exact(CIF) 0 """ - if not is_ComplexIntervalField(field): + if not isinstance(field, sage.rings.abc.ComplexIntervalField): raise ValueError("AlgebraicNumber interval_exact requires a ComplexIntervalField") rfld = field._real_field() re = self.real().interval_exact(rfld) @@ -5910,7 +5910,7 @@ def _complex_mpfr_field_(self, field): sage: AA(golden_ratio)._complex_mpfr_field_(ComplexField(100)) 1.6180339887498948482045868344 """ - if is_ComplexIntervalField(field): + if isinstance(field, sage.rings.abc.ComplexIntervalField): return field(self.interval(field._real_field())) else: return field(self.real_number(field._real_field())) diff --git a/src/sage/rings/real_interval_absolute.pyx b/src/sage/rings/real_interval_absolute.pyx index 2b193145eb3..16a275aab2b 100644 --- a/src/sage/rings/real_interval_absolute.pyx +++ b/src/sage/rings/real_interval_absolute.pyx @@ -185,7 +185,7 @@ cdef class RealIntervalAbsoluteField_class(Field): """ if isinstance(R, RealIntervalAbsoluteField_class): return self._absprec < (R)._absprec - elif is_RealIntervalField(R): + elif isinstance(R, sage.rings.abc.RealIntervalField): return True else: return RR_min_prec.has_coerce_map_from(R) diff --git a/src/sage/rings/real_interval_field.py b/src/sage/rings/real_interval_field.py index 97a32ae67cc..8a00d507bc4 100644 --- a/src/sage/rings/real_interval_field.py +++ b/src/sage/rings/real_interval_field.py @@ -7,7 +7,7 @@ from sage.rings.real_mpfi import RealIntervalField_class, RealIntervalFieldElement -def is_RealIntervalField(x): +def isinstance(x, sage.rings.abc.RealIntervalField): """ Check if ``x`` is a :class:`RealIntervalField_class`. diff --git a/src/sage/rings/real_mpfi.pyx b/src/sage/rings/real_mpfi.pyx index ce83e1ddf4e..4bc459f2695 100644 --- a/src/sage/rings/real_mpfi.pyx +++ b/src/sage/rings/real_mpfi.pyx @@ -5317,15 +5317,15 @@ def RealInterval(s, upper=None, int base=10, int pad=0, min_prec=53): # The default real interval field, with precision 53 bits RIF = RealIntervalField() -def is_RealIntervalField(x): +def isinstance(x, sage.rings.abc.RealIntervalField): """ Check if ``x`` is a :class:`RealIntervalField_class`. EXAMPLES:: - sage: sage.rings.real_mpfi.is_RealIntervalField(RIF) + sage: sage.rings.real_mpfi.isinstance(RIF, sage.rings.abc.RealIntervalField) True - sage: sage.rings.real_mpfi.is_RealIntervalField(RealIntervalField(200)) + sage: sage.rings.real_mpfi.isinstance(RealIntervalField(200, sage.rings.abc.RealIntervalField)) True """ return isinstance(x, RealIntervalField_class) diff --git a/src/sage/symbolic/expression.pyx b/src/sage/symbolic/expression.pyx index de4720f90a7..52fa2d2e5a3 100644 --- a/src/sage/symbolic/expression.pyx +++ b/src/sage/symbolic/expression.pyx @@ -3565,8 +3565,8 @@ cdef class Expression(CommutativeRingElement): else: domain = RIF else: - is_interval = (is_RealIntervalField(domain) - or is_ComplexIntervalField(domain) + is_interval = (isinstance(domain, sage.rings.abc.RealIntervalField) + or isinstance(domain, sage.rings.abc.ComplexIntervalField) or is_AlgebraicField(domain) or is_AlgebraicRealField(domain)) zero = domain(0) @@ -3620,7 +3620,7 @@ cdef class Expression(CommutativeRingElement): eq_count += val.contains_zero() except (TypeError, ValueError, ArithmeticError, AttributeError) as ex: errors += 1 - if k == errors > 3 and is_ComplexIntervalField(domain): + if k == errors > 3 and isinstance(domain, sage.rings.abc.ComplexIntervalField): domain = RIF.to_prec(domain.prec()) # we are plugging in random values above, don't be surprised # if something goes wrong... diff --git a/src/sage/symbolic/ring.pyx b/src/sage/symbolic/ring.pyx index ffe8d7443f2..18174ae3212 100644 --- a/src/sage/symbolic/ring.pyx +++ b/src/sage/symbolic/ring.pyx @@ -231,7 +231,7 @@ cdef class SymbolicRing(CommutativeRing): base = R.base_ring() return base is not self and self.has_coerce_map_from(base) elif (R is InfinityRing or R is UnsignedInfinityRing - or is_RealIntervalField(R) or is_ComplexIntervalField(R) + or isinstance(R, sage.rings.abc.RealIntervalField) or isinstance(R, sage.rings.abc.ComplexIntervalField) or isinstance(R, RealBallField) or isinstance(R, ComplexBallField) or is_IntegerModRing(R) or is_FiniteField(R)): diff --git a/src/sage/symbolic/subring.py b/src/sage/symbolic/subring.py index 060ad32a5ed..832d75236bc 100644 --- a/src/sage/symbolic/subring.py +++ b/src/sage/symbolic/subring.py @@ -425,7 +425,7 @@ def _coerce_map_from_(self, P): return True elif (P is InfinityRing or - is_RealIntervalField(P) or is_ComplexIntervalField(P)): + isinstance(P, sage.rings.abc.RealIntervalField) or isinstance(P, sage.rings.abc.ComplexIntervalField)): return True elif P._is_numerical(): From a8432f910c2b61ef4f4e4d681e531e11551d64ea Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 3 Oct 2021 17:50:01 -0700 Subject: [PATCH 232/359] is_{Real,Complex}{Ball,Interval}Field: Undo automatic edits --- src/sage/rings/complex_interval_field.py | 5 ++++- src/sage/rings/real_interval_field.py | 2 +- src/sage/rings/real_mpfi.pyx | 6 +++--- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/sage/rings/complex_interval_field.py b/src/sage/rings/complex_interval_field.py index ff7830505d0..3c37e000154 100644 --- a/src/sage/rings/complex_interval_field.py +++ b/src/sage/rings/complex_interval_field.py @@ -49,7 +49,7 @@ from sage.misc.cachefunc import cached_method -def isinstance(x, sage.rings.abc.ComplexIntervalField): +def is_ComplexIntervalField(x): """ Check if ``x`` is a :class:`ComplexIntervalField`. @@ -61,8 +61,11 @@ def isinstance(x, sage.rings.abc.ComplexIntervalField): sage: is_CIF(CC) False """ + from sage.misc.superseded import deprecation + deprecation(32612, 'is_ComplexIntervalField is deprecated; use isinstance(..., sage.rings.abc.ComplexIntervalField) instead') return isinstance(x, ComplexIntervalField_class) + cache = {} def ComplexIntervalField(prec=53, names=None): """ diff --git a/src/sage/rings/real_interval_field.py b/src/sage/rings/real_interval_field.py index 8a00d507bc4..97a32ae67cc 100644 --- a/src/sage/rings/real_interval_field.py +++ b/src/sage/rings/real_interval_field.py @@ -7,7 +7,7 @@ from sage.rings.real_mpfi import RealIntervalField_class, RealIntervalFieldElement -def isinstance(x, sage.rings.abc.RealIntervalField): +def is_RealIntervalField(x): """ Check if ``x`` is a :class:`RealIntervalField_class`. diff --git a/src/sage/rings/real_mpfi.pyx b/src/sage/rings/real_mpfi.pyx index 4bc459f2695..ce83e1ddf4e 100644 --- a/src/sage/rings/real_mpfi.pyx +++ b/src/sage/rings/real_mpfi.pyx @@ -5317,15 +5317,15 @@ def RealInterval(s, upper=None, int base=10, int pad=0, min_prec=53): # The default real interval field, with precision 53 bits RIF = RealIntervalField() -def isinstance(x, sage.rings.abc.RealIntervalField): +def is_RealIntervalField(x): """ Check if ``x`` is a :class:`RealIntervalField_class`. EXAMPLES:: - sage: sage.rings.real_mpfi.isinstance(RIF, sage.rings.abc.RealIntervalField) + sage: sage.rings.real_mpfi.is_RealIntervalField(RIF) True - sage: sage.rings.real_mpfi.isinstance(RealIntervalField(200, sage.rings.abc.RealIntervalField)) + sage: sage.rings.real_mpfi.is_RealIntervalField(RealIntervalField(200)) True """ return isinstance(x, RealIntervalField_class) From 6209c1fdab2879e042970014628459ccbdda7e7f Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 3 Oct 2021 18:03:22 -0700 Subject: [PATCH 233/359] src/sage/rings/complex_interval_field.py: Add deprecation warning to doctest output --- src/sage/rings/complex_interval_field.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/sage/rings/complex_interval_field.py b/src/sage/rings/complex_interval_field.py index 3c37e000154..05758d9956b 100644 --- a/src/sage/rings/complex_interval_field.py +++ b/src/sage/rings/complex_interval_field.py @@ -56,6 +56,10 @@ def is_ComplexIntervalField(x): EXAMPLES:: sage: from sage.rings.complex_interval_field import is_ComplexIntervalField as is_CIF + doctest:warning... + DeprecationWarning: is_ComplexIntervalField is deprecated; + use isinstance(..., sage.rings.abc.ComplexIntervalField) instead + See https://trac.sagemath.org/32612 for details. sage: is_CIF(CIF) True sage: is_CIF(CC) From 5cb3d59d6724546ff37e3329cd28fe239e95fb5a Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 3 Oct 2021 18:04:23 -0700 Subject: [PATCH 234/359] Fix imports, consolidate isinstance calls --- src/sage/rings/number_field/number_field.py | 1 - src/sage/symbolic/expression.pyx | 4 ++-- src/sage/symbolic/ring.pyx | 7 ++++--- src/sage/symbolic/subring.py | 6 +++--- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/sage/rings/number_field/number_field.py b/src/sage/rings/number_field/number_field.py index 1752d3fb214..d6694f1bb9a 100644 --- a/src/sage/rings/number_field/number_field.py +++ b/src/sage/rings/number_field/number_field.py @@ -9946,7 +9946,6 @@ def hilbert_symbol(self, a, b, P = None): raise ValueError("Domain of P (=%s) should be self (=%s) in self.hilbert_symbol" % (P, self)) codom = P.codomain() from sage.rings.complex_mpfr import is_ComplexField - from sage.rings.complex_interval_field import is_ComplexIntervalField from sage.rings.real_mpfr import is_RealField from sage.rings.all import (AA, CDF, QQbar, RDF) if is_ComplexField(codom) or isinstance(codom, sage.rings.abc.ComplexIntervalField) or \ diff --git a/src/sage/symbolic/expression.pyx b/src/sage/symbolic/expression.pyx index 52fa2d2e5a3..0d2d194560c 100644 --- a/src/sage/symbolic/expression.pyx +++ b/src/sage/symbolic/expression.pyx @@ -3565,8 +3565,8 @@ cdef class Expression(CommutativeRingElement): else: domain = RIF else: - is_interval = (isinstance(domain, sage.rings.abc.RealIntervalField) - or isinstance(domain, sage.rings.abc.ComplexIntervalField) + is_interval = (isinstance(domain, (sage.rings.abc.RealIntervalField, + sage.rings.abc.ComplexIntervalField)) or is_AlgebraicField(domain) or is_AlgebraicRealField(domain)) zero = domain(0) diff --git a/src/sage/symbolic/ring.pyx b/src/sage/symbolic/ring.pyx index 18174ae3212..d0022b060d9 100644 --- a/src/sage/symbolic/ring.pyx +++ b/src/sage/symbolic/ring.pyx @@ -231,9 +231,10 @@ cdef class SymbolicRing(CommutativeRing): base = R.base_ring() return base is not self and self.has_coerce_map_from(base) elif (R is InfinityRing or R is UnsignedInfinityRing - or isinstance(R, sage.rings.abc.RealIntervalField) or isinstance(R, sage.rings.abc.ComplexIntervalField) - or isinstance(R, RealBallField) - or isinstance(R, ComplexBallField) + or isinstance(R, (sage.rings.abc.RealIntervalField, + sage.rings.abc.ComplexIntervalField, + sage.rings.abc.RealBallField, + sage.rings.abc.ComplexBallField)) or is_IntegerModRing(R) or is_FiniteField(R)): return True elif isinstance(R, GenericSymbolicSubring): diff --git a/src/sage/symbolic/subring.py b/src/sage/symbolic/subring.py index 832d75236bc..c1eb48e16ae 100644 --- a/src/sage/symbolic/subring.py +++ b/src/sage/symbolic/subring.py @@ -97,6 +97,7 @@ # http://www.gnu.org/licenses/ #***************************************************************************** +import sage.rings.abc from .ring import SymbolicRing, SR from sage.categories.pushout import ConstructionFunctor from sage.structure.factory import UniqueFactory @@ -412,8 +413,6 @@ def _coerce_map_from_(self, P): return False from sage.rings.all import RLF, CLF, AA, QQbar, InfinityRing - from sage.rings.real_mpfi import is_RealIntervalField - from sage.rings.complex_interval_field import is_ComplexIntervalField if isinstance(P, type): return SR._coerce_map_from_(P) @@ -425,7 +424,8 @@ def _coerce_map_from_(self, P): return True elif (P is InfinityRing or - isinstance(P, sage.rings.abc.RealIntervalField) or isinstance(P, sage.rings.abc.ComplexIntervalField)): + isinstance(P, (sage.rings.abc.RealIntervalField, + sage.rings.abc.ComplexIntervalField))): return True elif P._is_numerical(): From be1db022c9bb35ca0875a5c7bdd8a99ede246d97 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 3 Oct 2021 19:32:26 -0700 Subject: [PATCH 235/359] src/sage/rings/abc.pxd: Add cdef class RealIntervalField --- src/sage/rings/abc.pxd | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/sage/rings/abc.pxd b/src/sage/rings/abc.pxd index ea998549070..5b2aec37eff 100644 --- a/src/sage/rings/abc.pxd +++ b/src/sage/rings/abc.pxd @@ -5,6 +5,11 @@ cdef class RealField(Field): pass +cdef class RealIntervalField(Field): + + pass + + cdef class RealDoubleField(Field): pass From 7e7f5fe8ddc7c10308584579701b556f8a13ddac Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 3 Oct 2021 19:36:58 -0700 Subject: [PATCH 236/359] sage.doctest.forker: Use sage.misc.lazy_import.ensure_startup_finished --- src/sage/doctest/forker.py | 5 +++++ src/sage/misc/lazy_import.pyx | 28 ++++++++++++++++++++++++++-- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/sage/doctest/forker.py b/src/sage/doctest/forker.py index 960429a8ed0..f7fe607eadf 100644 --- a/src/sage/doctest/forker.py +++ b/src/sage/doctest/forker.py @@ -2496,6 +2496,11 @@ def _run(self, runner, options, results): from importlib import import_module sage_all = import_module(options.environment) dict_all = sage_all.__dict__ + # When using global environments other than sage.all, + # make sure startup is finished so we don't get "Resolving lazy import" + # warnings. + from sage.misc.lazy_import import ensure_startup_finished + ensure_startup_finished() # Remove '__package__' item from the globals since it is not # always in the globals in an actual Sage session. dict_all.pop('__package__', None) diff --git a/src/sage/misc/lazy_import.pyx b/src/sage/misc/lazy_import.pyx index 7e8b731965a..50a3bb325d4 100644 --- a/src/sage/misc/lazy_import.pyx +++ b/src/sage/misc/lazy_import.pyx @@ -79,11 +79,15 @@ cdef inline obj(x): # boolean to determine whether Sage is still starting up cdef bint startup_guard = True +cdef bint finish_startup_called = False + cpdef finish_startup(): """ + Finish the startup phase. + This function must be called exactly once at the end of the Sage - import process + import process (:mod:`~sage.all`). TESTS:: @@ -96,6 +100,24 @@ cpdef finish_startup(): global startup_guard assert startup_guard, 'finish_startup() must be called exactly once' startup_guard = False + finish_startup_called = True + + +cpdef ensure_startup_finished(): + """ + Make sure that the startup phase is finished. + + In contrast to :func:`finish_startup`, this function can + be called repeatedly. + + TESTS:: + + sage: from sage.misc.lazy_import import ensure_startup_finished + sage: ensure_startup_finished() + """ + global startup_guard + startup_guard = False + cpdef bint is_during_startup(): """ @@ -114,6 +136,7 @@ cpdef bint is_during_startup(): global startup_guard return startup_guard + cpdef test_fake_startup(): """ For testing purposes only. @@ -218,7 +241,8 @@ cdef class LazyImport(object): if startup_guard and not self._at_startup: print(f"Resolving lazy import {self._name} during startup") elif self._at_startup and not startup_guard: - print(f"Option ``at_startup=True`` for lazy import {self._name} not needed anymore") + if finish_startup_called: + print(f"Option ``at_startup=True`` for lazy import {self._name} not needed anymore") try: self._object = getattr(__import__(self._module, {}, {}, [self._name]), self._name) From 181e4a00604d7ec5d4653acc9783738779dc8105 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 3 Oct 2021 19:39:25 -0700 Subject: [PATCH 237/359] src/sage/misc/lazy_import.pyx: Use warnings.warn instead of print --- src/sage/misc/lazy_import.pyx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/sage/misc/lazy_import.pyx b/src/sage/misc/lazy_import.pyx index 50a3bb325d4..880cf80352c 100644 --- a/src/sage/misc/lazy_import.pyx +++ b/src/sage/misc/lazy_import.pyx @@ -63,6 +63,7 @@ cdef extern from *: import os import pickle +from warnings import warn import inspect from . import sageinspect @@ -239,10 +240,10 @@ cdef class LazyImport(object): return self._object if startup_guard and not self._at_startup: - print(f"Resolving lazy import {self._name} during startup") + warn(f"Resolving lazy import {self._name} during startup") elif self._at_startup and not startup_guard: if finish_startup_called: - print(f"Option ``at_startup=True`` for lazy import {self._name} not needed anymore") + warn(f"Option ``at_startup=True`` for lazy import {self._name} not needed anymore") try: self._object = getattr(__import__(self._module, {}, {}, [self._name]), self._name) From 13607cb249da2bdedaee511a7741b744bd439ca6 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 3 Oct 2021 19:43:01 -0700 Subject: [PATCH 238/359] src/sage/dynamics/arithmetic_dynamics/projective_ds.py: Remove unused import --- src/sage/dynamics/arithmetic_dynamics/projective_ds.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py index 3c56fd3885b..96df43c2d8d 100644 --- a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py +++ b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py @@ -80,7 +80,6 @@ class initialization directly. from sage.rings.polynomial.flatten import FlatteningMorphism, UnflatteningMorphism from sage.rings.morphism import RingHomomorphism_im_gens from sage.rings.number_field.number_field_ideal import NumberFieldFractionalIdeal -from sage.rings.number_field.number_field import is_NumberField from sage.rings.padics.all import Qp from sage.rings.polynomial.multi_polynomial_ring_base import is_MPolynomialRing from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing From 271e04420c0868f1d9630e7c3feb68b2c83003c7 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 3 Oct 2021 20:55:33 -0700 Subject: [PATCH 239/359] src/sage/rings/real_interval_absolute.pyx: Fix imports --- src/sage/rings/real_interval_absolute.pyx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/sage/rings/real_interval_absolute.pyx b/src/sage/rings/real_interval_absolute.pyx index 16a275aab2b..7b39d84b5fa 100644 --- a/src/sage/rings/real_interval_absolute.pyx +++ b/src/sage/rings/real_interval_absolute.pyx @@ -10,12 +10,13 @@ from sage.structure.factory import UniqueFactory from sage.structure.element cimport RingElement, ModuleElement, Element, FieldElement from sage.rings.ring cimport Field from sage.rings.integer cimport Integer +import sage.rings.abc from sage.structure.parent cimport Parent from sage.structure.element cimport parent from sage.rings.real_mpfr import RR_min_prec -from sage.rings.real_mpfi import RealIntervalField, RealIntervalFieldElement, is_RealIntervalField +from sage.rings.real_mpfi import RealIntervalField, RealIntervalFieldElement from sage.rings.rational_field import QQ cdef Integer zero = Integer(0) From fc039f12c354c9f0c3cb55373bcabaa897500e91 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 3 Oct 2021 20:57:07 -0700 Subject: [PATCH 240/359] src/sage/symbolic/ring.pyx: Fix imports --- src/sage/symbolic/ring.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/symbolic/ring.pyx b/src/sage/symbolic/ring.pyx index d0022b060d9..7e899398a9b 100644 --- a/src/sage/symbolic/ring.pyx +++ b/src/sage/symbolic/ring.pyx @@ -32,6 +32,7 @@ The symbolic ring # **************************************************************************** from sage.rings.integer cimport Integer +import sage.rings.abc from sage.symbolic.expression cimport ( is_Expression, @@ -207,7 +208,6 @@ cdef class SymbolicRing(CommutativeRing): from sage.rings.fraction_field import is_FractionField from sage.rings.finite_rings.integer_mod_ring import is_IntegerModRing from sage.rings.real_mpfi import is_RealIntervalField - from sage.rings.complex_interval_field import is_ComplexIntervalField from sage.rings.real_arb import RealBallField from sage.rings.complex_arb import ComplexBallField from sage.rings.polynomial.polynomial_ring import is_PolynomialRing From f7e07bf5cdebaef88504d15169c45d7b8a43c285 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 3 Oct 2021 21:43:06 -0700 Subject: [PATCH 241/359] git grep -l 'all import ZZ' src/sage | xargs sed -E -i.bak $'s/^( *)from sage.*all import (ZZ, QQ|QQ, ZZ) *$/\1from sage.rings.integer_ring import ZZ\\n\1from sage.rings.rational_field import QQ/' --- src/sage/algebras/lie_algebras/verma_module.py | 3 ++- src/sage/algebras/schur_algebra.py | 3 ++- src/sage/combinat/derangements.py | 3 ++- src/sage/combinat/descent_algebra.py | 3 ++- src/sage/combinat/diagram_algebras.py | 3 ++- src/sage/combinat/dyck_word.py | 3 ++- src/sage/combinat/ncsf_qsym/qsym.py | 3 ++- src/sage/combinat/partition_algebra.py | 3 ++- src/sage/combinat/root_system/ambient_space.py | 3 ++- src/sage/combinat/root_system/plot.py | 3 ++- .../combinat/root_system/reflection_group_complex.py | 3 ++- .../root_system/reflection_group_element.pyx | 3 ++- .../root_system/root_lattice_realizations.py | 3 ++- src/sage/combinat/root_system/root_system.py | 3 ++- src/sage/combinat/root_system/weyl_group.py | 3 ++- src/sage/combinat/skew_partition.py | 3 ++- src/sage/groups/additive_abelian/qmodnz.py | 3 ++- src/sage/libs/linkages/padics/Polynomial_shared.pxi | 3 ++- src/sage/matroids/constructor.py | 3 ++- src/sage/modular/abvar/morphism.py | 3 ++- src/sage/modular/hecke/algebra.py | 3 ++- src/sage/modular/pollack_stevens/padic_lseries.py | 3 ++- src/sage/rings/number_field/totallyreal.pyx | 3 ++- src/sage/rings/number_field/totallyreal_rel.py | 3 ++- src/sage/rings/padics/padic_valuation.py | 12 ++++++++---- src/sage/schemes/affine/affine_rational_point.py | 3 ++- src/sage/schemes/elliptic_curves/isogeny_class.py | 3 ++- .../schemes/elliptic_curves/isogeny_small_degree.py | 3 ++- src/sage/schemes/toric/ideal.py | 3 ++- src/sage/schemes/toric/library.py | 3 ++- 30 files changed, 66 insertions(+), 33 deletions(-) diff --git a/src/sage/algebras/lie_algebras/verma_module.py b/src/sage/algebras/lie_algebras/verma_module.py index 9c9fdca0147..730714b0bb3 100644 --- a/src/sage/algebras/lie_algebras/verma_module.py +++ b/src/sage/algebras/lie_algebras/verma_module.py @@ -31,7 +31,8 @@ from sage.modules.free_module_element import vector from sage.sets.family import Family from sage.structure.richcmp import richcmp -from sage.rings.all import ZZ, QQ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ class VermaModule(CombinatorialFreeModule): diff --git a/src/sage/algebras/schur_algebra.py b/src/sage/algebras/schur_algebra.py index 2d7af71b6f6..08b921ea160 100644 --- a/src/sage/algebras/schur_algebra.py +++ b/src/sage/algebras/schur_algebra.py @@ -45,7 +45,8 @@ from sage.matrix.constructor import Matrix from sage.misc.cachefunc import cached_method from sage.misc.flatten import flatten -from sage.rings.all import ZZ, QQ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ def _schur_I_nr_representatives(n, r): diff --git a/src/sage/combinat/derangements.py b/src/sage/combinat/derangements.py index 4ad088c9575..4640798c7dc 100644 --- a/src/sage/combinat/derangements.py +++ b/src/sage/combinat/derangements.py @@ -29,7 +29,8 @@ from sage.misc.all import prod from sage.misc.prandom import random, randrange from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing -from sage.rings.all import ZZ, QQ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ from sage.rings.integer import Integer from sage.combinat.combinat import CombinatorialElement from sage.combinat.permutation import Permutation, Permutations diff --git a/src/sage/combinat/descent_algebra.py b/src/sage/combinat/descent_algebra.py index bff1e214ee5..8d2678bc518 100644 --- a/src/sage/combinat/descent_algebra.py +++ b/src/sage/combinat/descent_algebra.py @@ -20,7 +20,8 @@ from sage.categories.algebras import Algebras from sage.categories.realizations import Realizations, Category_realization_of_parent from sage.categories.all import FiniteDimensionalAlgebrasWithBasis -from sage.rings.all import ZZ, QQ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ from sage.arith.misc import factorial from sage.combinat.free_module import CombinatorialFreeModule from sage.combinat.permutation import Permutations diff --git a/src/sage/combinat/diagram_algebras.py b/src/sage/combinat/diagram_algebras.py index 1f7dfef039d..17a9f85bc5f 100644 --- a/src/sage/combinat/diagram_algebras.py +++ b/src/sage/combinat/diagram_algebras.py @@ -41,7 +41,8 @@ from sage.misc.lazy_attribute import lazy_attribute from sage.misc.flatten import flatten from sage.misc.misc_c import prod -from sage.rings.all import ZZ, QQ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ from sage.functions.other import floor, ceil import itertools diff --git a/src/sage/combinat/dyck_word.py b/src/sage/combinat/dyck_word.py index 10f8a588a8b..4eb3cebf1b4 100644 --- a/src/sage/combinat/dyck_word.py +++ b/src/sage/combinat/dyck_word.py @@ -91,7 +91,8 @@ from sage.categories.infinite_enumerated_sets import InfiniteEnumeratedSets from sage.categories.all import Posets -from sage.rings.all import ZZ, QQ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ from sage.combinat.permutation import Permutation, Permutations from sage.combinat.words.word import Word from sage.combinat.alternating_sign_matrix import AlternatingSignMatrices diff --git a/src/sage/combinat/ncsf_qsym/qsym.py b/src/sage/combinat/ncsf_qsym/qsym.py index f76f1891ad3..a13e4acf51e 100644 --- a/src/sage/combinat/ncsf_qsym/qsym.py +++ b/src/sage/combinat/ncsf_qsym/qsym.py @@ -1908,7 +1908,8 @@ def lambda_of_monomial(self, I, n): # The following algorithm is a rewriting of the formula in the docstring. # We are working over QQ because there are denominators which don't # immediately cancel. - from sage.rings.all import ZZ, QQ + from sage.rings.integer_ring import ZZ + from sage.rings.rational_field import QQ QQM = QuasiSymmetricFunctions(QQ).M() QQ_result = QQM.zero() for lam in Partitions(n): diff --git a/src/sage/combinat/partition_algebra.py b/src/sage/combinat/partition_algebra.py index 9a6869b0de2..a820494f388 100644 --- a/src/sage/combinat/partition_algebra.py +++ b/src/sage/combinat/partition_algebra.py @@ -23,7 +23,8 @@ from sage.graphs.graph import Graph from sage.arith.all import factorial, binomial from .permutation import Permutations -from sage.rings.all import ZZ, QQ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ from .subset import Subsets from sage.functions.all import ceil diff --git a/src/sage/combinat/root_system/ambient_space.py b/src/sage/combinat/root_system/ambient_space.py index e1d4adea0ea..c55646e94ce 100644 --- a/src/sage/combinat/root_system/ambient_space.py +++ b/src/sage/combinat/root_system/ambient_space.py @@ -11,7 +11,8 @@ from sage.misc.cachefunc import cached_method from sage.combinat.free_module import CombinatorialFreeModule from .weight_lattice_realizations import WeightLatticeRealizations -from sage.rings.all import ZZ, QQ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ from sage.categories.homset import End diff --git a/src/sage/combinat/root_system/plot.py b/src/sage/combinat/root_system/plot.py index 5e8ee505465..36da0e98384 100644 --- a/src/sage/combinat/root_system/plot.py +++ b/src/sage/combinat/root_system/plot.py @@ -809,7 +809,8 @@ from sage.misc.lazy_import import lazy_import from sage.structure.element import parent from sage.modules.free_module_element import vector -from sage.rings.all import ZZ, QQ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ from sage.combinat.root_system.cartan_type import CartanType lazy_import("sage.combinat.root_system.root_lattice_realizations", "RootLatticeRealizations") diff --git a/src/sage/combinat/root_system/reflection_group_complex.py b/src/sage/combinat/root_system/reflection_group_complex.py index 5f769683634..f66ff07ab5c 100644 --- a/src/sage/combinat/root_system/reflection_group_complex.py +++ b/src/sage/combinat/root_system/reflection_group_complex.py @@ -205,7 +205,8 @@ from sage.sets.family import Family from sage.structure.unique_representation import UniqueRepresentation from sage.groups.perm_gps.permgroup import PermutationGroup_generic -from sage.rings.all import ZZ, QQ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ from sage.matrix.all import Matrix, identity_matrix from sage.structure.element import is_Matrix from sage.interfaces.gap3 import gap3 diff --git a/src/sage/combinat/root_system/reflection_group_element.pyx b/src/sage/combinat/root_system/reflection_group_element.pyx index 157c74e18dd..bd96e4297c3 100644 --- a/src/sage/combinat/root_system/reflection_group_element.pyx +++ b/src/sage/combinat/root_system/reflection_group_element.pyx @@ -27,7 +27,8 @@ from sage.misc.lazy_attribute import lazy_attribute from sage.misc.misc_c import prod from sage.arith.functions import lcm from sage.combinat.root_system.cartan_type import CartanType, CartanType_abstract -from sage.rings.all import ZZ, QQ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ from sage.interfaces.gap3 import gap3 from sage.combinat.root_system.cartan_matrix import CartanMatrix from sage.misc.sage_eval import sage_eval diff --git a/src/sage/combinat/root_system/root_lattice_realizations.py b/src/sage/combinat/root_system/root_lattice_realizations.py index 1eaf908e63c..95301036614 100644 --- a/src/sage/combinat/root_system/root_lattice_realizations.py +++ b/src/sage/combinat/root_system/root_lattice_realizations.py @@ -22,7 +22,8 @@ from sage.categories.modules_with_basis import ModulesWithBasis from sage.structure.element import Element from sage.sets.family import Family -from sage.rings.all import ZZ, QQ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ from sage.matrix.constructor import matrix from sage.modules.free_module_element import vector from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet diff --git a/src/sage/combinat/root_system/root_system.py b/src/sage/combinat/root_system/root_system.py index 628afb34833..9285d9b958b 100644 --- a/src/sage/combinat/root_system/root_system.py +++ b/src/sage/combinat/root_system/root_system.py @@ -18,7 +18,8 @@ from sage.structure.sage_object import SageObject from sage.structure.unique_representation import UniqueRepresentation from .cartan_type import CartanType -from sage.rings.all import ZZ, QQ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ from sage.misc.all import cached_method from .root_space import RootSpace from .weight_space import WeightSpace diff --git a/src/sage/combinat/root_system/weyl_group.py b/src/sage/combinat/root_system/weyl_group.py index e546d399274..f5b693f1313 100644 --- a/src/sage/combinat/root_system/weyl_group.py +++ b/src/sage/combinat/root_system/weyl_group.py @@ -40,7 +40,8 @@ from sage.groups.matrix_gps.finitely_generated import FinitelyGeneratedMatrixGroup_gap from sage.groups.matrix_gps.group_element import MatrixGroupElement_gap from sage.groups.perm_gps.permgroup import PermutationGroup_generic -from sage.rings.all import ZZ, QQ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ from sage.interfaces.gap import gap from sage.misc.cachefunc import cached_method from sage.combinat.root_system.cartan_type import CartanType diff --git a/src/sage/combinat/skew_partition.py b/src/sage/combinat/skew_partition.py index 9be0a9b6237..585e1802c74 100644 --- a/src/sage/combinat/skew_partition.py +++ b/src/sage/combinat/skew_partition.py @@ -148,7 +148,8 @@ from sage.categories.infinite_enumerated_sets import InfiniteEnumeratedSets from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets -from sage.rings.all import ZZ, QQ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ from sage.sets.set import Set from sage.graphs.digraph import DiGraph from sage.matrix.matrix_space import MatrixSpace diff --git a/src/sage/groups/additive_abelian/qmodnz.py b/src/sage/groups/additive_abelian/qmodnz.py index 344344234a6..6fdb3838fd2 100644 --- a/src/sage/groups/additive_abelian/qmodnz.py +++ b/src/sage/groups/additive_abelian/qmodnz.py @@ -31,7 +31,8 @@ from sage.structure.parent import Parent from sage.structure.unique_representation import UniqueRepresentation -from sage.rings.all import ZZ, QQ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ from sage.categories.commutative_additive_groups import CommutativeAdditiveGroups from .qmodnz_element import QmodnZ_Element diff --git a/src/sage/libs/linkages/padics/Polynomial_shared.pxi b/src/sage/libs/linkages/padics/Polynomial_shared.pxi index 7c66463ac12..738ab9bf457 100644 --- a/src/sage/libs/linkages/padics/Polynomial_shared.pxi +++ b/src/sage/libs/linkages/padics/Polynomial_shared.pxi @@ -29,7 +29,8 @@ AUTHORS: from cpython.list cimport * from sage.rings.integer cimport Integer from sage.rings.rational cimport Rational -from sage.rings.all import ZZ, QQ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ from sage.ext.stdsage cimport PY_NEW from copy import copy from sage.rings.padics.common_conversion cimport cconv_mpz_t_out_shared, cconv_mpz_t_shared, cconv_mpq_t_out_shared, cconv_mpq_t_shared, cconv_shared diff --git a/src/sage/matroids/constructor.py b/src/sage/matroids/constructor.py index 8fc0a44957a..1e2a85ff6bc 100644 --- a/src/sage/matroids/constructor.py +++ b/src/sage/matroids/constructor.py @@ -105,7 +105,8 @@ from sage.matrix.constructor import Matrix from sage.graphs.all import Graph from sage.structure.element import is_Matrix -from sage.rings.all import ZZ, QQ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ from sage.categories.all import Fields, Rings from sage.rings.finite_rings.finite_field_base import FiniteField import sage.matroids.matroid diff --git a/src/sage/modular/abvar/morphism.py b/src/sage/modular/abvar/morphism.py index 99bbd68af9d..386561a1b02 100644 --- a/src/sage/modular/abvar/morphism.py +++ b/src/sage/modular/abvar/morphism.py @@ -40,7 +40,8 @@ ########################################################################### from sage.categories.morphism import Morphism as base_Morphism -from sage.rings.all import ZZ, QQ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ import sage.modules.matrix_morphism import sage.matrix.matrix_space as matrix_space diff --git a/src/sage/modular/hecke/algebra.py b/src/sage/modular/hecke/algebra.py index 2e8506d4599..ffd6364c8bc 100644 --- a/src/sage/modular/hecke/algebra.py +++ b/src/sage/modular/hecke/algebra.py @@ -32,7 +32,8 @@ from sage.arith.all import lcm, gcd from sage.misc.latex import latex from sage.matrix.matrix_space import MatrixSpace -from sage.rings.all import ZZ, QQ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ from sage.structure.element import Element from sage.structure.unique_representation import CachedRepresentation from sage.misc.cachefunc import cached_method diff --git a/src/sage/modular/pollack_stevens/padic_lseries.py b/src/sage/modular/pollack_stevens/padic_lseries.py index 5dd019eee93..4a3beb12fdf 100644 --- a/src/sage/modular/pollack_stevens/padic_lseries.py +++ b/src/sage/modular/pollack_stevens/padic_lseries.py @@ -21,7 +21,8 @@ # **************************************************************************** from sage.rings.padics.all import pAdicField -from sage.rings.all import ZZ, QQ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ from sage.rings.power_series_ring import PowerSeriesRing from sage.arith.all import binomial, kronecker from sage.rings.padics.precision_error import PrecisionError diff --git a/src/sage/rings/number_field/totallyreal.pyx b/src/sage/rings/number_field/totallyreal.pyx index 0512f0559fc..3841146b7a7 100644 --- a/src/sage/rings/number_field/totallyreal.pyx +++ b/src/sage/rings/number_field/totallyreal.pyx @@ -105,7 +105,8 @@ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing from sage.rings.integer import Integer from sage.rings.integer cimport Integer from sage.rings.integer_ring import IntegerRing -from sage.rings.all import ZZ, QQ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ from sage.misc.misc import cputime from sage.rings.number_field.totallyreal_data import tr_data, int_has_small_square_divisor diff --git a/src/sage/rings/number_field/totallyreal_rel.py b/src/sage/rings/number_field/totallyreal_rel.py index e531dcaa126..f5061ff7b36 100644 --- a/src/sage/rings/number_field/totallyreal_rel.py +++ b/src/sage/rings/number_field/totallyreal_rel.py @@ -98,7 +98,8 @@ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing from sage.rings.number_field.totallyreal import weed_fields, odlyzko_bound_totallyreal, enumerate_totallyreal_fields_prim from sage.libs.pari.all import pari -from sage.rings.all import ZZ, QQ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ import math import sys diff --git a/src/sage/rings/padics/padic_valuation.py b/src/sage/rings/padics/padic_valuation.py index f47f1d8de5b..3aaa77b1d6f 100644 --- a/src/sage/rings/padics/padic_valuation.py +++ b/src/sage/rings/padics/padic_valuation.py @@ -119,7 +119,8 @@ def create_key_and_extra_args(self, R, prime=None, approximants=None): 2-adic valuation """ - from sage.rings.all import ZZ, QQ + from sage.rings.integer_ring import ZZ + from sage.rings.rational_field import QQ from sage.rings.padics.padic_generic import pAdicGeneric from sage.rings.number_field.number_field import is_NumberField from sage.rings.polynomial.polynomial_quotient_ring import is_PolynomialQuotientRing @@ -389,7 +390,8 @@ def create_object(self, version, key, **extra_args): 5-adic valuation """ - from sage.rings.all import ZZ, QQ + from sage.rings.integer_ring import ZZ + from sage.rings.rational_field import QQ from sage.rings.padics.padic_generic import pAdicGeneric from sage.rings.valuation.valuation_space import DiscretePseudoValuationSpace from sage.rings.polynomial.polynomial_quotient_ring import is_PolynomialQuotientRing @@ -956,7 +958,8 @@ def element_with_valuation(self, v): y^3 + O(y^43) """ - from sage.rings.all import QQ, ZZ + from sage.rings.integer_ring import ZZ + from sage.rings.rational_field import QQ v = QQ(v) if v not in self.value_semigroup(): raise ValueError("%r is not in the value semigroup of %r"%(v, self)) @@ -1327,7 +1330,8 @@ def inverse(self, x, precision): if self(x) > 0 or precision is infinity: raise ValueError("element has no approximate inverse in this ring") - from sage.rings.all import ZZ, QQ + from sage.rings.integer_ring import ZZ + from sage.rings.rational_field import QQ return self.domain()(ZZ(x).inverse_mod(self.p() ** QQ(precision).ceil())) diff --git a/src/sage/schemes/affine/affine_rational_point.py b/src/sage/schemes/affine/affine_rational_point.py index 122103dacc4..513b5d67aa0 100644 --- a/src/sage/schemes/affine/affine_rational_point.py +++ b/src/sage/schemes/affine/affine_rational_point.py @@ -51,7 +51,8 @@ # http://www.gnu.org/licenses/ #***************************************************************************** -from sage.rings.all import ZZ, QQ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ from sage.misc.all import cartesian_product_iterator from sage.schemes.generic.scheme import is_Scheme diff --git a/src/sage/schemes/elliptic_curves/isogeny_class.py b/src/sage/schemes/elliptic_curves/isogeny_class.py index 94d99a82ec5..174359868b3 100644 --- a/src/sage/schemes/elliptic_curves/isogeny_class.py +++ b/src/sage/schemes/elliptic_curves/isogeny_class.py @@ -28,7 +28,8 @@ from sage.structure.sage_object import SageObject from sage.structure.richcmp import richcmp_method, richcmp import sage.databases.cremona -from sage.rings.all import ZZ, QQ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ from sage.misc.all import flatten, cached_method from sage.schemes.elliptic_curves.ell_field import EllipticCurve_field from sage.schemes.elliptic_curves.ell_number_field import EllipticCurve_number_field diff --git a/src/sage/schemes/elliptic_curves/isogeny_small_degree.py b/src/sage/schemes/elliptic_curves/isogeny_small_degree.py index d5e08668737..58bfc0fb5b8 100644 --- a/src/sage/schemes/elliptic_curves/isogeny_small_degree.py +++ b/src/sage/schemes/elliptic_curves/isogeny_small_degree.py @@ -32,7 +32,8 @@ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing from sage.rings.polynomial.polynomial_ring import polygen -from sage.rings.all import ZZ, QQ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ from sage.schemes.elliptic_curves.all import EllipticCurve from sage.misc.cachefunc import cached_function diff --git a/src/sage/schemes/toric/ideal.py b/src/sage/schemes/toric/ideal.py index fc0c5ecde5c..20681b39896 100644 --- a/src/sage/schemes/toric/ideal.py +++ b/src/sage/schemes/toric/ideal.py @@ -135,7 +135,8 @@ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing from sage.misc.misc_c import prod from sage.matrix.constructor import matrix -from sage.rings.all import ZZ, QQ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ from sage.rings.polynomial.multi_polynomial_ideal import MPolynomialIdeal diff --git a/src/sage/schemes/toric/library.py b/src/sage/schemes/toric/library.py index 7de2cd950bc..7b3509c2132 100644 --- a/src/sage/schemes/toric/library.py +++ b/src/sage/schemes/toric/library.py @@ -42,7 +42,8 @@ from sage.matrix.all import matrix, identity_matrix from sage.geometry.all import Fan, LatticePolytope, ToricLattice -from sage.rings.all import ZZ, QQ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ from sage.arith.all import gcd from sage.schemes.toric.variety import (DEFAULT_PREFIX, ToricVariety, From acf7ae99825035ec3b5f0262c8d1c5c5124fdde0 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 3 Oct 2021 21:44:13 -0700 Subject: [PATCH 242/359] git grep -l 'all import ZZ' src/sage | xargs sed -E -i.bak $'s/^( *)from sage.*all import ZZ *$/\1from sage.rings.integer_ring import ZZ/' --- src/sage/interfaces/qepcad.py | 2 +- src/sage/interfaces/singular.py | 2 +- src/sage/quivers/path_semigroup.py | 2 +- src/sage/rings/pari_ring.py | 2 +- src/sage/rings/polynomial/term_order.py | 2 +- src/sage/rings/tests.py | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/sage/interfaces/qepcad.py b/src/sage/interfaces/qepcad.py index 29baa767b4e..3007961aad6 100644 --- a/src/sage/interfaces/qepcad.py +++ b/src/sage/interfaces/qepcad.py @@ -2253,7 +2253,7 @@ def exactly_k(self, k, v, formula, allow_multi=False): sage: qf.exactly_k(0, b, a*b == 1) (A b)[~a b = 1] """ - from sage.all import ZZ + from sage.rings.integer_ring import ZZ k = ZZ(k) if k < 0: raise ValueError("negative k in exactly_k quantifier") diff --git a/src/sage/interfaces/singular.py b/src/sage/interfaces/singular.py index d9c0a90fb08..35dfd02c88b 100644 --- a/src/sage/interfaces/singular.py +++ b/src/sage/interfaces/singular.py @@ -1608,7 +1608,7 @@ def sage_global_ring(self): # extract the ring of coefficients singular = self.parent() charstr = singular.eval('charstr(basering)').split(',',1) - from sage.all import ZZ + from sage.rings.integer_ring import ZZ is_extension = len(charstr)==2 if charstr[0] in ['integer', 'ZZ']: br = ZZ diff --git a/src/sage/quivers/path_semigroup.py b/src/sage/quivers/path_semigroup.py index 7426132d4ec..d4e05928d85 100644 --- a/src/sage/quivers/path_semigroup.py +++ b/src/sage/quivers/path_semigroup.py @@ -543,7 +543,7 @@ def cardinality(self): ... ValueError: the underlying quiver has cycles, thus, there may be an infinity of directed paths """ - from sage.all import ZZ + from sage.rings.integer_ring import ZZ if self._quiver.is_directed_acyclic() and not self._quiver.has_loops(): return ZZ(len(self)) from sage.rings.infinity import Infinity diff --git a/src/sage/rings/pari_ring.py b/src/sage/rings/pari_ring.py index 17e5f161473..c46fceed07b 100644 --- a/src/sage/rings/pari_ring.py +++ b/src/sage/rings/pari_ring.py @@ -215,7 +215,7 @@ def random_element(self, x=None, y=None, distribution=None): True """ - from sage.all import ZZ + from sage.rings.integer_ring import ZZ return self(ZZ.random_element(x, y, distribution)) def zeta(self): diff --git a/src/sage/rings/polynomial/term_order.py b/src/sage/rings/polynomial/term_order.py index 6c411c2011e..51c4e6ef4c6 100644 --- a/src/sage/rings/polynomial/term_order.py +++ b/src/sage/rings/polynomial/term_order.py @@ -2216,7 +2216,7 @@ def termorder_from_singular(S): sage: PolynomialRing(QQ, 'x,y', order='degneglex')('x^2')._singular_().sage() x^2 """ - from sage.all import ZZ + from sage.rings.integer_ring import ZZ singular = S T = singular('ringlist(basering)[3]') order = [] diff --git a/src/sage/rings/tests.py b/src/sage/rings/tests.py index 4fd37826771..58e88decae2 100644 --- a/src/sage/rings/tests.py +++ b/src/sage/rings/tests.py @@ -182,7 +182,7 @@ def relative_number_field(n=2, maxdeg=2): sage: from sage.rings.tests import relative_number_field sage: _ = relative_number_field(3) """ - from sage.all import ZZ + from sage.rings.integer_ring import ZZ K = absolute_number_field(maxdeg) n -= 1 var = 'aa' From 31e17a41bf21118dfba1ea3a67667ada48bd078d Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 3 Oct 2021 21:46:17 -0700 Subject: [PATCH 243/359] git grep -l 'all import .*ZZ' src/sage | xargs sed -E -i.bak $'s/^( *)from sage.*all import (ZZ, GF) *$/\1from sage.rings.integer_ring import ZZ\\n\1from sage.rings.finite_rings.finite_field_constructor import GF/' --- src/sage/algebras/steenrod/steenrod_algebra.py | 6 ++++-- src/sage/interfaces/macaulay2.py | 6 ++++-- src/sage/matroids/catalog.py | 3 ++- src/sage/rings/tests.py | 9 ++++++--- src/sage/schemes/elliptic_curves/ell_torsion.py | 3 ++- 5 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/sage/algebras/steenrod/steenrod_algebra.py b/src/sage/algebras/steenrod/steenrod_algebra.py index f289d4fd86d..3eb15efd811 100644 --- a/src/sage/algebras/steenrod/steenrod_algebra.py +++ b/src/sage/algebras/steenrod/steenrod_algebra.py @@ -2037,7 +2037,8 @@ def _coerce_map_from_(self, S): sage: B3._coerce_map_from_(A31) False """ - from sage.rings.all import ZZ, GF + from sage.rings.integer_ring import ZZ + from sage.rings.finite_rings.finite_field_constructor import GF from sage.rings.infinity import Infinity p = self.prime() if S == ZZ or S == GF(p): @@ -2099,7 +2100,8 @@ def _element_constructor_(self, x): sage: A1({(2,): 1, (1,): 13}) Sq(1) + Sq(2) """ - from sage.rings.all import ZZ, GF + from sage.rings.integer_ring import ZZ + from sage.rings.finite_rings.finite_field_constructor import GF if x in GF(self.prime()) or x in ZZ: return self.from_base_ring_from_one_basis(x) diff --git a/src/sage/interfaces/macaulay2.py b/src/sage/interfaces/macaulay2.py index 64dd877ab05..5fb903b7f6a 100644 --- a/src/sage/interfaces/macaulay2.py +++ b/src/sage/interfaces/macaulay2.py @@ -1562,7 +1562,8 @@ def _sage_(self): #Handle the ZZ/n case ambient = self.ambient() if ambient.external_string() == 'ZZ': - from sage.rings.all import ZZ, GF + from sage.rings.integer_ring import ZZ + from sage.rings.finite_rings.finite_field_constructor import GF external_string = self.external_string() zz, n = external_string.split("/") @@ -1600,7 +1601,8 @@ def _sage_(self): return PolynomialRing(base_ring, order=order, names=gens) elif cls_str == "GaloisField": - from sage.rings.all import ZZ, GF + from sage.rings.integer_ring import ZZ + from sage.rings.finite_rings.finite_field_constructor import GF gf, n = repr_str.split(" ") n = ZZ(n) if n.is_prime(): diff --git a/src/sage/matroids/catalog.py b/src/sage/matroids/catalog.py index d6a35bd6091..f80d1741248 100644 --- a/src/sage/matroids/catalog.py +++ b/src/sage/matroids/catalog.py @@ -38,7 +38,8 @@ from sage.matrix.constructor import Matrix from sage.graphs.all import graphs -from sage.rings.all import ZZ, GF +from sage.rings.integer_ring import ZZ +from sage.rings.finite_rings.finite_field_constructor import GF from sage.schemes.all import ProjectiveSpace import sage.matroids.matroid diff --git a/src/sage/rings/tests.py b/src/sage/rings/tests.py index 58e88decae2..9575ef5c6a8 100644 --- a/src/sage/rings/tests.py +++ b/src/sage/rings/tests.py @@ -29,7 +29,8 @@ def prime_finite_field(): sage: K.cardinality().is_prime() True """ - from sage.all import ZZ, GF + from sage.rings.integer_ring import ZZ + from sage.rings.finite_rings.finite_field_constructor import GF return GF(ZZ.random_element(x=2, y=10**20 - 12).next_prime()) @@ -49,7 +50,8 @@ def finite_field(): sage: while K.cardinality().is_prime(): ....: K = sage.rings.tests.finite_field() """ - from sage.all import ZZ, GF + from sage.rings.integer_ring import ZZ + from sage.rings.finite_rings.finite_field_constructor import GF p = ZZ.random_element(x=2, y=10**6 - 18).next_prime() d = ZZ.random_element(x=1, y=20) return GF(p**d, 'a') @@ -72,7 +74,8 @@ def small_finite_field(): sage: q <= 2^16 True """ - from sage.all import ZZ, GF + from sage.rings.integer_ring import ZZ + from sage.rings.finite_rings.finite_field_constructor import GF while True: q = ZZ.random_element(x=2, y=2**16) if q.is_prime_power(): diff --git a/src/sage/schemes/elliptic_curves/ell_torsion.py b/src/sage/schemes/elliptic_curves/ell_torsion.py index 33265f11d7d..5e1795f088f 100644 --- a/src/sage/schemes/elliptic_curves/ell_torsion.py +++ b/src/sage/schemes/elliptic_curves/ell_torsion.py @@ -320,7 +320,8 @@ def torsion_bound(E, number_of_places=20): sage: E.torsion_subgroup().invariants() (4, 4) """ - from sage.rings.all import ZZ, GF + from sage.rings.integer_ring import ZZ + from sage.rings.finite_rings.finite_field_constructor import GF from sage.schemes.elliptic_curves.constructor import EllipticCurve K = E.base_field() From d9dd2d008821e19886c20cd3e2270c5bff3c5473 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 3 Oct 2021 21:53:36 -0700 Subject: [PATCH 244/359] git grep -l 'all import.*ZZ' src/sage | xargs sed -E -i.bak $'s/^( *)from sage.*all import (ZZ, QQ|QQ, ZZ) *$/\1from sage.rings.integer_ring import ZZ\\n\1from sage.rings.rational_field import QQ/' --- src/sage/combinat/path_tableaux/frieze.py | 3 ++- src/sage/combinat/ribbon_tableau.py | 3 ++- src/sage/combinat/root_system/associahedron.py | 3 ++- src/sage/interfaces/chomp.py | 3 ++- src/sage/modular/abvar/abvar_newform.py | 3 ++- src/sage/rings/valuation/valuation_space.py | 3 ++- src/sage/schemes/elliptic_curves/gp_simon.py | 3 ++- src/sage/schemes/toric/divisor.py | 3 ++- 8 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/sage/combinat/path_tableaux/frieze.py b/src/sage/combinat/path_tableaux/frieze.py index e68a0747b9d..da1d4205b00 100644 --- a/src/sage/combinat/path_tableaux/frieze.py +++ b/src/sage/combinat/path_tableaux/frieze.py @@ -25,7 +25,8 @@ from sage.categories.sets_cat import Sets from sage.combinat.path_tableaux.path_tableau import PathTableau, PathTableaux, CylindricalDiagram from sage.categories.fields import Fields -from sage.rings.all import QQ, ZZ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ class FriezePattern(PathTableau, metaclass=InheritComparisonClasscallMetaclass): diff --git a/src/sage/combinat/ribbon_tableau.py b/src/sage/combinat/ribbon_tableau.py index f164a886729..b6cf87a57b5 100644 --- a/src/sage/combinat/ribbon_tableau.py +++ b/src/sage/combinat/ribbon_tableau.py @@ -21,7 +21,8 @@ from sage.structure.unique_representation import UniqueRepresentation from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets from sage.categories.sets_cat import Sets -from sage.rings.all import QQ, ZZ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ from sage.rings.integer import Integer from sage.combinat.combinat import CombinatorialElement from sage.combinat.skew_partition import SkewPartition, SkewPartitions diff --git a/src/sage/combinat/root_system/associahedron.py b/src/sage/combinat/root_system/associahedron.py index 498e37aa782..30092073473 100644 --- a/src/sage/combinat/root_system/associahedron.py +++ b/src/sage/combinat/root_system/associahedron.py @@ -27,7 +27,8 @@ from sage.geometry.polyhedron.parent import Polyhedra, Polyhedra_base, Polyhedra_QQ_ppl, Polyhedra_QQ_normaliz, Polyhedra_QQ_cdd, Polyhedra_polymake, Polyhedra_field from sage.combinat.root_system.cartan_type import CartanType from sage.modules.free_module_element import vector -from sage.rings.all import QQ, ZZ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ ancestors_of_associahedron = set([Polyhedron_QQ_ppl, Polyhedron_QQ_normaliz, Polyhedron_QQ_cdd, Polyhedron_field, Polyhedron_polymake]) diff --git a/src/sage/interfaces/chomp.py b/src/sage/interfaces/chomp.py index 00f4b3f93b3..c86ae49b2cc 100644 --- a/src/sage/interfaces/chomp.py +++ b/src/sage/interfaces/chomp.py @@ -138,7 +138,8 @@ def __call__(self, program, complex, subcomplex=None, **kwds): from sage.topology.simplicial_complex import SimplicialComplex, Simplex from sage.homology.chain_complex import HomologyGroup from subprocess import Popen, PIPE - from sage.rings.all import QQ, ZZ + from sage.rings.integer_ring import ZZ + from sage.rings.rational_field import QQ from sage.modules.all import VectorSpace, vector from sage.combinat.free_module import CombinatorialFreeModule diff --git a/src/sage/modular/abvar/abvar_newform.py b/src/sage/modular/abvar/abvar_newform.py index 21a1758283a..67c478511f3 100644 --- a/src/sage/modular/abvar/abvar_newform.py +++ b/src/sage/modular/abvar/abvar_newform.py @@ -14,7 +14,8 @@ ########################################################################### from sage.misc.lazy_import import lazy_import -from sage.rings.all import QQ, ZZ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ from sage.modular.modform.element import Newform from sage.modular.arithgroup.all import is_Gamma0, is_Gamma1, is_GammaH diff --git a/src/sage/rings/valuation/valuation_space.py b/src/sage/rings/valuation/valuation_space.py index f64072338b5..da900837371 100644 --- a/src/sage/rings/valuation/valuation_space.py +++ b/src/sage/rings/valuation/valuation_space.py @@ -475,7 +475,8 @@ def element_with_valuation(self, s): 1024 """ - from sage.rings.all import QQ, ZZ + from sage.rings.integer_ring import ZZ + from sage.rings.rational_field import QQ s = QQ.coerce(s) if s not in self.value_semigroup(): raise ValueError("s must be in the value semigroup of this valuation but %r is not in %r"%(s, self.value_semigroup())) diff --git a/src/sage/schemes/elliptic_curves/gp_simon.py b/src/sage/schemes/elliptic_curves/gp_simon.py index d1d45aa7c3d..fd68549b118 100644 --- a/src/sage/schemes/elliptic_curves/gp_simon.py +++ b/src/sage/schemes/elliptic_curves/gp_simon.py @@ -21,7 +21,8 @@ from sage.interfaces.gp import Gp from sage.misc.sage_eval import sage_eval from sage.misc.randstate import current_randstate -from sage.rings.all import QQ, ZZ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ gp = None diff --git a/src/sage/schemes/toric/divisor.py b/src/sage/schemes/toric/divisor.py index 576845ac1e8..fb6b60f71ff 100644 --- a/src/sage/schemes/toric/divisor.py +++ b/src/sage/schemes/toric/divisor.py @@ -176,7 +176,8 @@ from sage.modules.all import vector from sage.modules.free_module import (FreeModule_ambient_field, FreeModule_ambient_pid) -from sage.rings.all import QQ, ZZ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ from sage.schemes.generic.divisor import Divisor_generic from sage.schemes.generic.divisor_group import DivisorGroup_generic from sage.schemes.toric.divisor_class import ToricRationalDivisorClass From 0b06521bbe9ff8075d7158f7266657785a02da93 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 3 Oct 2021 23:20:49 -0700 Subject: [PATCH 245/359] src/sage/sets/disjoint_union_enumerated_sets.py: Remove import from sage.misc.all --- src/sage/sets/disjoint_union_enumerated_sets.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/sage/sets/disjoint_union_enumerated_sets.py b/src/sage/sets/disjoint_union_enumerated_sets.py index 7a6f604dc16..79e5954c561 100644 --- a/src/sage/sets/disjoint_union_enumerated_sets.py +++ b/src/sage/sets/disjoint_union_enumerated_sets.py @@ -21,7 +21,8 @@ from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets from sage.categories.infinite_enumerated_sets import InfiniteEnumeratedSets from sage.rings.infinity import Infinity -from sage.misc.all import cached_method, lazy_attribute +from sage.misc.cachefunc import cached_method +from sage.misc.lazy_attribute import lazy_attribute from sage.structure.unique_representation import UniqueRepresentation class DisjointUnionEnumeratedSets(UniqueRepresentation, Parent): From 43ed0cadadf02c48c31990b62817ef53d4eef15d Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 3 Oct 2021 23:25:04 -0700 Subject: [PATCH 246/359] git grep -l 'all import cputime' src/sage | xargs sed -E -i.bak $'s/^( *)from sage.*all import (cputime) *$/\1from sage.misc.misc import \2/' --- src/sage/modular/modform/eis_series.py | 2 +- src/sage/modular/quatalg/brandt.py | 2 +- src/sage/rings/number_field/splitting_field.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sage/modular/modform/eis_series.py b/src/sage/modular/modform/eis_series.py index adf7ec610c7..4f2e0ed878a 100644 --- a/src/sage/modular/modform/eis_series.py +++ b/src/sage/modular/modform/eis_series.py @@ -12,7 +12,7 @@ # https://www.gnu.org/licenses/ # **************************************************************************** -from sage.misc.all import cputime +from sage.misc.misc import cputime import sage.modular.dirichlet as dirichlet from sage.modular.arithgroup.congroup_gammaH import GammaH_class from sage.rings.all import Integer, CyclotomicField, ZZ, QQ diff --git a/src/sage/modular/quatalg/brandt.py b/src/sage/modular/quatalg/brandt.py index 5fbde461d12..366830a6325 100644 --- a/src/sage/modular/quatalg/brandt.py +++ b/src/sage/modular/quatalg/brandt.py @@ -1685,7 +1685,7 @@ def benchmark_sage(levels, silent=False): ('sage', 43, 2, ...) ('sage', 97, 2, ...) """ - from sage.misc.all import cputime + from sage.misc.misc import cputime ans = [] for p, M in levels: t = cputime() diff --git a/src/sage/rings/number_field/splitting_field.py b/src/sage/rings/number_field/splitting_field.py index 06edcad31d5..8818e5d1bad 100644 --- a/src/sage/rings/number_field/splitting_field.py +++ b/src/sage/rings/number_field/splitting_field.py @@ -339,7 +339,7 @@ def splitting_field(poly, name, map=False, degree_multiple=None, abort_degree=No To: Number Field in x with defining polynomial x Defn: 1 |--> 1) """ - from sage.misc.all import cputime + from sage.misc.misc import cputime from sage.misc.verbose import verbose degree_multiple = Integer(degree_multiple or 0) From bc4e07dc4e0bc7999fcc31ba5db3d065a7ddfb84 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Mon, 4 Oct 2021 15:45:55 +0900 Subject: [PATCH 247/359] Using another iterator in restrict(). --- src/sage/combinat/skew_tableau.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/combinat/skew_tableau.py b/src/sage/combinat/skew_tableau.py index 99ef0d512e3..676aff61440 100644 --- a/src/sage/combinat/skew_tableau.py +++ b/src/sage/combinat/skew_tableau.py @@ -703,8 +703,8 @@ def restrict(self, n): sage: SkewTableau([[None,1],[1],[2]]).restrict(1) [[None, 1], [1]] """ - return SkewTableau([z for z in [[y for y in x if y is None or y <= n] - for x in self] if z]) + data = ([y for y in x if y is None or y <= n] for x in self) + return SkewTableau([z for z in data if z]) def restriction_outer_shape(self, n): """ From 3a20afe93036dcd0c0e3869e0a4001c6711dc788 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 3 Oct 2021 23:48:30 -0700 Subject: [PATCH 248/359] src/sage/categories/pushout.py: Remove .all imports --- src/sage/categories/pushout.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/sage/categories/pushout.py b/src/sage/categories/pushout.py index 7a15885b609..10e17140849 100644 --- a/src/sage/categories/pushout.py +++ b/src/sage/categories/pushout.py @@ -2584,7 +2584,7 @@ def merge(self, other): True """ if self == other: # both are Completion functors with the same p - from sage.all import Infinity + from sage.rings.infinity import Infinity if self.p == Infinity: new_prec = min(self.prec, other.prec) new_type = self._real_types[min(self._real_types.index(self.type), @@ -2773,7 +2773,7 @@ def _apply_functor(self, R): if not I.is_zero(): from sage.categories.fields import Fields if R in Fields(): - from sage.all import Integers + from sage.rings.finite_rings.integer_mod_ring import Integers return Integers(1) if I.ring() != R: if I.ring().has_coerce_map_from(R): @@ -3153,8 +3153,10 @@ def _apply_functor(self, R): 3-adic Eisenstein Extension Field in a defined by a^2 - 3 """ - from sage.all import QQ, ZZ, CyclotomicField + from sage.rings.rational_field import QQ + from sage.rings.integer_ring import ZZ if self.cyclotomic: + from sage.rings.number_field.number_field import CyclotomicField if R == QQ: return CyclotomicField(self.cyclotomic) if R == ZZ: @@ -3325,7 +3327,7 @@ def merge(self, other): # return other # ... or we may use the given embeddings: if self.embeddings != [None] and other.embeddings != [None]: - from sage.all import QQ + from sage.rings.rational_field import QQ KS = self(QQ) KO = other(QQ) if KS.has_coerce_map_from(KO): @@ -3566,7 +3568,7 @@ def merge(self, other): """ if self.__class__ != other.__class__: return None - from sage.sets.all import FiniteEnumeratedSet + from sage.sets.finite_enumerated_set import FiniteEnumeratedSet new_domain = set(self._domain).union(set(other._domain)) try: From 19ac6fd5e7826aa726a555bf73dfcde0f753e579 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 4 Oct 2021 00:00:40 -0700 Subject: [PATCH 249/359] src/sage/rings/complex_interval_field.py: Fixup deprecation warning in doctest output --- src/sage/rings/complex_interval_field.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/rings/complex_interval_field.py b/src/sage/rings/complex_interval_field.py index 05758d9956b..013977aa338 100644 --- a/src/sage/rings/complex_interval_field.py +++ b/src/sage/rings/complex_interval_field.py @@ -56,11 +56,11 @@ def is_ComplexIntervalField(x): EXAMPLES:: sage: from sage.rings.complex_interval_field import is_ComplexIntervalField as is_CIF + sage: is_CIF(CIF) doctest:warning... DeprecationWarning: is_ComplexIntervalField is deprecated; use isinstance(..., sage.rings.abc.ComplexIntervalField) instead See https://trac.sagemath.org/32612 for details. - sage: is_CIF(CIF) True sage: is_CIF(CC) False From e18d1fb9864580a70255291b84396ec67d94660f Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 4 Oct 2021 00:07:43 -0700 Subject: [PATCH 250/359] src/sage/categories/enumerated_sets.py: Remove .all import --- src/sage/categories/enumerated_sets.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/categories/enumerated_sets.py b/src/sage/categories/enumerated_sets.py index 4ca5747f04e..68bebd0f84f 100644 --- a/src/sage/categories/enumerated_sets.py +++ b/src/sage/categories/enumerated_sets.py @@ -146,7 +146,7 @@ def _call_(self, X): """ import sage.sets.set if isinstance(X, (tuple, list, set, range, sage.sets.set.Set_object_enumerated)): - return sage.sets.all.FiniteEnumeratedSet(X) + return sage.sets.finite_enumerated_set.FiniteEnumeratedSet(X) raise NotImplementedError class ParentMethods: From f31deb3c73264040962e0d7b9f43bc0d38d07d8c Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 4 Oct 2021 08:49:16 -0700 Subject: [PATCH 251/359] src/sage/rings/qqbar.py: Remove unused import --- src/sage/rings/qqbar.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/rings/qqbar.py b/src/sage/rings/qqbar.py index a36b5de3c72..63b566f47f2 100644 --- a/src/sage/rings/qqbar.py +++ b/src/sage/rings/qqbar.py @@ -566,7 +566,7 @@ from sage.rings.real_mpfr import RR from sage.rings.real_mpfi import RealIntervalField, RIF, is_RealIntervalFieldElement, RealIntervalField_class from sage.rings.complex_mpfr import ComplexField -from sage.rings.complex_interval_field import ComplexIntervalField, is_ComplexIntervalField +from sage.rings.complex_interval_field import ComplexIntervalField from sage.rings.complex_interval import is_ComplexIntervalFieldElement from sage.rings.polynomial.all import PolynomialRing from sage.rings.polynomial.polynomial_element import is_Polynomial From 14fd1e54a13b1df7f81858019b31fb92cdf36007 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 4 Oct 2021 15:37:57 -0700 Subject: [PATCH 252/359] src/doc/en/developer/coding_basics.rst: Update discussion of feature tags --- src/doc/en/developer/coding_basics.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/doc/en/developer/coding_basics.rst b/src/doc/en/developer/coding_basics.rst index f6413de91e8..31d87ef7d84 100644 --- a/src/doc/en/developer/coding_basics.rst +++ b/src/doc/en/developer/coding_basics.rst @@ -1101,9 +1101,10 @@ framework. Here is a comprehensive list: .. NOTE:: - Any words after ``# optional`` are interpreted as a list of - package names, separated by spaces. + package (spkg) names or other feature tags, separated by spaces. - - Any punctuation (periods, commas, hyphens, semicolons, ...) after the + - Any punctuation other than underscores (``_``) and periods (``.``), + that is, commas, hyphens, semicolons, ..., after the first word ends the list of packages. Hyphens or colons between the word ``optional`` and the first package name are allowed. Therefore, you should not write ``optional: needs package CHomP`` but simply From 29f5a7ee02dc0064af63c2f58a262bb431b077d3 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Tue, 5 Oct 2021 12:28:49 +0900 Subject: [PATCH 253/359] Replacing all sage.combinat.family import with sage.sets.family. --- src/sage/algebras/iwahori_hecke_algebra.py | 2 +- src/sage/categories/modules_with_basis.py | 4 ++-- src/sage/combinat/chas/fsym.py | 2 +- src/sage/combinat/fqsym.py | 2 +- src/sage/combinat/root_system/type_E.py | 2 +- src/sage/combinat/root_system/type_F.py | 2 +- src/sage/combinat/root_system/weight_lattice_realizations.py | 2 +- src/sage/libs/coxeter3/coxeter_group.py | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/sage/algebras/iwahori_hecke_algebra.py b/src/sage/algebras/iwahori_hecke_algebra.py index 660699d2a93..a35fd831f9d 100644 --- a/src/sage/algebras/iwahori_hecke_algebra.py +++ b/src/sage/algebras/iwahori_hecke_algebra.py @@ -30,7 +30,7 @@ from sage.rings.polynomial.laurent_polynomial_ring import LaurentPolynomialRing from sage.arith.all import is_square from sage.combinat.root_system.coxeter_group import CoxeterGroup -from sage.combinat.family import Family +from sage.sets.family import Family from sage.combinat.free_module import CombinatorialFreeModule diff --git a/src/sage/categories/modules_with_basis.py b/src/sage/categories/modules_with_basis.py index bb1dd2d4bbf..6cd291e4c91 100644 --- a/src/sage/categories/modules_with_basis.py +++ b/src/sage/categories/modules_with_basis.py @@ -219,7 +219,7 @@ def basis(self): sage: list(QS3.basis()) [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]] """ - from sage.combinat.family import Family + from sage.sets.family import Family return Family(self._indices, self.monomial) def module_morphism(self, on_basis=None, matrix=None, function=None, @@ -1155,7 +1155,7 @@ def _apply_module_morphism(self, x, on_basis, codomain=False): """ if x == self.zero(): if not codomain: - from sage.combinat.family import Family + from sage.sets.family import Family B = Family(self.basis()) try: z = B.first() diff --git a/src/sage/combinat/chas/fsym.py b/src/sage/combinat/chas/fsym.py index 5a3fe04b921..d618f44d3fd 100644 --- a/src/sage/combinat/chas/fsym.py +++ b/src/sage/combinat/chas/fsym.py @@ -284,7 +284,7 @@ def basis(self, degree=None): sage: TG.basis(degree=3).list() [G[123], G[13|2], G[12|3], G[1|2|3]] """ - from sage.combinat.family import Family + from sage.sets.family import Family if degree is None: return Family(self._indices, self.monomial) else: diff --git a/src/sage/combinat/fqsym.py b/src/sage/combinat/fqsym.py index fc29f0f0a06..ba89286a1a3 100644 --- a/src/sage/combinat/fqsym.py +++ b/src/sage/combinat/fqsym.py @@ -1337,7 +1337,7 @@ def basis(self, degree=None): sage: G.basis(degree=3).list() [G[1, 2, 3], G[1, 3, 2], G[2, 1, 3], G[2, 3, 1], G[3, 1, 2], G[3, 2, 1]] """ - from sage.combinat.family import Family + from sage.sets.family import Family if degree is None: return Family(self._indices, self.monomial) else: diff --git a/src/sage/combinat/root_system/type_E.py b/src/sage/combinat/root_system/type_E.py index 7c910ecab6d..aeb03ecccd9 100644 --- a/src/sage/combinat/root_system/type_E.py +++ b/src/sage/combinat/root_system/type_E.py @@ -13,7 +13,7 @@ from . import ambient_space from sage.rings.all import ZZ -from sage.combinat.family import Family +from sage.sets.family import Family class AmbientSpace(ambient_space.AmbientSpace): """ diff --git a/src/sage/combinat/root_system/type_F.py b/src/sage/combinat/root_system/type_F.py index f7b9dbcf667..3ce580d78e0 100644 --- a/src/sage/combinat/root_system/type_F.py +++ b/src/sage/combinat/root_system/type_F.py @@ -13,7 +13,7 @@ from . import ambient_space from sage.rings.all import ZZ -from sage.combinat.family import Family +from sage.sets.family import Family # TODO: double check that this can't be defined over ZZ diff --git a/src/sage/combinat/root_system/weight_lattice_realizations.py b/src/sage/combinat/root_system/weight_lattice_realizations.py index 033152d42ec..0503d6ddc74 100644 --- a/src/sage/combinat/root_system/weight_lattice_realizations.py +++ b/src/sage/combinat/root_system/weight_lattice_realizations.py @@ -23,7 +23,7 @@ from sage.misc.lazy_attribute import lazy_attribute from sage.misc.all import prod from sage.categories.category_types import Category_over_base_ring -from sage.combinat.family import Family +from sage.sets.family import Family from .root_lattice_realizations import RootLatticeRealizations diff --git a/src/sage/libs/coxeter3/coxeter_group.py b/src/sage/libs/coxeter3/coxeter_group.py index b4118ca9592..fe4457b5eaf 100644 --- a/src/sage/libs/coxeter3/coxeter_group.py +++ b/src/sage/libs/coxeter3/coxeter_group.py @@ -160,7 +160,7 @@ def simple_reflections(self): sage: s[2]*s[1]*s[2] # optional - coxeter3 [2, 1, 2] """ - from sage.combinat.family import Family + from sage.sets.family import Family return Family(self.index_set(), lambda i: self.element_class(self, [i])) gens = simple_reflections From 6228141f7317aeb05034e68099b54306aefdbc0a Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Tue, 5 Oct 2021 15:22:26 +0900 Subject: [PATCH 254/359] Allowing more than 9 variables for quantum matrix coordinate ring. --- .../quantum_matrix_coordinate_algebra.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/sage/algebras/quantum_matrix_coordinate_algebra.py b/src/sage/algebras/quantum_matrix_coordinate_algebra.py index 498aa34811d..a38a00aa2b7 100644 --- a/src/sage/algebras/quantum_matrix_coordinate_algebra.py +++ b/src/sage/algebras/quantum_matrix_coordinate_algebra.py @@ -515,6 +515,16 @@ def __init__(self, m, n, q, bar, R): sage: O = algebras.QuantumMatrixCoordinate(4) sage: TestSuite(O).run() + + sage: O = algebras.QuantumMatrixCoordinate(10) + sage: O.variable_names() + ('x0101', ..., 'x1010') + sage: O = algebras.QuantumMatrixCoordinate(11,3) + sage: O.variable_names() + ('x011', ..., 'x113') + sage: O = algebras.QuantumMatrixCoordinate(3,11) + sage: O.variable_names() + ('x101', ..., 'x311') """ gp_indices = [(i, j) for i in range(1, m + 1) for j in range(1, n + 1)] @@ -526,7 +536,10 @@ def __init__(self, m, n, q, bar, R): self._m = m QuantumMatrixCoordinateAlgebra_abstract.__init__(self, gp_indices, n, q, bar, R, cat) # Set the names - names = ['x{}{}'.format(*k) for k in gp_indices] + mb = len(str(m)) + nb = len(str(n)) + base = 'x{{:0>{}}}{{:0>{}}}'.format(mb,nb) + names = [base.format(*k) for k in gp_indices] self._assign_names(names) def _repr_(self): @@ -992,3 +1005,4 @@ def _generator_key(t): if isinstance(t, tuple): return t return () + From 9ea834aba64a3e54ee9e96a668e875e3964be442 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Tue, 5 Oct 2021 15:28:00 +0900 Subject: [PATCH 255/359] Speedup for quantum det. --- src/sage/algebras/quantum_matrix_coordinate_algebra.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/sage/algebras/quantum_matrix_coordinate_algebra.py b/src/sage/algebras/quantum_matrix_coordinate_algebra.py index a38a00aa2b7..26b783d7101 100644 --- a/src/sage/algebras/quantum_matrix_coordinate_algebra.py +++ b/src/sage/algebras/quantum_matrix_coordinate_algebra.py @@ -238,9 +238,8 @@ def quantum_determinant(self): raise ValueError("undefined for non-square quantum matrices") from sage.combinat.permutation import Permutations q = self._q - return self.sum(self.term(self._indices({(i, p(i)): 1 for i in range(1, self._n + 1)}), - (-q) ** p.length()) - for p in Permutations(self._n)) + return self._from_dict({self._indices({(i, p(i)): 1 for i in range(1, self._n + 1)}): + (-q) ** p.length() for p in Permutations(self._n)}) def product_on_basis(self, a, b): """ From 28dc817c7b8a97807e5514d28a66a178652d3ed4 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 4 Oct 2021 22:28:02 -0700 Subject: [PATCH 256/359] Polyhedron._test...: Avoid testing using unavailable functionality --- src/sage/geometry/polyhedron/base.py | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/src/sage/geometry/polyhedron/base.py b/src/sage/geometry/polyhedron/base.py index 47063568802..32e2193fd1c 100644 --- a/src/sage/geometry/polyhedron/base.py +++ b/src/sage/geometry/polyhedron/base.py @@ -6369,12 +6369,17 @@ def _test_lawrence(self, tester=None, **options): with warnings.catch_warnings(): warnings.simplefilter("error") try: + from sage.rings.real_double_field import RDF + two = RDF(2.0) # Implicitly checks :trac:`30328`. - R = self.lawrence_extension(2.0*v - self.center()) + R = self.lawrence_extension(two * v - self.center()) tester.assertEqual(self.dim() + 1, R.dim()) tester.assertEqual(self.n_vertices() + 2, R.n_vertices()) tester.assertTrue(Q.is_combinatorially_isomorphic(R)) + except ImportError: + # RDF not available + pass except UserWarning: # Data is numerically complicated. pass @@ -7373,8 +7378,13 @@ def _test_combinatorial_face_as_combinatorial_polyhedron(self, tester=None, **op D2 = f2.as_combinatorial_polyhedron(quotient=True).dual() D1._test_bitsets(tester, **options) D2._test_bitsets(tester, **options) - tester.assertTrue(P.combinatorial_polyhedron().vertex_facet_graph().is_isomorphic(D1.vertex_facet_graph())) - tester.assertTrue(P.combinatorial_polyhedron().vertex_facet_graph().is_isomorphic(D2.vertex_facet_graph())) + try: + import sage.graphs.graph + except ImportError: + pass + else: + tester.assertTrue(P.combinatorial_polyhedron().vertex_facet_graph().is_isomorphic(D1.vertex_facet_graph())) + tester.assertTrue(P.combinatorial_polyhedron().vertex_facet_graph().is_isomorphic(D2.vertex_facet_graph())) @cached_method(do_pickle=True) def f_vector(self, num_threads=None, parallelization_depth=None): @@ -7954,7 +7964,12 @@ def check_pyramid_certificate(P, cert): tester.assertTrue(b) check_pyramid_certificate(polar_pyr, cert) - tester.assertTrue(pyr_polar.is_combinatorially_isomorphic(pyr_polar)) + try: + import sage.graphs.graph + except ImportError: + pass + else: + tester.assertTrue(pyr_polar.is_combinatorially_isomorphic(pyr_polar)) # Basic properties of the pyramid. @@ -10736,6 +10751,11 @@ def _test_is_combinatorially_isomorphic(self, tester=None, **options): # Avoid very long doctests. return + try: + import sage.graphs.graph + except ImportError: + return + tester.assertTrue(self.is_combinatorially_isomorphic(ZZ(4)*self)) if self.n_vertices(): tester.assertTrue(self.is_combinatorially_isomorphic(self + self.center())) From 52ac1dac69cfc8b869459e08408ff94ff2f81611 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 4 Oct 2021 23:26:44 -0700 Subject: [PATCH 257/359] Polyhedron_base._test_gale_transform: Do not test is_combinatorially_isomorphic if sage.graphs.graphs not available --- src/sage/geometry/polyhedron/base.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/sage/geometry/polyhedron/base.py b/src/sage/geometry/polyhedron/base.py index 32e2193fd1c..d6662d8a156 100644 --- a/src/sage/geometry/polyhedron/base.py +++ b/src/sage/geometry/polyhedron/base.py @@ -4220,7 +4220,12 @@ def _test_gale_transform(self, tester=None, **options): g = self.gale_transform() P = gale_transform_to_polytope(g, base_ring=self.base_ring(), backend=self.backend()) - tester.assertTrue(self.is_combinatorially_isomorphic(P)) + try: + import sage.graphs.graph + except ImportError: + pass + else: + tester.assertTrue(self.is_combinatorially_isomorphic(P)) @cached_method def normal_fan(self, direction='inner'): From 9793567a731d895b9239bee77d76e66276531172 Mon Sep 17 00:00:00 2001 From: Moritz Firsching Date: Tue, 5 Oct 2021 09:53:05 +0200 Subject: [PATCH 258/359] adding quantum_determinant to matrix --- src/sage/matrix/matrix2.pyx | 38 +++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/sage/matrix/matrix2.pyx b/src/sage/matrix/matrix2.pyx index d4a8ec9d3a1..bb6f9855c0f 100644 --- a/src/sage/matrix/matrix2.pyx +++ b/src/sage/matrix/matrix2.pyx @@ -62,6 +62,7 @@ AUTHORS: - Michael Jung (2020-10-02): added Bär-Faddeev-LeVerrier algorithm for the Pfaffian +- Moritz Firsching(2020-10-05): added ``quantum_determinant`` """ # **************************************************************************** @@ -2113,6 +2114,43 @@ cdef class Matrix(Matrix1): self.swap_rows(level, i) return d + def quantum_determinant(self, q=None): + r""" + Return the quantum deteminant of a matrix. + + INPUT: + - ``q`` -- a symbolic variable or a generator for a + (Laurent) polynomial ring. Creates a generator for a + polynomial ring over the base ring of the by default. + + EXAMPLES:: + + sage: A = Matrix([[SR(f'a{i}{j}') for i in range(2)] + ....: for j in range(2)]); A + [a00 a10] + [a01 a11] + sage: A.quantum_determinant() + -a01*a10*q + a00*a11 + sage: R. = LaurentPolynomialRing(ZZ) + sage: A = MatrixSpace(Integers(8),3)([1,7,3, 1,1,1, 3,4,5]) + sage: A.quantum_determinant(q) + 5 + q + q^2 + 7*q^3 + """ + n = self._ncols + + if self._nrows != n: + raise ValueError("self must be a square matrix") + + if q is None: + from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing + q = PolynomialRing(self.base_ring(), 'q').gen() + + from sage.misc.misc_c import prod + from sage.combinat.permutation import Permutations + return sum((-q)**(s.number_of_inversions()) * + prod(self[s(i + 1) - 1, i] for i in range(n)) + for s in Permutations(n)) + def pfaffian(self, algorithm=None, check=True): r""" Return the Pfaffian of ``self``, assuming that ``self`` is an From b8969296368a4a1ad944792780d3cba17f72817a Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Tue, 5 Oct 2021 19:08:12 +0900 Subject: [PATCH 259/359] Reviewer changes to quantum_determinant. --- src/sage/matrix/matrix2.pyx | 48 ++++++++++++++++++++++++++++--------- 1 file changed, 37 insertions(+), 11 deletions(-) diff --git a/src/sage/matrix/matrix2.pyx b/src/sage/matrix/matrix2.pyx index bb6f9855c0f..cbe509e2180 100644 --- a/src/sage/matrix/matrix2.pyx +++ b/src/sage/matrix/matrix2.pyx @@ -2116,27 +2116,52 @@ cdef class Matrix(Matrix1): def quantum_determinant(self, q=None): r""" - Return the quantum deteminant of a matrix. + Return the quantum deteminant of ``self``. INPUT: - - ``q`` -- a symbolic variable or a generator for a - (Laurent) polynomial ring. Creates a generator for a - polynomial ring over the base ring of the by default. + + - ``q`` -- the parameter `q`; the default is `q \in F[q]`, + where `F` is the base ring of ``self`` EXAMPLES:: - sage: A = Matrix([[SR(f'a{i}{j}') for i in range(2)] + sage: A = matrix([[SR(f'a{i}{j}') for i in range(2)] ....: for j in range(2)]); A [a00 a10] [a01 a11] sage: A.quantum_determinant() -a01*a10*q + a00*a11 + + sage: A = matrix([[SR(f'a{i}{j}') for i in range(3)] + ....: for j in range(3)]) + sage: A.quantum_determinant() + -a02*a11*a20*q^3 + (a01*a12*a20 + a02*a10*a21)*q^2 + + (-a00*a12*a21 - a01*a10*a22)*q + a00*a11*a22 + sage: R. = LaurentPolynomialRing(ZZ) - sage: A = MatrixSpace(Integers(8),3)([1,7,3, 1,1,1, 3,4,5]) - sage: A.quantum_determinant(q) - 5 + q + q^2 + 7*q^3 + sage: MS = MatrixSpace(Integers(8), 3) + sage: A = MS([1,7,3, 1,1,1, 3,4,5]) + sage: A.det() + 6 + sage: A.quantum_determinant(q^-2) + 7*q^-6 + q^-4 + q^-2 + 5 + + sage: S. = PolynomialRing(GF(7)) + sage: R. = LaurentPolynomialRing(S) + sage: MS = MatrixSpace(S, 3, sparse=True) + sage: A = MS([[x, y, 3], [4, 2+y, x^2], [0, 1-x, x+y]]) + sage: A.det() + x^4 - x^3 + x^2*y + x*y^2 + 2*x^2 - 2*x*y + 3*y^2 + 2*x - 2 + sage: A.quantum_determinant() + (2*x - 2)*q^2 + (x^4 - x^3 + 3*x*y + 3*y^2)*q + x^2*y + x*y^2 + 2*x^2 + 2*x*y + sage: A.quantum_determinant(int(2)) + 2*x^4 - 2*x^3 + x^2*y + x*y^2 + 2*x^2 + x*y - y^2 + x - 1 + sage: A.quantum_determinant(q*x + q^-1*y) + (2*x*y^2 - 2*y^2)*q^-2 + (x^4*y - x^3*y + 3*x*y^2 + 3*y^3)*q^-1 + + (-2*x^2*y + x*y^2 + 2*x^2 - 2*x*y) + + (x^5 - x^4 + 3*x^2*y + 3*x*y^2)*q + (2*x^3 - 2*x^2)*q^2 """ - n = self._ncols + cdef Py_ssize_t n = self._ncols if self._nrows != n: raise ValueError("self must be a square matrix") @@ -2147,8 +2172,9 @@ cdef class Matrix(Matrix1): from sage.misc.misc_c import prod from sage.combinat.permutation import Permutations - return sum((-q)**(s.number_of_inversions()) * - prod(self[s(i + 1) - 1, i] for i in range(n)) + cdef Py_ssize_t i + return sum((-q)**s.number_of_inversions() + * prod(self.get_unsafe(s[i] - 1, i) for i in range(n)) for s in Permutations(n)) def pfaffian(self, algorithm=None, check=True): From 924dc714eddde5bb8168126e0baccbe6ae3cb604 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Tue, 5 Oct 2021 21:12:14 +0900 Subject: [PATCH 260/359] Adding a description of the quantum det. --- src/sage/matrix/matrix2.pyx | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/sage/matrix/matrix2.pyx b/src/sage/matrix/matrix2.pyx index cbe509e2180..8373ca6d7ea 100644 --- a/src/sage/matrix/matrix2.pyx +++ b/src/sage/matrix/matrix2.pyx @@ -2118,6 +2118,19 @@ cdef class Matrix(Matrix1): r""" Return the quantum deteminant of ``self``. + The quantum determinant of a matrix `M = (m_{ij})_{i,j=1}^n` + is defined by + + .. MATH:: + + \det_q(M) = + \sum_{\sigma \in S_n} (-q)^{\ell(\sigma)} M_{\sigma(i),j}, + + where `S_n` is symmetric group on `\{1, \ldots, n\}` and + `\ell(\sigma)` denotes the length of `\sigma` witten as simple + transpositions (equivalently the number of inversions when + written in one-line notation). + INPUT: - ``q`` -- the parameter `q`; the default is `q \in F[q]`, @@ -2177,6 +2190,8 @@ cdef class Matrix(Matrix1): * prod(self.get_unsafe(s[i] - 1, i) for i in range(n)) for s in Permutations(n)) + qdet = quantum_determinant + def pfaffian(self, algorithm=None, check=True): r""" Return the Pfaffian of ``self``, assuming that ``self`` is an From d457a590d19791fa16eda91b99b7203f781a4715 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Tue, 5 Oct 2021 21:34:21 +0900 Subject: [PATCH 261/359] Fixing typos in qdet description. --- src/sage/matrix/matrix2.pyx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/matrix/matrix2.pyx b/src/sage/matrix/matrix2.pyx index 8373ca6d7ea..0c741a395d3 100644 --- a/src/sage/matrix/matrix2.pyx +++ b/src/sage/matrix/matrix2.pyx @@ -2126,8 +2126,8 @@ cdef class Matrix(Matrix1): \det_q(M) = \sum_{\sigma \in S_n} (-q)^{\ell(\sigma)} M_{\sigma(i),j}, - where `S_n` is symmetric group on `\{1, \ldots, n\}` and - `\ell(\sigma)` denotes the length of `\sigma` witten as simple + where `S_n` is the symmetric group on `\{1, \ldots, n\}` and + `\ell(\sigma)` denotes the length of `\sigma` written as simple transpositions (equivalently the number of inversions when written in one-line notation). From 71cb38201a3aca2411ffb774f671d5bacb7ee201 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Tue, 5 Oct 2021 16:37:30 +0200 Subject: [PATCH 262/359] pep cleanup for toric Chow group file --- src/sage/schemes/toric/chow_group.py | 122 +++++++++++---------------- 1 file changed, 47 insertions(+), 75 deletions(-) diff --git a/src/sage/schemes/toric/chow_group.py b/src/sage/schemes/toric/chow_group.py index 84d32fe373e..34deb208d74 100644 --- a/src/sage/schemes/toric/chow_group.py +++ b/src/sage/schemes/toric/chow_group.py @@ -110,7 +110,6 @@ sage: sum( mixed.project_to_degree(i) for i in range(X.dimension()+1) ) == mixed True """ - # **************************************************************************** # Copyright (C) 2010 Volker Braun # @@ -118,6 +117,7 @@ # # https://www.gnu.org/licenses/ # **************************************************************************** +from __future__ import annotations from sage.misc.all import flatten from sage.misc.fast_methods import WithEqualityById @@ -133,9 +133,6 @@ from sage.schemes.toric.divisor import is_ToricDivisor - - -#******************************************************************* class ChowCycle(FGP_Element): """ The elements of the Chow group. @@ -158,7 +155,6 @@ class ChowCycle(FGP_Element): sage: A( Cone([(1,0)]) ) ( 0 | 1 | 0 ) """ - def __init__(self, parent, v, check=True): r""" Construct a :class:`ChowCycle`. @@ -184,7 +180,7 @@ def __init__(self, parent, v, check=True): """ FGP_Element.__init__(self, parent, v, check) - def _repr_(self): + def _repr_(self) -> str: r""" Return a string representation of the Chow cycle. @@ -230,7 +226,7 @@ def _repr_(self): s += ')' return s - def degree(self): + def degree(self) -> int: r""" The degree of the Chow cycle. @@ -253,14 +249,13 @@ def degree(self): ambient_dim = self.parent()._variety.dimension() cone_dim = None for i, cone in enumerate(self.parent()._cones): - if self.lift()[i]!=0: - if cone_dim not in [None,cone.dim()]: + if self.lift()[i] != 0: + if cone_dim not in [None, cone.dim()]: raise ValueError('Chow cycle is not of definite degree.') cone_dim = cone.dim() self._dim = ambient_dim - cone_dim return self._dim - def project_to_degree(self, degree): r""" Project a (mixed-degree) Chow cycle to the given ``degree``. @@ -287,13 +282,12 @@ def project_to_degree(self, degree): v = list(self.lift()) for i in range(len(v)): cone = self.parent()._cones[i] - if cone.dim() != ambient_dim-degree: + if cone.dim() != ambient_dim - degree: v[i] = 0 v = self.parent().cover()(v) P = self.parent() return P.element_class(P, v, check=False) - def count_points(self): r""" Return the number of points in the Chow cycle. @@ -340,9 +334,7 @@ def count_points(self): sage: P1xP1_Z2.integrate( Dt.cohomology_class() * Dy.cohomology_class() ) 1/2 """ - c0 = self.project_to_degree(0).lift() - return sum(c0) - + return sum(self.project_to_degree(0).lift()) def intersection_with_divisor(self, divisor): """ @@ -413,7 +405,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), str(divisor)+' is not a toric divisor.' + assert is_ToricDivisor(divisor), f'{divisor} is not a toric divisor' A = self.parent() # the Chow group X = A._variety # the toric variety @@ -421,11 +413,11 @@ def intersection_with_divisor(self, divisor): coefficients = self.lift() for sigma_idx, sigma in enumerate(A._cones): - if sigma.dim()==X.dimension(): + if sigma.dim() == X.dimension(): # full-dimensional cone = degree-0 Chow cycle continue coefficient = coefficients[sigma_idx] - if coefficient==0: + if coefficient == 0: continue D = divisor.move_away_from(sigma) for gamma in sigma.facet_of(): @@ -436,13 +428,11 @@ def intersection_with_divisor(self, divisor): i = I_gamma.pop() # index of a ray in gamma but not sigma v_i = X.fan().ray(i) a_i = D.coefficient(i) - s_i = (v_i*perp)/(n*perp) - b_gamma = a_i/s_i - # print sigma._points_idx, "\t", i, D, a_i, s_i, b_gamma, gamma.A() - intersection += self.base_ring()(coefficient*b_gamma) * A(gamma) + s_i = (v_i * perp) / (n * perp) + b_gamma = a_i / s_i + intersection += self.base_ring()(coefficient * b_gamma) * A(gamma) return intersection - def cohomology_class(self): r""" Return the (Poincaré-dual) cohomology class. @@ -523,13 +513,13 @@ def cohomology_class(self): """ toric_variety = self.parent().scheme() if not toric_variety.is_orbifold(): - raise ValueError + raise ValueError('not an orbifold') HH = toric_variety.cohomology_ring() coeff = self.lift() - return sum([ HH(cone) * coeff[i] for i,cone in enumerate(self.parent()._cones) ]) + return sum([HH(cone) * coeff[i] + for i, cone in enumerate(self.parent()._cones)]) -#******************************************************************* class ChowGroupFactory(UniqueFactory): """ Factory for :class:`ChowGroup_class`. @@ -558,14 +548,13 @@ def create_key_and_extra_args(self, toric_variety, base_ring=ZZ, check=True): if not is_ToricVariety(toric_variety): raise ValueError('First argument must be a toric variety.') - if not base_ring in [ZZ,QQ]: + if base_ring not in [ZZ, QQ]: raise ValueError('Base ring must be either ZZ or QQ.') key = tuple([toric_variety, base_ring]) - extra = {'check':check} + extra = {'check': check} return key, extra - def create_object(self, version, key, **extra_args): """ Create a :class:`ChowGroup_class`. @@ -593,21 +582,19 @@ def create_object(self, version, key, **extra_args): ChowGroup = ChowGroupFactory('ChowGroup') -#******************************************************************* class ChowGroup_class(FGP_Module_class, WithEqualityById): r""" The Chow group of a toric variety. EXAMPLES:: - sage: P2=toric_varieties.P2() + sage: P2 = toric_varieties.P2() sage: from sage.schemes.toric.chow_group import ChowGroup_class sage: A = ChowGroup_class(P2,ZZ,True); A Chow group of 2-d CPR-Fano toric variety covered by 3 affine patches sage: A.an_element() ( 0 | 0 | 1 ) """ - Element = ChowCycle def __init__(self, toric_variety, base_ring, check): @@ -615,7 +602,7 @@ def __init__(self, toric_variety, base_ring, check): EXAMPLES:: sage: from sage.schemes.toric.chow_group import * - sage: P2=toric_varieties.P2() + sage: P2 = toric_varieties.P2() sage: A = ChowGroup_class(P2,ZZ,True); A Chow group of 2-d CPR-Fano toric variety covered by 3 affine patches sage: is_ChowGroup(A) @@ -639,7 +626,7 @@ def __init__(self, toric_variety, base_ring, check): sage: print(coercion_model.get_action(A_ZZ, QQ)) None - You can't multiply integer classes with fractional + You cannot multiply integer classes with fractional numbers. For that you need to go to the rational Chow group:: sage: A_QQ = P2.Chow_group(QQ) @@ -657,13 +644,12 @@ def __init__(self, toric_variety, base_ring, check): self._variety = toric_variety # cones are automatically sorted by dimension - self._cones = flatten( toric_variety.fan().cones() ) + self._cones = flatten(toric_variety.fan().cones()) V = FreeModule(base_ring, len(self._cones)) W = self._rational_equivalence_relations(V) - super(ChowGroup_class,self).__init__(V, W, check) - + super(ChowGroup_class, self).__init__(V, W, check) def scheme(self): r""" @@ -685,7 +671,6 @@ def scheme(self): """ return self._variety - def _element_constructor_(self, x, check=True): r""" Construct a :class:`ChowCycle`. @@ -716,15 +701,14 @@ def _element_constructor_(self, x, check=True): cone = fan.embed(x) return self.element_class(self, self._cone_to_V(cone), False) if is_ToricDivisor(x): - v = sum(x.coefficient(i)*self._cone_to_V(onecone) - for i,onecone in enumerate(fan(1))) + v = sum(x.coefficient(i) * self._cone_to_V(onecone) + for i, onecone in enumerate(fan(1))) return self.element_class(self, v, False) - return super(ChowGroup_class,self)._element_constructor_(x, check) - + return super(ChowGroup_class, self)._element_constructor_(x, check) def _coerce_map_from_(self, S): """ - Return true if S canonically coerces to self. + Return ``True`` if ``S`` canonically coerces to ``self``. EXAMPLES:: @@ -735,9 +719,8 @@ def _coerce_map_from_(self, S): False """ # We might want to coerce Cone_of_fans into ChowCycles - # but cones don't have parents at the moment. - return super(ChowGroup_class,self)._coerce_map_from_(S) - + # but cones do not have parents at the moment. + return super(ChowGroup_class, self)._coerce_map_from_(S) def _rational_equivalence_relations(self, V): r""" @@ -770,8 +753,8 @@ def _rational_equivalence_relations(self, V): for sigma in rho.facet_of(): sigma_idx = self._cones.index(sigma) Q = sigma.relative_quotient(rho) - for v in [n.lift() for n in Q.gens()]: - rel += (u * v) * V.gen(sigma_idx) + for n in Q.gens(): + rel += (u * n.lift()) * V.gen(sigma_idx) relations.append(rel) return V.span(relations) @@ -790,18 +773,17 @@ def __truediv__(self, other): sage: A/Asub Traceback (most recent call last): ... - NotImplementedError: Quotients of the Chow group are not implemented. + NotImplementedError: quotients of the Chow group are not implemented """ - raise NotImplementedError('Quotients of the Chow group are not implemented.') + raise NotImplementedError('quotients of the Chow group are not implemented') - - def _repr_(self): + def _repr_(self) -> str: """ Return a string representation. EXAMPLES:: - sage: P2=toric_varieties.P2() + sage: P2 = toric_varieties.P2() sage: from sage.schemes.toric.chow_group import ChowGroup sage: ChowGroup(P2,ZZ)._repr_() 'Chow group of 2-d CPR-Fano toric variety covered by 3 affine patches' @@ -840,7 +822,6 @@ def _cone_to_V(self, cone): x[self._cones.index(cone)] = 1 return self._V(x) - def degree(self, k=None): r""" Return the degree-`k` Chow group. @@ -939,11 +920,10 @@ def degree(self, k=None): except AttributeError: pass - self._degree = tuple(ChowGroup_degree_class(self,d) + self._degree = tuple(ChowGroup_degree_class(self, d) for d in range(self._variety.dimension() + 1)) return self._degree - def coordinate_vector(self, chow_cycle, degree=None, reduce=True): r""" Return the coordinate vector of the ``chow_cycle``. @@ -981,7 +961,6 @@ def coordinate_vector(self, chow_cycle, degree=None, reduce=True): a = chow_cycle.project_to_degree(degree) return self.degree(degree).module().coordinate_vector(a, reduce=reduce) - def gens(self, degree=None): r""" Return the generators of the Chow group. @@ -1012,7 +991,6 @@ def gens(self, degree=None): else: return self.degree(degree).gens() - def relation_gens(self): r""" Return the Chow cycles equivalent to zero. @@ -1044,7 +1022,6 @@ def relation_gens(self): A tuple of Chow cycles, each rationally equivalent to zero, that generates the rational equivalence. - EXAMPLES:: sage: P2 = toric_varieties.P2() @@ -1057,11 +1034,9 @@ def relation_gens(self): sage: first.lift() (0, 1, 0, -1, 0, 0, 0) """ - gens = self.W().gens() - return tuple( self(gen) for gen in gens ) + return tuple(self(gen) for gen in self.W().gens()) -#******************************************************************* class ChowGroup_degree_class(SageObject): r""" A fixed-degree subgroup of the Chow group of a toric variety. @@ -1119,11 +1094,10 @@ def __init__(self, A, d): # The minimal set of generators self._module = A.submodule(gens) - self._gens = tuple([ A.element_class(A, a.lift(), False) - for a in self._module.gens() ]) - + self._gens = tuple([A.element_class(A, a.lift(), False) + for a in self._module.gens()]) - def _repr_(self): + def _repr_(self) -> str: """ Return a string representation. @@ -1153,7 +1127,7 @@ def _repr_(self): elif self._Chow_group.base_ring() is QQ: ring = 'Q' else: - raise NotImplementedError('Base ring must be ZZ or QQ.') + raise NotImplementedError('base ring must be ZZ or QQ') s = ['C' + str(x) for x in tors] if len(free) == 1: @@ -1179,7 +1153,7 @@ def module(self): """ return self._module - def ngens(self): + def ngens(self) -> int: """ Return the number of generators. @@ -1238,8 +1212,7 @@ def gens(self): return self._gens -#******************************************************************* -def is_ChowGroup(x): +def is_ChowGroup(x) -> bool: r""" Return whether ``x`` is a :class:`ChowGroup_class` @@ -1261,11 +1234,10 @@ def is_ChowGroup(x): sage: is_ChowGroup('Victoria') False """ - return isinstance(x,ChowGroup_class) + return isinstance(x, ChowGroup_class) -#******************************************************************* -def is_ChowCycle(x): +def is_ChowCycle(x) -> bool: r""" Return whether ``x`` is a :class:`ChowGroup_class` @@ -1279,7 +1251,7 @@ def is_ChowCycle(x): EXAMPLES:: - sage: P2=toric_varieties.P2() + sage: P2 = toric_varieties.P2() sage: A = P2.Chow_group() sage: from sage.schemes.toric.chow_group import * sage: is_ChowCycle(A) @@ -1289,4 +1261,4 @@ def is_ChowCycle(x): sage: is_ChowCycle('Victoria') False """ - return isinstance(x,ChowCycle) + return isinstance(x, ChowCycle) From 22f125bcd0544c53c32cead5ccc2bb260f450716 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 28 Sep 2021 15:57:09 -0700 Subject: [PATCH 263/359] src/sage/misc/latex.py: Move import from sage.misc.sage_eval into method --- src/sage/misc/latex.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/misc/latex.py b/src/sage/misc/latex.py index 3aa015bb062..5c9d8680efd 100644 --- a/src/sage/misc/latex.py +++ b/src/sage/misc/latex.py @@ -31,7 +31,6 @@ import shutil from subprocess import call, PIPE -from sage.misc import sage_eval from sage.misc.cachefunc import cached_function, cached_method from sage.misc.sage_ostools import have_program from sage.misc.temporary_file import tmp_dir @@ -1015,6 +1014,7 @@ def _latex_preparse(self, s, locals): sage: sage.misc.latex.Latex()._latex_preparse(r'\sage{s}', locals()) '2' """ + from sage.misc.sage_eval import sage_eval i0 = -1 while True: i = s.find('\\sage{') @@ -1028,7 +1028,7 @@ def _latex_preparse(self, s, locals): var = t[:j] try: - k = str(latex(sage_eval.sage_eval(var, locals))) + k = str(latex(sage_eval(var, locals))) except Exception as msg: print(msg) k = '\\mbox{\\rm [%s undefined]}' % var From 0809840464cd51dc09624d5953894dec04bf9c3b Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 28 Sep 2021 16:22:10 -0700 Subject: [PATCH 264/359] src/sage/misc/latex.py: Move import of have_program into methods --- src/sage/misc/latex.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/sage/misc/latex.py b/src/sage/misc/latex.py index 5c9d8680efd..56a47ea4513 100644 --- a/src/sage/misc/latex.py +++ b/src/sage/misc/latex.py @@ -32,7 +32,6 @@ from subprocess import call, PIPE from sage.misc.cachefunc import cached_function, cached_method -from sage.misc.sage_ostools import have_program from sage.misc.temporary_file import tmp_dir from sage.structure.sage_object import SageObject @@ -81,6 +80,7 @@ def have_latex() -> bool: sage: have_latex() # random True """ + from sage.misc.sage_ostools import have_program return have_program('latex') @@ -98,6 +98,7 @@ def have_pdflatex() -> bool: sage: have_pdflatex() # random True """ + from sage.misc.sage_ostools import have_program return have_program('pdflatex') @@ -115,6 +116,7 @@ def have_xelatex() -> bool: sage: have_xelatex() # random True """ + from sage.misc.sage_ostools import have_program return have_program('xelatex') @@ -132,6 +134,7 @@ def have_dvipng() -> bool: sage: have_dvipng() # random True """ + from sage.misc.sage_ostools import have_program return have_program('dvipng') @@ -150,6 +153,7 @@ def have_convert() -> bool: sage: have_convert() # random True """ + from sage.misc.sage_ostools import have_program return have_program('convert') From bdd032501fd8ad7b5363c4269cdc598c9fd29826 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 28 Sep 2021 16:21:36 -0700 Subject: [PATCH 265/359] sage.repl.display.fancy_repr: For isinstance testing, import abc Matrix from sage.structure.element --- src/sage/repl/display/fancy_repr.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/sage/repl/display/fancy_repr.py b/src/sage/repl/display/fancy_repr.py index de3a5569ba5..6a231d526d8 100644 --- a/src/sage/repl/display/fancy_repr.py +++ b/src/sage/repl/display/fancy_repr.py @@ -200,10 +200,7 @@ def __call__(self, obj, p, cycle): if not p.toplevel(): # Do not print the help for matrices inside containers return False - try: - from sage.matrix.matrix1 import Matrix - except ModuleNotFoundError: - return False + from sage.structure.element import Matrix if not isinstance(obj, Matrix): return False from sage.matrix.constructor import options From e94e96f00087822e829ae46fc70c0ab01a88ec58 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 29 Sep 2021 15:11:05 -0700 Subject: [PATCH 266/359] src/sage/matrix/{matrix_space.py,action.pyx}: Do not fail if sage.schemes is not present --- src/sage/matrix/action.pyx | 7 ++++++- src/sage/matrix/matrix_space.py | 7 +++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/sage/matrix/action.pyx b/src/sage/matrix/action.pyx index 14d2d5cc414..6d4d7853b5f 100644 --- a/src/sage/matrix/action.pyx +++ b/src/sage/matrix/action.pyx @@ -66,7 +66,12 @@ from .matrix_space import MatrixSpace, is_MatrixSpace from sage.modules.free_module import FreeModule, is_FreeModule from sage.structure.coerce cimport coercion_model from sage.categories.homset import Hom, End -from sage.schemes.generic.homset import SchemeHomset_generic, SchemeHomset_points + + +try: + from sage.schemes.generic.homset import SchemeHomset_generic, SchemeHomset_points +except ImportError: + SchemeHomset_generic = SchemeHomset_points = () cdef class MatrixMulAction(Action): diff --git a/src/sage/matrix/matrix_space.py b/src/sage/matrix/matrix_space.py index 47766db0c46..15423ad1b8f 100644 --- a/src/sage/matrix/matrix_space.py +++ b/src/sage/matrix/matrix_space.py @@ -968,8 +968,11 @@ def _get_action_(self, S, op, self_on_left): Left scalar multiplication by Integer Ring on Full MatrixSpace of 2 by 3 dense matrices over Rational Field """ try: - from sage.schemes.generic.homset import SchemeHomset_generic - from sage.schemes.generic.homset import SchemeHomset_points + try: + from sage.schemes.generic.homset import SchemeHomset_generic + from sage.schemes.generic.homset import SchemeHomset_points + except ImportError: + SchemeHomset_generic = SchemeHomset_points = None if op is operator.mul: from . import action as matrix_action if self_on_left: From bc2b707315325ec40dc4e257ce8fa538cbd75b6c Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 5 Oct 2021 10:27:55 -0700 Subject: [PATCH 267/359] sage.misc.lazy_import.finish_startup: Fixup --- src/sage/misc/lazy_import.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/misc/lazy_import.pyx b/src/sage/misc/lazy_import.pyx index 880cf80352c..771c2f600f3 100644 --- a/src/sage/misc/lazy_import.pyx +++ b/src/sage/misc/lazy_import.pyx @@ -98,7 +98,7 @@ cpdef finish_startup(): ... AssertionError: finish_startup() must be called exactly once """ - global startup_guard + global startup_guard, finish_startup_called assert startup_guard, 'finish_startup() must be called exactly once' startup_guard = False finish_startup_called = True From 37ee682cde696bd9a49b61b2f5081f042d4b3f68 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 5 Oct 2021 16:34:57 -0700 Subject: [PATCH 268/359] sage.structure.element.Expression: New abc for sage.symbolic.expression.Expression --- src/sage/structure/element.pxd | 4 +++- src/sage/structure/element.pyx | 11 +++++++++++ src/sage/symbolic/expression.pyx | 3 ++- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/sage/structure/element.pxd b/src/sage/structure/element.pxd index 3cc480aa18c..5c6e295a4b8 100644 --- a/src/sage/structure/element.pxd +++ b/src/sage/structure/element.pxd @@ -236,9 +236,11 @@ cdef class AlgebraElement(RingElement): cdef class CommutativeAlgebraElement(CommutativeRingElement): pass -cdef class InfinityElement(RingElement): +cdef class Expression(CommutativeRingElement): pass +cdef class InfinityElement(RingElement): + pass cdef class Vector(ModuleElementWithMutability): cdef Py_ssize_t _degree diff --git a/src/sage/structure/element.pyx b/src/sage/structure/element.pyx index d610bbb71cc..2e12a318981 100644 --- a/src/sage/structure/element.pyx +++ b/src/sage/structure/element.pyx @@ -47,6 +47,7 @@ abstract base classes. EuclideanDomainElement FieldElement CommutativeAlgebraElement + Expression AlgebraElement Matrix InfinityElement @@ -3254,6 +3255,16 @@ cdef class CommutativeRingElement(RingElement): ############################################## +cdef class Expression(CommutativeRingElement): + + r""" + Abstract base class for :class:`~sage.symbolic.expression.Expression`. + """ + + pass + + ############################################## + cdef class Vector(ModuleElementWithMutability): cdef bint is_sparse_c(self): raise NotImplementedError diff --git a/src/sage/symbolic/expression.pyx b/src/sage/symbolic/expression.pyx index de4720f90a7..5f49c78a260 100644 --- a/src/sage/symbolic/expression.pyx +++ b/src/sage/symbolic/expression.pyx @@ -385,6 +385,7 @@ from cpython.object cimport Py_EQ, Py_NE, Py_LE, Py_GE, Py_LT, Py_GT from sage.cpython.string cimport str_to_bytes, char_to_str from sage.structure.element cimport RingElement, Element, Matrix +from sage.structure.element cimport Expression as Expression_abc from sage.symbolic.complexity_measures import string_length from sage.symbolic.function cimport SymbolicFunction from sage.rings.rational import Rational @@ -694,7 +695,7 @@ def _subs_fun_make_dict(s): raise TypeError(msg.format(s)) -cdef class Expression(CommutativeRingElement): +cdef class Expression(Expression_abc): cdef GEx _gobj From 9830e4eb3a0d8dd387b89891c9d8af73cc668dd8 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 5 Oct 2021 16:39:40 -0700 Subject: [PATCH 269/359] src/sage/misc/lazy_import.pyx: Adjust doctest output to use of warnings.warn --- src/sage/misc/lazy_import.pyx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sage/misc/lazy_import.pyx b/src/sage/misc/lazy_import.pyx index 771c2f600f3..a454bd5d0e4 100644 --- a/src/sage/misc/lazy_import.pyx +++ b/src/sage/misc/lazy_import.pyx @@ -31,7 +31,7 @@ it is actually resolved after the startup, so that the developer knows that (s)he can remove the flag:: sage: ZZ - Option ``at_startup=True`` for lazy import ZZ not needed anymore + UserWarning: Option ``at_startup=True`` for lazy import ZZ not needed anymore Integer Ring .. SEEALSO:: :func:`lazy_import`, :class:`LazyImport` @@ -149,7 +149,7 @@ cpdef test_fake_startup(): sage: sage.misc.lazy_import.test_fake_startup() sage: lazy_import('sage.rings.all', 'ZZ', 'my_ZZ') sage: my_ZZ(123) - Resolving lazy import ZZ during startup + UserWarning: Resolving lazy import ZZ during startup 123 sage: sage.misc.lazy_import.finish_startup() """ @@ -233,7 +233,7 @@ cdef class LazyImport(object): False sage: my_integer_ring = LazyImport('sage.rings.all', 'ZZ', at_startup=True) sage: my_integer_ring - Option ``at_startup=True`` for lazy import ZZ not needed anymore + UserWarning: Option ``at_startup=True`` for lazy import ZZ not needed anymore Integer Ring """ if self._object is not None: From 56d1c36fbe3862ed104560137442774594ad8dab Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 5 Oct 2021 16:49:41 -0700 Subject: [PATCH 270/359] git grep -l -E 'is_Expression' | xargs sed -E -i.bak 's/sage[.]symbolic.*import is_Expression *$/sage.structure.element import Expression/;s/is_Expression[(]([^)]*)[)]/isinstance(\1, Expression)/g;' --- src/sage/calculus/all.py | 4 ++-- src/sage/calculus/integration.pyx | 4 ++-- src/sage/ext/fast_callable.pyx | 8 +++---- src/sage/plot/contour_plot.py | 14 ++++++------ src/sage/plot/plot3d/plot3d.py | 4 ++-- src/sage/rings/padics/factory.py | 12 +++++----- .../schemes/berkovich/berkovich_cp_element.py | 22 +++++++++---------- src/sage/sets/condition_set.py | 4 ++-- src/sage/structure/parent.pyx | 4 ++-- src/sage/symbolic/callable.py | 4 ++-- src/sage/symbolic/comparison_impl.pxi | 14 ++++++------ src/sage/symbolic/expression.pxd | 2 +- src/sage/symbolic/expression.pyx | 14 ++++++------ src/sage/symbolic/function.pyx | 4 ++-- src/sage/symbolic/relation.py | 12 +++++----- src/sage/symbolic/ring.pyx | 2 +- 16 files changed, 64 insertions(+), 64 deletions(-) diff --git a/src/sage/calculus/all.py b/src/sage/calculus/all.py index 1f89c3f7ffe..4cd480570fd 100644 --- a/src/sage/calculus/all.py +++ b/src/sage/calculus/all.py @@ -58,8 +58,8 @@ def symbolic_expression(x): 2*x^2 + 3 sage: type(a) - sage: from sage.symbolic.expression import is_Expression - sage: is_Expression(a) + sage: from sage.structure.element import Expression + sage: isinstance(a, Expression) True sage: a in SR True diff --git a/src/sage/calculus/integration.pyx b/src/sage/calculus/integration.pyx index 56456173632..508ad2d6537 100644 --- a/src/sage/calculus/integration.pyx +++ b/src/sage/calculus/integration.pyx @@ -612,8 +612,8 @@ def monte_carlo_integral(func, xl, xu, size_t calls, algorithm='plain', "more items in upper and lower limits" ).format(len(vars), tuple(vars), target_dim)) - from sage.symbolic.expression import is_Expression - if is_Expression(func): + from sage.structure.element import Expression + if isinstance(func, Expression): if params: to_sub = dict(zip(vars[-len(params):], params)) func = func.subs(to_sub) diff --git a/src/sage/ext/fast_callable.pyx b/src/sage/ext/fast_callable.pyx index 11d4b652ceb..fb26e1f2d50 100644 --- a/src/sage/ext/fast_callable.pyx +++ b/src/sage/ext/fast_callable.pyx @@ -428,7 +428,7 @@ def fast_callable(x, domain=None, vars=None, vars = et._etb._vars else: from sage.symbolic.callable import is_CallableSymbolicExpression - from sage.symbolic.expression import is_Expression + from sage.structure.element import Expression if not vars: # fast_float passes empty list/tuple @@ -439,7 +439,7 @@ def fast_callable(x, domain=None, vars=None, vars = x.arguments() if expect_one_var and len(vars) != 1: raise ValueError(f"passed expect_one_var=True, but the callable expression takes {len(vars)} arguments") - elif is_Expression(x): + elif isinstance(x, Expression): from sage.symbolic.ring import is_SymbolicVariable if vars is None: vars = x.variables() @@ -999,8 +999,8 @@ cdef class Expression: return ExpressionIPow(es._etb, s, o) else: # I really don't like this, but I can't think of a better way - from sage.symbolic.expression import is_Expression - if is_Expression(o) and o in ZZ: + from sage.structure.element import Expression + if isinstance(o, Expression) and o in ZZ: es = s return ExpressionIPow(es._etb, s, ZZ(o)) else: diff --git a/src/sage/plot/contour_plot.py b/src/sage/plot/contour_plot.py index b1d9533c90f..27577d396d6 100644 --- a/src/sage/plot/contour_plot.py +++ b/src/sage/plot/contour_plot.py @@ -1217,8 +1217,8 @@ def f(x,y): options.pop('contours', None) incol = options.pop('fillcolor', 'blue') bordercol = options.pop('cmap', [None])[0] - from sage.symbolic.expression import is_Expression - if not is_Expression(f): + from sage.structure.element import Expression + if not isinstance(f, Expression): return region_plot(lambda x, y: f(x, y) < 0, xrange, yrange, borderwidth=linewidths, borderstyle=linestyles, incol=incol, bordercol=bordercol, @@ -1499,7 +1499,7 @@ def region_plot(f, xrange, yrange, plot_points, incol, outcol, bordercol, """ from sage.plot.all import Graphics from sage.plot.misc import setup_for_eval_on_grid - from sage.symbolic.expression import is_Expression + from sage.structure.element import Expression from warnings import warn import numpy @@ -1507,10 +1507,10 @@ def region_plot(f, xrange, yrange, plot_points, incol, outcol, bordercol, f = [f] feqs = [equify(g) for g in f - if is_Expression(g) and g.operator() is operator.eq + if isinstance(g, Expression) and g.operator() is operator.eq and not equify(g).is_zero()] f = [equify(g) for g in f - if not (is_Expression(g) and g.operator() is operator.eq)] + if not (isinstance(g, Expression) and g.operator() is operator.eq)] neqs = len(feqs) if neqs > 1: warn("There are at least 2 equations; " @@ -1620,8 +1620,8 @@ def equify(f): -1 """ from sage.calculus.all import symbolic_expression - from sage.symbolic.expression import is_Expression - if not is_Expression(f): + from sage.structure.element import Expression + if not isinstance(f, Expression): return lambda x, y: -1 if f(x, y) else 1 op = f.operator() diff --git a/src/sage/plot/plot3d/plot3d.py b/src/sage/plot/plot3d/plot3d.py index d5951640950..d95d332bf18 100644 --- a/src/sage/plot/plot3d/plot3d.py +++ b/src/sage/plot/plot3d/plot3d.py @@ -306,10 +306,10 @@ def to_cartesian(self, func, params=None): Graphics3d Object """ - from sage.symbolic.expression import is_Expression + from sage.structure.element import Expression from sage.rings.real_mpfr import is_RealNumber from sage.rings.integer import is_Integer - if params is not None and (is_Expression(func) or is_RealNumber(func) or is_Integer(func)): + if params is not None and (isinstance(func, Expression) or is_RealNumber(func) or is_Integer(func)): return self.transform(**{ self.dep_var: func, self.indep_vars[0]: params[0], diff --git a/src/sage/rings/padics/factory.py b/src/sage/rings/padics/factory.py index 90c54a2524a..abfce6c44c9 100644 --- a/src/sage/rings/padics/factory.py +++ b/src/sage/rings/padics/factory.py @@ -2534,8 +2534,8 @@ def Zq(q, prec = None, type = 'capped-rel', modulus = None, names=None, prec = Integer(prec) if isinstance(names, (list, tuple)): names = names[0] - from sage.symbolic.expression import is_Expression - if not (modulus is None or is_Polynomial(modulus) or is_Expression(modulus)): + from sage.structure.element import Expression + if not (modulus is None or is_Polynomial(modulus) or isinstance(modulus, Expression)): raise TypeError("modulus must be a polynomial") if names is not None and not isinstance(names, str): names = str(names) @@ -3271,9 +3271,9 @@ def create_key_and_extra_args(self, base, modulus, prec = None, print_mode = Non if print_max_terse_terms is None: print_max_terse_terms = base._printer._max_terse_terms() show_prec = _canonicalize_show_prec(base._prec_type(), print_mode, show_prec) - from sage.symbolic.expression import is_Expression + from sage.structure.element import Expression if check: - if is_Expression(modulus): + if isinstance(modulus, Expression): if len(modulus.variables()) != 1: raise ValueError("symbolic expression must be in only one variable") exact_modulus = modulus.polynomial(base.exact_field()) @@ -3378,8 +3378,8 @@ def create_object(self, version, key, approx_modulus=None, shift_seed=None): if version[0] < 8: (polytype, base, premodulus, approx_modulus, names, prec, halt, print_mode, print_pos, print_sep, print_alphabet, print_max_ram_terms, print_max_unram_terms, print_max_terse_terms, implementation) = key - from sage.symbolic.expression import is_Expression - if is_Expression(premodulus): + from sage.structure.element import Expression + if isinstance(premodulus, Expression): exact_modulus = premodulus.polynomial(base.exact_field()) elif is_Polynomial(premodulus): exact_modulus = premodulus.change_ring(base.exact_field()) diff --git a/src/sage/schemes/berkovich/berkovich_cp_element.py b/src/sage/schemes/berkovich/berkovich_cp_element.py index 9c730a31626..ef419c0b50a 100644 --- a/src/sage/schemes/berkovich/berkovich_cp_element.py +++ b/src/sage/schemes/berkovich/berkovich_cp_element.py @@ -34,7 +34,7 @@ # ***************************************************************************** from sage.structure.element import Element -from sage.symbolic.expression import is_Expression +from sage.structure.element import Expression from sage.rings.real_mpfr import RR, is_RealNumber from sage.rings.padics.padic_generic_element import pAdicGenericElement from sage.rings.padics.padic_base_generic import pAdicBaseGeneric @@ -118,16 +118,16 @@ def __init__(self, parent, center, radius=None, power=None, prec=20, space_type= # check if the radius and the center are functions center_func_check = is_FunctionFieldElement(center) or is_Polynomial(center) or\ - isinstance(center, FractionFieldElement_1poly_field) or is_Expression(center) + isinstance(center, FractionFieldElement_1poly_field) or isinstance(center, Expression) radius_func_check = is_FunctionFieldElement(radius) or is_Polynomial(radius) or\ - isinstance(radius, FractionFieldElement_1poly_field) or is_Expression(radius) + isinstance(radius, FractionFieldElement_1poly_field) or isinstance(radius, Expression) if center_func_check: # check that both center and radii are supported univariate function center_expr_check = False radius_expr_check = False if error_check: - if is_Expression(center): + if isinstance(center, Expression): if len(center.variables()) != 1: raise ValueError("an expression with %s " % (len(center.variables())) + "variables cannot define the centers approximating a type IV point") @@ -136,16 +136,16 @@ def __init__(self, parent, center, radius=None, power=None, prec=20, space_type= center_expr_check = True if not radius_func_check: raise TypeError("center was passed a function but radius was not a function") - if is_Expression(radius): + if isinstance(radius, Expression): if len(radius.variables()) != 1: raise ValueError("an expression with %s " % (len(radius.variables())) + "variables cannot define the radii approximating a type IV point") else: radius_expr_check = True else: - if is_Expression(center): + if isinstance(center, Expression): center_expr_check = True - if is_Expression(radius): + if isinstance(radius, Expression): radius_expr_check = True self._type = 4 self._prec = prec @@ -216,7 +216,7 @@ def __init__(self, parent, center, radius=None, power=None, prec=20, space_type= center.normalize_coordinates() # make sure the radius coerces into the reals if not is_RealNumber(radius): - if is_Expression(radius): + if isinstance(radius, Expression): radius = RR(radius) elif RR.has_coerce_map_from(radius.parent()): radius = RR(radius) @@ -259,7 +259,7 @@ def __init__(self, parent, center, radius=None, power=None, prec=20, space_type= raise ValueError('could not convert %s to %s' % (center, self._base_space)) # make sure the radius coerces into the reals if not is_RealNumber(radius): - if is_Expression(radius): + if isinstance(radius, Expression): radius = RR(radius) elif RR.has_coerce_map_from(radius.parent()): radius = RR(radius) @@ -375,7 +375,7 @@ def __init__(self, parent, center, radius=None, power=None, prec=20, space_type= self._type = 2 return if radius is not None: - if is_Expression(radius): + if isinstance(radius, Expression): try: power = QQ(radius.log(self._p).expand_log()) except TypeError: @@ -659,7 +659,7 @@ def diameter(self, basepoint=Infinity): from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing R = PolynomialRing(QQ, names="x") x = R.gens()[0] - if is_Expression(self._radius_func): + if isinstance(self._radius_func, Expression): radius_func_variable = self._radius_func.variables()[0] radius_expr = self._radius_func.subs({radius_func_variable: x}) else: diff --git a/src/sage/sets/condition_set.py b/src/sage/sets/condition_set.py index 757014ace6c..2660a52077b 100644 --- a/src/sage/sets/condition_set.py +++ b/src/sage/sets/condition_set.py @@ -19,7 +19,7 @@ from sage.categories.enumerated_sets import EnumeratedSets from sage.misc.cachefunc import cached_method from sage.misc.misc import _stable_uniq -from sage.symbolic.expression import is_Expression +from sage.structure.element import Expression from sage.symbolic.callable import is_CallableSymbolicExpression from sage.symbolic.ring import SR @@ -165,7 +165,7 @@ def __classcall_private__(cls, universe, *predicates, vars=None, names=None, cat if vars is None: vars = predicate.args() callable_symbolic_predicates.append(predicate) - elif is_Expression(predicate): + elif isinstance(predicate, Expression): if names is None: raise TypeError('use callable symbolic expressions or provide variable names') if vars is None: diff --git a/src/sage/structure/parent.pyx b/src/sage/structure/parent.pyx index 4559972c94f..53df4273f29 100644 --- a/src/sage/structure/parent.pyx +++ b/src/sage/structure/parent.pyx @@ -1169,8 +1169,8 @@ cdef class Parent(sage.structure.category_object.CategoryObject): elif EQ: return True else: - from sage.symbolic.expression import is_Expression - return is_Expression(EQ) + from sage.structure.element import Expression + return isinstance(EQ, Expression) # if comparing gives an Expression, then it must be an equation. # We return *true* here, even though the equation # EQ must have evaluated to False for us to get to diff --git a/src/sage/symbolic/callable.py b/src/sage/symbolic/callable.py index 758fa7ff790..f1a45811db8 100644 --- a/src/sage/symbolic/callable.py +++ b/src/sage/symbolic/callable.py @@ -109,8 +109,8 @@ def is_CallableSymbolicExpression(x): sage: is_CallableSymbolicExpression(foo) False """ - from sage.symbolic.expression import is_Expression - return is_Expression(x) and isinstance(x.parent(), CallableSymbolicExpressionRing_class) + from sage.structure.element import Expression + return isinstance(x, Expression) and isinstance(x.parent(), CallableSymbolicExpressionRing_class) class CallableSymbolicExpressionFunctor(ConstructionFunctor): def __init__(self, arguments): diff --git a/src/sage/symbolic/comparison_impl.pxi b/src/sage/symbolic/comparison_impl.pxi index 9d73c7359fe..2b112b271cd 100644 --- a/src/sage/symbolic/comparison_impl.pxi +++ b/src/sage/symbolic/comparison_impl.pxi @@ -79,9 +79,9 @@ cpdef int print_order(lhs, rhs) except -2: sage: print_order(SR(oo), sqrt(2)) 1 """ - if not is_Expression(lhs): + if not isinstance(lhs, Expression): lhs = SR(lhs) - if not is_Expression(rhs): + if not isinstance(rhs, Expression): rhs = SR(rhs) return print_order_c(lhs, rhs) @@ -103,7 +103,7 @@ class _print_key(object): sage: _print_key(1) """ - self.ex = ex if is_Expression(ex) else SR(ex) + self.ex = ex if isinstance(ex, Expression) else SR(ex) def __lt__(self, other): """ @@ -171,7 +171,7 @@ class _math_key(object): sage: _math_key(1) """ - self.ex = ex if is_Expression(ex) else SR(ex) + self.ex = ex if isinstance(ex, Expression) else SR(ex) def __lt__(self, other): """ @@ -283,9 +283,9 @@ cpdef int mixed_order(lhs, rhs) except -2: """ if lhs is rhs: return 0 - if not is_Expression(lhs): + if not isinstance(lhs, Expression): lhs = SR(lhs) - if not is_Expression(rhs): + if not isinstance(rhs, Expression): rhs = SR(rhs) less_than = _mixed_key(lhs) < _mixed_key(rhs) if less_than: @@ -318,7 +318,7 @@ class _mixed_key(object): sage: _mixed_key(1) """ - self.ex = ex if is_Expression(ex) else SR(ex) + self.ex = ex if isinstance(ex, Expression) else SR(ex) def __lt__(self, other): """ diff --git a/src/sage/symbolic/expression.pxd b/src/sage/symbolic/expression.pxd index 1fa578d43c3..be27fb8b224 100644 --- a/src/sage/symbolic/expression.pxd +++ b/src/sage/symbolic/expression.pxd @@ -1,4 +1,4 @@ -cpdef bint is_Expression(x) +cpdef bint isinstance(x, Expression) cpdef _repr_Expression(x) cpdef _latex_Expression(x) cpdef new_Expression(parent, x) diff --git a/src/sage/symbolic/expression.pyx b/src/sage/symbolic/expression.pyx index 5f49c78a260..ed615c42429 100644 --- a/src/sage/symbolic/expression.pyx +++ b/src/sage/symbolic/expression.pyx @@ -406,18 +406,18 @@ include "pynac.pxi" include "pynac_impl.pxi" -cpdef bint is_Expression(x): +cpdef bint isinstance(x, Expression): """ Return True if *x* is a symbolic Expression. EXAMPLES:: - sage: from sage.symbolic.expression import is_Expression - sage: is_Expression(x) + sage: from sage.structure.element import Expression + sage: isinstance(x, Expression) True - sage: is_Expression(2) + sage: isinstance(2, Expression) False - sage: is_Expression(SR(2)) + sage: isinstance(SR(2, Expression)) True """ return isinstance(x, Expression) @@ -473,7 +473,7 @@ cpdef bint _is_SymbolicVariable(x): sage: ZZ['x'] Univariate Polynomial Ring in x over Integer Ring """ - return is_Expression(x) and is_a_symbol((x)._gobj) + return isinstance(x, Expression) and is_a_symbol((x)._gobj) def _dict_update_check_duplicate(dict d1, dict d2): @@ -13579,7 +13579,7 @@ cpdef new_Expression(parent, x): x + 1 """ cdef GEx exp - if is_Expression(x): + if isinstance(x, Expression): return new_Expression_from_GEx(parent, (x)._gobj) if hasattr(x, '_symbolic_'): return x._symbolic_(parent) diff --git a/src/sage/symbolic/function.pyx b/src/sage/symbolic/function.pyx index 7feef512673..15fe84b3195 100644 --- a/src/sage/symbolic/function.pyx +++ b/src/sage/symbolic/function.pyx @@ -334,7 +334,7 @@ cdef class Function(SageObject): try: evalf = self._evalf_ # catch AttributeError early if any(self._is_numerical(x) for x in args): - if not any(is_Expression(x) for x in args): + if not any(isinstance(x, Expression) for x in args): p = coercion_model.common_parent(*args) return evalf(*args, parent=p) except Exception: @@ -553,7 +553,7 @@ cdef class Function(SageObject): else: # coerce == False for a in args: - if not is_Expression(a): + if not isinstance(a, Expression): raise TypeError("arguments must be symbolic expressions") return call_registered_function(self._serial, self._nargs, args, hold, diff --git a/src/sage/symbolic/relation.py b/src/sage/symbolic/relation.py index 28b1bce0301..698eed45d0e 100644 --- a/src/sage/symbolic/relation.py +++ b/src/sage/symbolic/relation.py @@ -1058,14 +1058,14 @@ def solve(f, *args, **kwds): if isinstance(f, (list, tuple)) and len(f) == 1: # f is a list with a single element - if is_Expression(f[0]): + if isinstance(f[0], Expression): f = f[0] else: raise TypeError("The first argument to solve() should be a " "symbolic expression or a list of symbolic " "expressions.") - if is_Expression(f): # f is a single expression + if isinstance(f, Expression): # f is a single expression return _solve_expression(f, x, explicit_solutions, multiplicities, to_poly_solve, solution_dict, algorithm, domain) if not isinstance(f, (list, tuple)): @@ -1095,7 +1095,7 @@ def solve(f, *args, **kwds): if algorithm == 'sympy': from sympy import solve as ssolve from sage.interfaces.sympy import sympy_set_to_list - if is_Expression(f): # f is a single expression + if isinstance(f, Expression): # f is a single expression sympy_f = f._sympy_() else: sympy_f = [s._sympy_() for s in f] @@ -1103,7 +1103,7 @@ def solve(f, *args, **kwds): sympy_vars = (x._sympy_(),) else: sympy_vars = tuple([v._sympy_() for v in x]) - if len(sympy_vars) > 1 or not is_Expression(f): + if len(sympy_vars) > 1 or not isinstance(f, Expression): ret = ssolve(sympy_f, sympy_vars, dict=True) if isinstance(ret, dict): if solution_dict: @@ -1569,14 +1569,14 @@ def solve_mod(eqns, modulus, solution_dict=False): """ from sage.rings.all import Integer, Integers, crt_basis - from sage.symbolic.expression import is_Expression + from sage.structure.element import Expression from sage.misc.all import cartesian_product_iterator from sage.modules.all import vector from sage.matrix.all import matrix if not isinstance(eqns, (list, tuple)): eqns = [eqns] - eqns = [eq if is_Expression(eq) else (eq.lhs() - eq.rhs()) for eq in eqns] + eqns = [eq if isinstance(eq, Expression) else (eq.lhs() - eq.rhs()) for eq in eqns] modulus = Integer(modulus) if modulus < 1: raise ValueError("the modulus must be a positive integer") diff --git a/src/sage/symbolic/ring.pyx b/src/sage/symbolic/ring.pyx index ffe8d7443f2..cca5dec8fee 100644 --- a/src/sage/symbolic/ring.pyx +++ b/src/sage/symbolic/ring.pyx @@ -870,7 +870,7 @@ cdef class SymbolicRing(CommutativeRing): ... ValueError: cannot specify n for multiple symbol names """ - if is_Expression(name): + if isinstance(name, Expression): return name if not isinstance(name, (basestring, list, tuple)): name = repr(name) From 08bf900dd929f3859110130c98155e4fbe1d95e4 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 5 Oct 2021 16:54:12 -0700 Subject: [PATCH 271/359] is_Expression: Undo automatic edit of the definition; deprecate --- src/sage/symbolic/expression.pyx | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/sage/symbolic/expression.pyx b/src/sage/symbolic/expression.pyx index ed615c42429..3f6cb7b0f3d 100644 --- a/src/sage/symbolic/expression.pyx +++ b/src/sage/symbolic/expression.pyx @@ -406,20 +406,24 @@ include "pynac.pxi" include "pynac_impl.pxi" -cpdef bint isinstance(x, Expression): +cpdef bint is_Expression(x): """ Return True if *x* is a symbolic Expression. EXAMPLES:: - sage: from sage.structure.element import Expression - sage: isinstance(x, Expression) + sage: from sage.symbolic.expression import is_Expression + sage: is_Expression(x) + DeprecationWarning: is_Expression is deprecated; + use isinstance(..., sage.structure.element.Expression) instead True - sage: isinstance(2, Expression) + sage: is_Expression(2) False - sage: isinstance(SR(2, Expression)) + sage: is_Expression(SR(2)) True """ + from sage.misc.superseded import deprecation + deprecation(32638, 'is_Expression is deprecated; use isinstance(..., sage.structure.element.Expression) instead') return isinstance(x, Expression) From 4e5fe35817b7bc335af222e540e367b7704e2661 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 5 Oct 2021 18:56:37 -0700 Subject: [PATCH 272/359] src/sage/symbolic/expression.pxd: Undo automatic edit --- src/sage/symbolic/expression.pxd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/symbolic/expression.pxd b/src/sage/symbolic/expression.pxd index be27fb8b224..1fa578d43c3 100644 --- a/src/sage/symbolic/expression.pxd +++ b/src/sage/symbolic/expression.pxd @@ -1,4 +1,4 @@ -cpdef bint isinstance(x, Expression) +cpdef bint is_Expression(x) cpdef _repr_Expression(x) cpdef _latex_Expression(x) cpdef new_Expression(parent, x) From dadfa07f6bf9356db6c971b51ee320fbb04481f2 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 5 Oct 2021 19:02:18 -0700 Subject: [PATCH 273/359] src/sage/misc/lazy_import.pyx: Fix markup of doctest output --- src/sage/misc/lazy_import.pyx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/sage/misc/lazy_import.pyx b/src/sage/misc/lazy_import.pyx index a454bd5d0e4..71839dc2ef8 100644 --- a/src/sage/misc/lazy_import.pyx +++ b/src/sage/misc/lazy_import.pyx @@ -31,6 +31,7 @@ it is actually resolved after the startup, so that the developer knows that (s)he can remove the flag:: sage: ZZ + doctest:warning... UserWarning: Option ``at_startup=True`` for lazy import ZZ not needed anymore Integer Ring @@ -149,6 +150,7 @@ cpdef test_fake_startup(): sage: sage.misc.lazy_import.test_fake_startup() sage: lazy_import('sage.rings.all', 'ZZ', 'my_ZZ') sage: my_ZZ(123) + doctest:warning... UserWarning: Resolving lazy import ZZ during startup 123 sage: sage.misc.lazy_import.finish_startup() @@ -233,6 +235,7 @@ cdef class LazyImport(object): False sage: my_integer_ring = LazyImport('sage.rings.all', 'ZZ', at_startup=True) sage: my_integer_ring + doctest:warning... UserWarning: Option ``at_startup=True`` for lazy import ZZ not needed anymore Integer Ring """ From e14259b90bb05950c575731090220f08f41f563f Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 5 Oct 2021 19:14:48 -0700 Subject: [PATCH 274/359] src/sage/ext/fast_callable.pyx: Fix up clash of sage.ext.fast_callable.Expression and sage.structure.element.Expression --- src/sage/ext/fast_callable.pyx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/sage/ext/fast_callable.pyx b/src/sage/ext/fast_callable.pyx index fb26e1f2d50..50fb5e21f7a 100644 --- a/src/sage/ext/fast_callable.pyx +++ b/src/sage/ext/fast_callable.pyx @@ -308,6 +308,7 @@ from sage.rings.all import RDF, CDF from sage.rings.integer import Integer from sage.rings.integer_ring import ZZ from sage.structure.element cimport parent +from sage.structure.element cimport Expression as Expression_abc def fast_callable(x, domain=None, vars=None, @@ -428,7 +429,6 @@ def fast_callable(x, domain=None, vars=None, vars = et._etb._vars else: from sage.symbolic.callable import is_CallableSymbolicExpression - from sage.structure.element import Expression if not vars: # fast_float passes empty list/tuple @@ -439,7 +439,7 @@ def fast_callable(x, domain=None, vars=None, vars = x.arguments() if expect_one_var and len(vars) != 1: raise ValueError(f"passed expect_one_var=True, but the callable expression takes {len(vars)} arguments") - elif isinstance(x, Expression): + elif isinstance(x, Expression_abc): from sage.symbolic.ring import is_SymbolicVariable if vars is None: vars = x.variables() @@ -999,8 +999,7 @@ cdef class Expression: return ExpressionIPow(es._etb, s, o) else: # I really don't like this, but I can't think of a better way - from sage.structure.element import Expression - if isinstance(o, Expression) and o in ZZ: + if isinstance(o, Expression_abc) and o in ZZ: es = s return ExpressionIPow(es._etb, s, ZZ(o)) else: From daed11ede2e3dd63897eb16cda2a23d56b0dc220 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 5 Oct 2021 21:20:17 -0700 Subject: [PATCH 275/359] src/sage/symbolic/function.pyx: Update imports --- src/sage/symbolic/function.pyx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/sage/symbolic/function.pyx b/src/sage/symbolic/function.pyx index 15fe84b3195..7d7773163b8 100644 --- a/src/sage/symbolic/function.pyx +++ b/src/sage/symbolic/function.pyx @@ -139,12 +139,11 @@ is attempted, and after that ``sin()`` which succeeds:: #***************************************************************************** from sage.structure.sage_object cimport SageObject -from sage.structure.element cimport Element, parent +from sage.structure.element cimport Element, parent, Expression from sage.misc.lazy_attribute import lazy_attribute from .expression import ( call_registered_function, find_registered_function, register_or_update_function, - get_sfunction_from_hash, - is_Expression + get_sfunction_from_hash ) from .expression import get_sfunction_from_serial as get_sfunction_from_serial From c52251b59f888d3d9a2821ee5189daff95d056a9 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 5 Oct 2021 21:21:18 -0700 Subject: [PATCH 276/359] src/sage/symbolic/ring.pyx: Update imports --- src/sage/symbolic/ring.pyx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/sage/symbolic/ring.pyx b/src/sage/symbolic/ring.pyx index cca5dec8fee..512c996a8d3 100644 --- a/src/sage/symbolic/ring.pyx +++ b/src/sage/symbolic/ring.pyx @@ -34,7 +34,6 @@ The symbolic ring from sage.rings.integer cimport Integer from sage.symbolic.expression cimport ( - is_Expression, _latex_Expression, _repr_Expression, new_Expression, @@ -43,7 +42,7 @@ from sage.symbolic.expression cimport ( new_Expression_symbol, ) -from sage.structure.element cimport Element +from sage.structure.element cimport Element, Expression from sage.categories.morphism cimport Morphism from sage.structure.coerce cimport is_numpy_type From 98d2e9b0ebb6d56b18518ec2624592532fac034a Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 5 Oct 2021 22:43:27 -0700 Subject: [PATCH 277/359] src/sage/misc/lazy_import.pyx: In test_fake_startup, also reset finish_startup_called --- src/sage/misc/lazy_import.pyx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/sage/misc/lazy_import.pyx b/src/sage/misc/lazy_import.pyx index 71839dc2ef8..fb06fa01f56 100644 --- a/src/sage/misc/lazy_import.pyx +++ b/src/sage/misc/lazy_import.pyx @@ -155,8 +155,9 @@ cpdef test_fake_startup(): 123 sage: sage.misc.lazy_import.finish_startup() """ - global startup_guard + global startup_guard, finish_startup_called startup_guard = True + finish_startup_called = False @cython.final From 5a9ca1efca281c47c4345b2007147cb6cd6f93fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Wed, 6 Oct 2021 09:50:20 +0200 Subject: [PATCH 278/359] enumeration of linear intervals in posets --- src/sage/combinat/posets/hasse_diagram.py | 31 ++++++++++++++ src/sage/combinat/posets/posets.py | 52 ++++++++++++++++++++++- 2 files changed, 82 insertions(+), 1 deletion(-) diff --git a/src/sage/combinat/posets/hasse_diagram.py b/src/sage/combinat/posets/hasse_diagram.py index 17c632e9b02..e8c0d6b92b2 100644 --- a/src/sage/combinat/posets/hasse_diagram.py +++ b/src/sage/combinat/posets/hasse_diagram.py @@ -2353,6 +2353,37 @@ def chains(self, element_class=list, exclude=None, conversion=None): """ return IncreasingChains(self._leq_storage, element_class, exclude, conversion) + def is_linear_interval(self, t_min, t_max) -> bool: + """ + Return whether the interval ``[t_min, t_max]`` is linear. + + This means that this interval is a total order. + + .. WARNING:: + + For speed, this assumes that the input is an interval! + + EXAMPLES:: + + sage: P = posets.PentagonPoset() + sage: H = P._hasse_diagram + sage: H.is_linear_interval(0,4) + False + sage: H.is_linear_interval(0,3) + True + """ + t = t_max + while t != t_min: + found = False + for u in self.neighbor_in_iterator(t): + if self.is_lequal(t_min, u): + if not found: + found = True + t = u + else: + return False + return True + def diamonds(self): r""" Return the list of diamonds of ``self``. diff --git a/src/sage/combinat/posets/posets.py b/src/sage/combinat/posets/posets.py index 3c5b56dedf2..f987759cae4 100644 --- a/src/sage/combinat/posets/posets.py +++ b/src/sage/combinat/posets/posets.py @@ -66,6 +66,7 @@ :meth:`~FinitePoset.height` | Return the number of elements in a longest chain of the poset. :meth:`~FinitePoset.width` | Return the number of elements in a longest antichain of the poset. :meth:`~FinitePoset.relations_number` | Return the number of relations in the poset. + :meth:`~FinitePoset.linear_intervals_count` | Return the enumeration of linear intervals in the poset. :meth:`~FinitePoset.dimension` | Return the dimension of the poset. :meth:`~FinitePoset.jump_number` | Return the jump number of the poset. :meth:`~FinitePoset.magnitude` | Return the magnitude of the poset. @@ -281,8 +282,9 @@ # (at your option) any later version. # https://www.gnu.org/licenses/ # **************************************************************************** - +from __future__ import annotations from copy import copy, deepcopy + from sage.misc.cachefunc import cached_method from sage.misc.lazy_attribute import lazy_attribute from sage.misc.misc_c import prod @@ -2649,6 +2651,54 @@ def relations_number(self): # Maybe this should also be deprecated. intervals_number = relations_number + def linear_intervals_count(self) -> list[int]: + """ + Return the enumeration of linear intervals w.r.t. their cardinality. + + An interval is linear if it is a total order. + + OUTPUT: list of integers + + EXAMPLES:: + + sage: P = posets.PentagonPoset() + sage: P.linear_intervals_count() + [5, 5, 2] + sage: P = posets.TamariLattice(4) + sage: P.linear_intervals_count() + [14, 21, 12, 2] + + TESTS:: + + sage: P = Poset() + sage: P.linear_intervals_count() + [] + """ + if not self.cardinality(): + return [] + H = self._hasse_diagram + stock = [(x, x, x) for x in H] + poly = [len(stock)] + exposant = 0 + while True: + exposant += 1 + next_stock = [] + short_stock = [(ch[0], ch[2]) for ch in stock] + for xmin, cov_xmin, xmax in stock: + for y in H.neighbor_out_iterator(xmax): + if exposant == 1: + next_stock.append((xmin, y, y)) + else: + if (cov_xmin, y) in short_stock: + if H.is_linear_interval(xmin, y): + next_stock.append((xmin, cov_xmin, y)) + if next_stock: + poly.append(len(next_stock)) + stock = next_stock + else: + break + return poly + def is_incomparable_chain_free(self, m, n=None) -> bool: r""" Return ``True`` if the poset is `(m+n)`-free, and ``False`` otherwise. From c5d3cccacfdd8b3ccf7337453abdb38853fe827b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Tue, 5 Oct 2021 20:29:09 +0200 Subject: [PATCH 279/359] partial pep cleanup of one cluster file --- .../quiver_mutation_type.py | 791 +++++++++--------- 1 file changed, 398 insertions(+), 393 deletions(-) diff --git a/src/sage/combinat/cluster_algebra_quiver/quiver_mutation_type.py b/src/sage/combinat/cluster_algebra_quiver/quiver_mutation_type.py index b819aed8966..4a8d8816fa1 100644 --- a/src/sage/combinat/cluster_algebra_quiver/quiver_mutation_type.py +++ b/src/sage/combinat/cluster_algebra_quiver/quiver_mutation_type.py @@ -15,7 +15,7 @@ # Distributed under the terms of the GNU General Public License (GPL) # https://www.gnu.org/licenses/ # *************************************************************************** - +from __future__ import annotations import os import pickle @@ -62,12 +62,12 @@ def __call__(self, *args): _mutation_type_error(data) # check for reducible types - if all( type( data_component ) in [list,tuple,QuiverMutationType_Irreducible] for data_component in data ): + if all(type(data_component) in [list, tuple, QuiverMutationType_Irreducible] for data_component in data): if len(data) == 1: return QuiverMutationType(data[0]) else: - data = tuple( QuiverMutationType(comp) for comp in data ) - return QuiverMutationType_Reducible( *data ) + data = tuple(QuiverMutationType(comp) for comp in data) + return QuiverMutationType_Reducible(*data) # check for irreducible types if len(data) == 2: @@ -83,114 +83,114 @@ def __call__(self, *args): data = (data[0], tuple(data[1]), data[2]) # mutation type casting - if data == ('D',2,None): - return QuiverMutationType( ('A',1,None), ('A',1,None) ) - elif data == ('D',3,None): - data = ('A',3,None) - elif data == ('C',2,None): - data = ('B',2,None) - elif data == ('E',9,None): - data = ('E',8,1) + if data == ('D', 2, None): + return QuiverMutationType(('A', 1, None), ('A', 1, None)) + elif data == ('D', 3, None): + data = ('A', 3, None) + elif data == ('C', 2, None): + data = ('B', 2, None) + elif data == ('E', 9, None): + data = ('E', 8, 1) elif data[0] == 'A' and data[2] == 1 and isinstance(data[1], tuple) and len(data[1]) == 2 and min(data[1]) == 0: if max(data[1]) == 0: pass elif max(data[1]) == 1: - data = ('A', 1,None) + data = ('A', 1, None) elif max(data[1]) == 2: - return QuiverMutationType( ('A',1,None), ('A',1,None) ) + return QuiverMutationType(('A', 1, None), ('A', 1, None)) elif max(data[1]) == 3: - data = ('A',3,None) + data = ('A', 3, None) else: - data = ('D',max(data[1]),None) + data = ('D', max(data[1]), None) elif data[0] == 'GR' and data[2] is None and isinstance(data[1], tuple) and len(data[1]) == 2 and data[1][1] > data[1][0]: - if min(data[1]) > max(data[1])/2 and max(data[1]) != min(data[1])+1: - data = (data[0],(max(data[1])-min(data[1]),max(data[1])),data[2]) + if min(data[1]) > max(data[1]) / 2 and max(data[1]) != min(data[1]) + 1: + data = (data[0], (max(data[1]) - min(data[1]), max(data[1])), data[2]) if min(data[1]) == 2 and max(data[1]) > 3: - data = ('A',max(data[1])-3,None) - elif data[1] == (3,6): - data = ('D',4,None) - elif data[1] == (3,7): - data = ('E',6,None) - elif data[1] == (3,8): - data = ('E',8,None) - elif data[1] == (3,9): - data = ('E',8,[1,1]) - elif data[1] == (4,8): - data = ('E',7,[1,1]) - elif data == ('TR',1,None): - data = ('A',1,None) - elif data == ('TR',2,None): - data = ('A',3,None) - elif data == ('TR',3,None): - data = ('D',6,None) - elif data == ('TR',4,None): - data = ('E',8,(1,1)) + data = ('A', max(data[1]) - 3, None) + elif data[1] == (3, 6): + data = ('D', 4, None) + elif data[1] == (3, 7): + data = ('E', 6, None) + elif data[1] == (3, 8): + data = ('E', 8, None) + elif data[1] == (3, 9): + data = ('E', 8, [1, 1]) + elif data[1] == (4, 8): + data = ('E', 7, [1, 1]) + elif data == ('TR', 1, None): + data = ('A', 1, None) + elif data == ('TR', 2, None): + data = ('A', 3, None) + elif data == ('TR', 3, None): + data = ('D', 6, None) + elif data == ('TR', 4, None): + data = ('E', 8, (1, 1)) # mutation type casting from Kac conventions - elif data == ('A',1,1): - data = ('A',(1,1),1) + elif data == ('A', 1, 1): + data = ('A', (1, 1), 1) elif data[0] == 'B' and data[2] == 1: if data[1] == 2: - data = ('CC',2,1) + data = ('CC', 2, 1) elif data[1] > 2: - data = ('BD',data[1],1) + data = ('BD', data[1], 1) elif data[0] == 'B' and data[2] == -1: if data[1] == 2: - data = ('BB',2,1) + data = ('BB', 2, 1) elif data[1] > 2: data = ('CD', data[1], 1) elif data[0] == 'C' and data[1] > 1 and data[2] == 1: - data = ('CC', data[1],1) + data = ('CC', data[1], 1) elif data[0] == 'C' and data[1] > 1 and data[2] == -1: data = ('BB', data[1], 1) - elif data == ('A',2,2): + elif data == ('A', 2, 2): data = ('BC', 1, 1) elif data[0] == 'A' and data[1] in ZZ and data[1] > 1 and data[1] % 2 == 0 and data[2] == 2: data = ('BC', data[1] // 2, 1) elif data[0] == 'A' and data[1] in ZZ and data[1] > 3 and data[1] % 2 and data[2] == 2: data = ('CD', (data[1] + 1) // 2, 1) - # We think of ('A',3,2) as ('D',3,2) - elif data == ('A',3,2): - data = ('BB',2,1) + # We think of ('A',3, 2) as ('D',3, 2) + elif data == ('A', 3, 2): + data = ('BB', 2, 1) elif data[0] == 'D' and data[1] in ZZ and data[1] > 2 and data[2] == 2: - data = ('BB',data[1]-1,1) - elif data == ('E',6,2): - data = ('F',4,-1) - elif data == ('D',4,3): - data = ('G',2,-1) - elif data == ('F',4,(2,1)): - data = ('F',4,(1,2)) - elif data == ('G',2,(3,1)): - data = ('G',2,(1,3)) + data = ('BB', data[1] - 1, 1) + elif data == ('E', 6, 2): + data = ('F', 4, -1) + elif data == ('D', 4, 3): + data = ('G', 2, -1) + elif data == ('F', 4, (2, 1)): + data = ('F', 4, (1, 2)) + elif data == ('G', 2, (3, 1)): + data = ('G', 2, (1, 3)) elif data[0] == 'T' and data[2] is None: - data = (data[0],tuple(sorted(data[1])),data[2]) - r,p,q = data[1] + data = (data[0], tuple(sorted(data[1])), data[2]) + r, p, q = data[1] if r == 1: - data = ('A',p+q-1,None) + data = ('A', p + q - 1, None) elif r == p == 2: - data = ('D',q+2,None) + data = ('D', q + 2, None) elif r == 2 and p == 3: - if q in (3,4,5): - data = ('E',q+3,None) + if q in (3, 4, 5): + data = ('E', q + 3, None) elif q == 6: - data = ('E',8,1) + data = ('E', 8, 1) else: - data = ('E',q+3,None) + data = ('E', q + 3, None) elif r == 2 and p == q == 4: - data = ('E',7,1) + data = ('E', 7, 1) elif r == p == q == 3: - data = ('E',6,1) - elif data[0] == 'R2' and data[2] is None and all(data[1][i] in ZZ and data[1][i] > 0 for i in [0,1]): + data = ('E', 6, 1) + elif data[0] == 'R2' and data[2] is None and all(data[1][i] in ZZ and data[1][i] > 0 for i in [0, 1]): data = (data[0], tuple(sorted(data[1])), data[2]) - if data[1] == (1,1): - data = ('A',2,None) - elif data[1] == (1,2): - data = ('B',2,None) - elif data[1] == (1,3): - data = ('G',2,None) - elif data[1] == (1,4): - data = ('BC',1,1) - elif data[1] == (2,2): - data = ('A',(1,1),1) + if data[1] == (1, 1): + data = ('A', 2, None) + elif data[1] == (1, 2): + data = ('B', 2, None) + elif data[1] == (1, 3): + data = ('G', 2, None) + elif data[1] == (1, 4): + data = ('BC', 1, 1) + elif data[1] == (2, 2): + data = ('A', (1, 1), 1) # setting the parameters and returning the mutation type letter, rank, twist = data @@ -200,9 +200,9 @@ def __call__(self, *args): rank = tuple(rank) if isinstance(twist, list): twist = tuple(twist) - return QuiverMutationType_Irreducible(letter,rank,twist) + return QuiverMutationType_Irreducible(letter, rank, twist) - def _repr_(self): + def _repr_(self) -> str: """ Return the string representation of ``self``. @@ -284,13 +284,13 @@ def _samples(self): ["E", 6], ["E", 7], ["E", 8], ["F", 4], ["G", 2]]] affine_types = \ - [QuiverMutationType(t) for t in [['A', [1,1], 1], ['A', [4,5], 1], ['D', 4, 1], ['BB', 5, 1]]] + [QuiverMutationType(t) for t in [['A', [1, 1], 1], ['A', [4, 5], 1], ['D', 4, 1], ['BB', 5, 1]]] elliptic_types = \ - [QuiverMutationType(t) for t in [['E', 6, [1,1]], ['E', 7, [1,1]]]] + [QuiverMutationType(t) for t in [['E', 6, [1, 1]], ['E', 7, [1, 1]]]] mutation_finite_types = \ - [QuiverMutationType(t) for t in [['R2',(1,5)], ['R2',(3,5)]]] + [QuiverMutationType(t) for t in [['R2', (1, 5)], ['R2', (3, 5)]]] mutation_infinite_types = \ - [QuiverMutationType(t) for t in [['E',10], ['BE',5], ['GR',(3,10)], ['T',(3,3,4)]]] + [QuiverMutationType(t) for t in [['E', 10], ['BE', 5], ['GR', (3, 10)], ['T', (3, 3, 4)]]] return finite_types + affine_types + elliptic_types + mutation_finite_types + mutation_infinite_types @@ -299,7 +299,7 @@ def _samples(self): QuiverMutationType.__doc__ = \ -r""" + r""" *Quiver mutation types* can be seen as a slight generalization of *generalized Cartan types*. @@ -358,7 +358,7 @@ def _samples(self): ``BC`` and ``rank=1``. * Macdonald notation: for the dual of an untwisted affine type - (such as ['C', 6,1]), we accept a twist of -1 (i.e., + (such as ['C', 6, 1]), we accept a twist of -1 (i.e., ['C',6,-1]). - Elliptic type -- ``letter`` is a Dynkin type, ``rank`` is the rank @@ -417,22 +417,22 @@ def _samples(self): Finite types:: - sage: QuiverMutationType('A',1) + sage: QuiverMutationType('A', 1) ['A', 1] sage: QuiverMutationType('A',5) ['A', 5] - sage: QuiverMutationType('B',2) + sage: QuiverMutationType('B', 2) ['B', 2] sage: QuiverMutationType('B',5) ['B', 5] - sage: QuiverMutationType('C',2) + sage: QuiverMutationType('C', 2) ['B', 2] sage: QuiverMutationType('C',5) ['C', 5] - sage: QuiverMutationType('D',2) + sage: QuiverMutationType('D', 2) [ ['A', 1], ['A', 1] ] sage: QuiverMutationType('D',3) ['A', 3] @@ -442,111 +442,111 @@ def _samples(self): sage: QuiverMutationType('E',6) ['E', 6] - sage: QuiverMutationType('G',2) + sage: QuiverMutationType('G', 2) ['G', 2] - sage: QuiverMutationType('A',(1,0),1) + sage: QuiverMutationType('A',(1,0), 1) ['A', 1] - sage: QuiverMutationType('A',(2,0),1) + sage: QuiverMutationType('A',(2,0), 1) [ ['A', 1], ['A', 1] ] - sage: QuiverMutationType('A',(7,0),1) + sage: QuiverMutationType('A',(7,0), 1) ['D', 7] Affine types:: - sage: QuiverMutationType('A',(1,1),1) + sage: QuiverMutationType('A',(1, 1), 1) ['A', [1, 1], 1] - sage: QuiverMutationType('A',(2,4),1) + sage: QuiverMutationType('A',(2,4), 1) ['A', [2, 4], 1] - sage: QuiverMutationType('BB',2,1) + sage: QuiverMutationType('BB', 2, 1) ['BB', 2, 1] - sage: QuiverMutationType('BB',4,1) + sage: QuiverMutationType('BB',4, 1) ['BB', 4, 1] - sage: QuiverMutationType('CC',2,1) + sage: QuiverMutationType('CC', 2, 1) ['CC', 2, 1] - sage: QuiverMutationType('CC',4,1) + sage: QuiverMutationType('CC',4, 1) ['CC', 4, 1] - sage: QuiverMutationType('BC',1,1) + sage: QuiverMutationType('BC', 1, 1) ['BC', 1, 1] - sage: QuiverMutationType('BC',5,1) + sage: QuiverMutationType('BC',5, 1) ['BC', 5, 1] - sage: QuiverMutationType('BD',3,1) + sage: QuiverMutationType('BD',3, 1) ['BD', 3, 1] - sage: QuiverMutationType('BD',5,1) + sage: QuiverMutationType('BD',5, 1) ['BD', 5, 1] - sage: QuiverMutationType('CD',3,1) + sage: QuiverMutationType('CD',3, 1) ['CD', 3, 1] - sage: QuiverMutationType('CD',5,1) + sage: QuiverMutationType('CD',5, 1) ['CD', 5, 1] - sage: QuiverMutationType('D',4,1) + sage: QuiverMutationType('D',4, 1) ['D', 4, 1] - sage: QuiverMutationType('D',6,1) + sage: QuiverMutationType('D',6, 1) ['D', 6, 1] - sage: QuiverMutationType('E',6,1) + sage: QuiverMutationType('E',6, 1) ['E', 6, 1] - sage: QuiverMutationType('E',7,1) + sage: QuiverMutationType('E',7, 1) ['E', 7, 1] - sage: QuiverMutationType('E',8,1) + sage: QuiverMutationType('E',8, 1) ['E', 8, 1] - sage: QuiverMutationType('F',4,1) + sage: QuiverMutationType('F',4, 1) ['F', 4, 1] sage: QuiverMutationType('F',4,-1) ['F', 4, -1] - sage: QuiverMutationType('G',2,1) + sage: QuiverMutationType('G', 2, 1) ['G', 2, 1] - sage: QuiverMutationType('G',2,-1) + sage: QuiverMutationType('G', 2,-1) ['G', 2, -1] - sage: QuiverMutationType('A',3,2) == QuiverMutationType('D',3,2) + sage: QuiverMutationType('A',3, 2) == QuiverMutationType('D',3, 2) True Affine types using Kac's Notation:: - sage: QuiverMutationType('A',1,1) + sage: QuiverMutationType('A', 1, 1) ['A', [1, 1], 1] - sage: QuiverMutationType('B',5,1) + sage: QuiverMutationType('B',5, 1) ['BD', 5, 1] - sage: QuiverMutationType('C',5,1) + sage: QuiverMutationType('C',5, 1) ['CC', 5, 1] - sage: QuiverMutationType('A',2,2) + sage: QuiverMutationType('A', 2, 2) ['BC', 1, 1] - sage: QuiverMutationType('A',7,2) + sage: QuiverMutationType('A',7, 2) ['CD', 4, 1] - sage: QuiverMutationType('A',8,2) + sage: QuiverMutationType('A',8, 2) ['BC', 4, 1] - sage: QuiverMutationType('D',6,2) + sage: QuiverMutationType('D',6, 2) ['BB', 5, 1] - sage: QuiverMutationType('E',6,2) + sage: QuiverMutationType('E',6, 2) ['F', 4, -1] sage: QuiverMutationType('D',4,3) ['G', 2, -1] Elliptic types:: - sage: QuiverMutationType('E',6,[1,1]) + sage: QuiverMutationType('E',6,[1, 1]) ['E', 6, [1, 1]] - sage: QuiverMutationType('F',4,[2,1]) + sage: QuiverMutationType('F',4,[2, 1]) ['F', 4, [1, 2]] - sage: QuiverMutationType('G',2,[3,3]) + sage: QuiverMutationType('G', 2,[3,3]) ['G', 2, [3, 3]] Mutation finite types: Rank 2 cases:: - sage: QuiverMutationType('R2',(1,1)) + sage: QuiverMutationType('R2',(1, 1)) ['A', 2] - sage: QuiverMutationType('R2',(1,2)) + sage: QuiverMutationType('R2',(1, 2)) ['B', 2] sage: QuiverMutationType('R2',(1,3)) ['G', 2] @@ -554,7 +554,7 @@ def _samples(self): ['BC', 1, 1] sage: QuiverMutationType('R2',(1,5)) ['R2', [1, 5]] - sage: QuiverMutationType('R2',(2,2)) + sage: QuiverMutationType('R2',(2, 2)) ['A', [1, 1], 1] sage: QuiverMutationType('R2',(3,5)) ['R2', [3, 5]] @@ -571,9 +571,9 @@ def _samples(self): sage: QuiverMutationType('E',9) ['E', 8, 1] - sage: QuiverMutationType('E',10) + sage: QuiverMutationType('E', 10) ['E', 10] - sage: QuiverMutationType('E',12) + sage: QuiverMutationType('E', 12) ['E', 12] sage: QuiverMutationType('AE',(2,3)) @@ -597,12 +597,12 @@ def _samples(self): ['E', 6] sage: QuiverMutationType('GR',(3,8)) ['E', 8] - sage: QuiverMutationType('GR',(3,10)) + sage: QuiverMutationType('GR',(3, 10)) ['GR', [3, 10]] Triangular types:: - sage: QuiverMutationType('TR',2) + sage: QuiverMutationType('TR', 2) ['A', 3] sage: QuiverMutationType('TR',3) ['D', 6] @@ -613,15 +613,15 @@ def _samples(self): T types:: - sage: QuiverMutationType('T',(1,1,1)) + sage: QuiverMutationType('T',(1, 1, 1)) ['A', 1] - sage: QuiverMutationType('T',(1,1,4)) + sage: QuiverMutationType('T',(1, 1,4)) ['A', 4] sage: QuiverMutationType('T',(1,4,4)) ['A', 7] - sage: QuiverMutationType('T',(2,2,2)) + sage: QuiverMutationType('T',(2, 2, 2)) ['D', 4] - sage: QuiverMutationType('T',(2,2,4)) + sage: QuiverMutationType('T',(2, 2,4)) ['D', 6] sage: QuiverMutationType('T',(2,3,3)) ['E', 6] @@ -664,7 +664,7 @@ def _repr_(self): EXAMPLES:: - sage: QuiverMutationType(['A',2]) # indirect doctest + sage: QuiverMutationType(['A', 2]) # indirect doctest ['A', 2] """ return self._description @@ -706,7 +706,7 @@ def show(self, circular=False, directed=True): sage: QMT = QuiverMutationType(['A',5]) sage: QMT.show() # long time """ - self.plot( circular=circular, directed=directed ).show() + self.plot(circular=circular, directed=directed).show() def letter(self): """ @@ -719,7 +719,7 @@ def letter(self): sage: mut_type.letter() 'A' - sage: mut_type = QuiverMutationType( ['BC',5,1] ); mut_type + sage: mut_type = QuiverMutationType( ['BC',5, 1] ); mut_type ['BC', 5, 1] sage: mut_type.letter() 'BC' @@ -749,12 +749,12 @@ def rank(self): sage: mut_type.rank() 5 - sage: mut_type = QuiverMutationType( ['A',[4,5],1] ); mut_type + sage: mut_type = QuiverMutationType( ['A',[4,5], 1] ); mut_type ['A', [4, 5], 1] sage: mut_type.rank() 9 - sage: mut_type = QuiverMutationType( ['BC',5,1] ); mut_type + sage: mut_type = QuiverMutationType( ['BC',5, 1] ); mut_type ['BC', 5, 1] sage: mut_type.rank() 6 @@ -814,7 +814,7 @@ def standard_quiver(self): sage: mut_type.standard_quiver() Quiver on 5 vertices of type ['A', 5] - sage: mut_type = QuiverMutationType( ['A',[5,3],1] ); mut_type + sage: mut_type = QuiverMutationType( ['A',[5,3], 1] ); mut_type ['A', [3, 5], 1] sage: mut_type.standard_quiver() Quiver on 8 vertices of type ['A', [3, 5], 1] @@ -884,7 +884,7 @@ def is_irreducible(self): EXAMPLES:: - sage: mt = QuiverMutationType(['A',2]) + sage: mt = QuiverMutationType(['A', 2]) sage: mt.is_irreducible() True """ @@ -899,7 +899,7 @@ def is_mutation_finite(self): EXAMPLES:: - sage: mt = QuiverMutationType(['D',5,1]) + sage: mt = QuiverMutationType(['D',5, 1]) sage: mt.is_mutation_finite() True """ @@ -914,15 +914,15 @@ def is_simply_laced(self): EXAMPLES:: - sage: mt = QuiverMutationType(['A',2]) + sage: mt = QuiverMutationType(['A', 2]) sage: mt.is_simply_laced() True - sage: mt = QuiverMutationType(['B',2]) + sage: mt = QuiverMutationType(['B', 2]) sage: mt.is_simply_laced() False - sage: mt = QuiverMutationType(['A',(1,1),1]) + sage: mt = QuiverMutationType(['A',(1, 1), 1]) sage: mt.is_simply_laced() False """ @@ -934,15 +934,15 @@ def is_skew_symmetric(self): EXAMPLES:: - sage: mt = QuiverMutationType(['A',2]) + sage: mt = QuiverMutationType(['A', 2]) sage: mt.is_skew_symmetric() True - sage: mt = QuiverMutationType(['B',2]) + sage: mt = QuiverMutationType(['B', 2]) sage: mt.is_skew_symmetric() False - sage: mt = QuiverMutationType(['A',(1,1),1]) + sage: mt = QuiverMutationType(['A',(1, 1), 1]) sage: mt.is_skew_symmetric() True """ @@ -957,11 +957,11 @@ def is_finite(self): EXAMPLES:: - sage: mt = QuiverMutationType(['A',2]) + sage: mt = QuiverMutationType(['A', 2]) sage: mt.is_finite() True - sage: mt = QuiverMutationType(['A',[4,2],1]) + sage: mt = QuiverMutationType(['A',[4, 2], 1]) sage: mt.is_finite() False """ @@ -973,11 +973,11 @@ def is_affine(self): EXAMPLES:: - sage: mt = QuiverMutationType(['A',2]) + sage: mt = QuiverMutationType(['A', 2]) sage: mt.is_affine() False - sage: mt = QuiverMutationType(['A',[4,2],1]) + sage: mt = QuiverMutationType(['A',[4, 2], 1]) sage: mt.is_affine() True """ @@ -992,11 +992,11 @@ def is_elliptic(self): EXAMPLES:: - sage: mt = QuiverMutationType(['A',2]) + sage: mt = QuiverMutationType(['A', 2]) sage: mt.is_elliptic() False - sage: mt = QuiverMutationType(['E',6,[1,1]]) + sage: mt = QuiverMutationType(['E',6,[1, 1]]) sage: mt.is_elliptic() True """ @@ -1039,7 +1039,7 @@ def properties(self): - affine: False - elliptic: False - sage: mut_type = QuiverMutationType(['B',3,1]); mut_type + sage: mut_type = QuiverMutationType(['B',3, 1]); mut_type ['BD', 3, 1] sage: mut_type.properties() ['BD', 3, 1] has rank 4 and the following properties: @@ -1051,7 +1051,7 @@ def properties(self): - affine: True - elliptic: False - sage: mut_type = QuiverMutationType(['E',6,[1,1]]); mut_type + sage: mut_type = QuiverMutationType(['E',6,[1, 1]]); mut_type ['E', 6, [1, 1]] sage: mut_type.properties() ['E', 6, [1, 1]] has rank 8 and the following properties: @@ -1103,6 +1103,7 @@ class QuiverMutationType_Irreducible(QuiverMutationType_abstract): The mutation type for a cluster algebra or a quiver. Should not be called directly, but through QuiverMutationType. """ + def __init__(self, letter, rank, twist=None): """ Should not be called directly but through QuiverMutationType. @@ -1118,10 +1119,10 @@ def __init__(self, letter, rank, twist=None): sage: QuiverMutationType('A',5) ['A', 5] - sage: QuiverMutationType('A',[4,5],1) + sage: QuiverMutationType('A',[4,5], 1) ['A', [4, 5], 1] - sage: QuiverMutationType('BB',5,1) + sage: QuiverMutationType('BB',5, 1) ['BB', 5, 1] sage: QuiverMutationType('X',6) @@ -1155,7 +1156,7 @@ def __init__(self, letter, rank, twist=None): self._letter = letter self._twist = twist - data = [letter,rank,twist] + data = [letter, rank, twist] # type A (finite and affine) if letter == 'A': @@ -1167,11 +1168,11 @@ def __init__(self, letter, rank, twist=None): self._info['finite'] = True elif twist == 1 and isinstance(rank, list) and len(rank) == 2 and all(ri in ZZ and ri >= 0 for ri in rank) and rank != [0, 0]: if isinstance(rank, tuple): - rank = list( rank ) + rank = list(rank) data[1] = rank rank = sorted(rank) self._bi_rank = rank - self._rank = sum( self._bi_rank ) + self._rank = sum(self._bi_rank) self._info['mutation_finite'] = True if self._rank > 2: self._info['simply_laced'] = True @@ -1182,24 +1183,24 @@ def __init__(self, letter, rank, twist=None): self._info['finite'] = True else: _mutation_type_error(data) - # types ['A',1] and ['A',[0,1],1] need to be treated on + # types ['A', 1] and ['A',[0, 1], 1] need to be treated on # itself (as there is no edge) if twist is None and self._rank == 1 or twist == 1 and self._rank == 1: - self._graph.add_vertex( 0 ) - # type ['A',[1,1],1] needs to be treated on itself as well + self._graph.add_vertex(0) + # type ['A',[1, 1], 1] needs to be treated on itself as well # (as there is a double edge) elif twist == 1 and self._bi_rank[0] == 1 and self._bi_rank[1] == 1: - self._graph.add_edge( 0,1,2 ) + self._graph.add_edge(0, 1, 2) else: - for i in range( self._rank - 1 ): - self._graph.add_edge( i, i+1, 1 ) + for i in range(self._rank - 1): + self._graph.add_edge(i, i + 1, 1) if twist == 1: - self._digraph.add_edge( self._rank - 1, 0, 1 ) - for i in range( self._rank - 1 ): + self._digraph.add_edge(self._rank - 1, 0, 1) + for i in range(self._rank - 1): if i < (2 * self._bi_rank[0]) and i % 2 == 0: - self._digraph.add_edge( i+1, i, 1 ) + self._digraph.add_edge(i + 1, i, 1) else: - self._digraph.add_edge( i, i+1, 1 ) + self._digraph.add_edge(i, i + 1, 1) # type B (finite) elif letter == 'B': @@ -1209,12 +1210,12 @@ def __init__(self, letter, rank, twist=None): self._info['finite'] = True else: _mutation_type_error(data) - for i in range( rank - 2 ): - self._graph.add_edge( i, i+1, 1 ) + for i in range(rank - 2): + self._graph.add_edge(i, i+1, 1) if (rank % 2 == 0): - self._graph.add_edge( rank-2, rank-1, (1,-2) ) + self._graph.add_edge(rank-2, rank-1, (1, -2)) else: - self._graph.add_edge( rank-2, rank-1, (2,-1) ) + self._graph.add_edge(rank-2, rank-1, (2, -1)) # type C (finite) elif letter == 'C': @@ -1224,12 +1225,12 @@ def __init__(self, letter, rank, twist=None): self._info['finite'] = True else: _mutation_type_error(data) - for i in range( rank - 2 ): - self._graph.add_edge( i, i+1, 1 ) + for i in range(rank - 2): + self._graph.add_edge(i, i+1, 1) if (rank % 2 == 0): - self._graph.add_edge( rank-2, rank-1, (2,-1) ) + self._graph.add_edge(rank-2, rank-1, (2, -1)) else: - self._graph.add_edge( rank-2, rank-1, (1,-2) ) + self._graph.add_edge(rank-2, rank-1, (1, -2)) # type BB (affine) elif letter == 'BB': @@ -1239,12 +1240,12 @@ def __init__(self, letter, rank, twist=None): self._info['affine'] = True else: _mutation_type_error(data) - for i in range( rank - 2 ): - self._graph.add_edge( i, i+1, 1 ) + for i in range(rank - 2): + self._graph.add_edge(i, i+1, 1) if rank % 2 == 0: - self._graph.add_edge( rank-2, rank-1, (1, -2) ) + self._graph.add_edge(rank-2, rank-1, (1, -2)) else: - self._graph.add_edge( rank-2, rank-1, (2, -1) ) + self._graph.add_edge(rank-2, rank-1, (2, -1)) self._graph.add_edge(rank, 0, (1, -2)) # type CC (affine) @@ -1255,12 +1256,12 @@ def __init__(self, letter, rank, twist=None): self._info['affine'] = True else: _mutation_type_error(data) - for i in range( rank - 2 ): - self._graph.add_edge( i, i+1, 1 ) + for i in range(rank - 2): + self._graph.add_edge(i, i+1, 1) if rank % 2 == 0: - self._graph.add_edge( rank-2, rank-1, (2,-1) ) + self._graph.add_edge(rank-2, rank-1, (2, -1)) else: - self._graph.add_edge( rank-2, rank-1, (1,-2) ) + self._graph.add_edge(rank-2, rank-1, (1, -2)) self._graph.add_edge(rank, 0, (2, -1)) # type BC (affine) @@ -1272,14 +1273,14 @@ def __init__(self, letter, rank, twist=None): else: _mutation_type_error(data) if rank == 1: - self._graph.add_edge( 0,1,(1,-4) ) + self._graph.add_edge(0, 1, (1, -4)) else: - for i in range( rank - 2 ): - self._graph.add_edge( i, i+1, 1 ) + for i in range(rank - 2): + self._graph.add_edge(i, i+1, 1) if (rank % 2 == 0): - self._graph.add_edge( rank-2, rank-1, (2,-1) ) + self._graph.add_edge(rank-2, rank-1, (2, -1)) else: - self._graph.add_edge( rank-2, rank-1, (1,-2) ) + self._graph.add_edge(rank-2, rank-1, (1, -2)) if twist == 1: self._graph.add_edge(rank, 0, (1, -2)) @@ -1291,12 +1292,12 @@ def __init__(self, letter, rank, twist=None): self._info['affine'] = True else: _mutation_type_error(data) - for i in range( rank - 2 ): - self._graph.add_edge( i, i+1, 1 ) + for i in range(rank - 2): + self._graph.add_edge(i, i+1, 1) if (rank % 2 == 0): - self._graph.add_edge( rank-2, rank-1, (1,-2) ) + self._graph.add_edge(rank-2, rank-1, (1, -2)) else: - self._graph.add_edge( rank-2, rank-1, (2,-1) ) + self._graph.add_edge(rank-2, rank-1, (2, -1)) if twist == 1: self._graph.add_edge(rank, 1, 1) @@ -1308,12 +1309,12 @@ def __init__(self, letter, rank, twist=None): self._info['affine'] = True else: _mutation_type_error(data) - for i in range( rank - 2 ): - self._graph.add_edge( i, i+1, 1 ) + for i in range(rank - 2): + self._graph.add_edge(i, i+1, 1) if (rank % 2 == 0): - self._graph.add_edge( rank-2, rank-1, (2,-1) ) + self._graph.add_edge(rank-2, rank-1, (2, -1)) else: - self._graph.add_edge( rank-2, rank-1, (1,-2) ) + self._graph.add_edge(rank-2, rank-1, (1, -2)) if twist == 1: self._graph.add_edge(rank, 1, 1) @@ -1333,10 +1334,10 @@ def __init__(self, letter, rank, twist=None): self._info['affine'] = True else: _mutation_type_error(data) - for i in range( rank - 2 ): - self._graph.add_edge( i, i+1, 1 ) + for i in range(rank - 2): + self._graph.add_edge(i, i+1, 1) - self._graph.add_edge( rank-3, rank-1, 1 ) + self._graph.add_edge(rank-3, rank-1, 1) if twist is not None: self._graph.add_edge(rank, 1, 1) @@ -1349,63 +1350,65 @@ def __init__(self, letter, rank, twist=None): self._info['skew_symmetric'] = True self._info['finite'] = True if rank == 6: - self._graph.add_edges( [ (0,1),(1,2),(2,3),(3,4),(2,5) ] ) + self._graph.add_edges([(0, 1), (1, 2), (2, 3), (3, 4), (2, 5)]) elif rank == 7: self._graph.add_edges([(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (2, 6)]) elif rank == 8: self._graph.add_edges([(0, 1), (1, 2), (2, 3), - (3, 4), (4, 5), (5, 6),(2, 7)]) - elif rank in [6,7,8] and twist == 1: + (3, 4), (4, 5), (5, 6), (2, 7)]) + elif rank in [6, 7, 8] and twist == 1: self._rank = rank + 1 self._info['mutation_finite'] = True self._info['simply_laced'] = True self._info['skew_symmetric'] = True self._info['affine'] = True if rank == 6: - self._graph.add_edges( [ (0,1),(1,2),(2,3),(3,4),(2,5),(5,6) ] ) + self._graph.add_edges([(0, 1), (1, 2), (2, 3), (3, 4), (2, 5), (5, 6)]) elif rank == 7: - self._graph.add_edges( [ (0,1),(1,2),(2,3),(3,4),(4,5),(5,6),(3,7) ] ) + self._graph.add_edges([(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (3, 7)]) elif rank == 8: - self._graph.add_edges( [ (0,1),(1,2),(2,3),(3,4),(4,5),(5,6),(6,7),(2,8) ] ) - elif rank in [6,7,8] and twist == [1,1]: + self._graph.add_edges([(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (2, 8)]) + elif rank in [6, 7, 8] and twist == [1, 1]: self._rank = rank + 2 self._info['mutation_finite'] = True self._info['skew_symmetric'] = True self._info['elliptic'] = True if rank == 6: - self._digraph.add_edges( [ (0,1,1),(1,2,1),(3,2,1),(3,4,1),(5,6,1),(6,7,1),(5,1,1),(2,5,2),(5,3,1),(6,2,1) ] ) + self._digraph.add_edges([(0, 1, 1), (1, 2, 1), (3, 2, 1), (3, 4, 1), (5, 6, 1), (6, 7, 1), (5, 1, 1), (2, 5, 2), (5, 3, 1), (6, 2, 1)]) elif rank == 7: - self._digraph.add_edges( [ (1,0,1),(1,2,1),(2,3,1),(4,3,1),(4,5,1),(6,5,1),(7,8,1),(3,7,2),(7,2,1),(7,4,1),(8,3,1) ] ) + self._digraph.add_edges([(1, 0, 1), (1, 2, 1), (2, 3, 1), (4, 3, 1), (4, 5, 1), + (6, 5, 1), (7, 8, 1), (3, 7, 2), (7, 2, 1), (7, 4, 1), (8, 3, 1)]) elif rank == 8: - self._digraph.add_edges( [ (0,1,1),(1,9,1),(3,9,1),(3,4,1),(2,8,1),(2,1,1),(9,2,2),(2,3,1),(8,9,1),(5,4,1),(5,6,1),(7,6,1) ] ) + self._digraph.add_edges([(0, 1, 1), (1, 9, 1), (3, 9, 1), (3, 4, 1), (2, 8, 1), (2, 1, 1), + (9, 2, 2), (2, 3, 1), (8, 9, 1), (5, 4, 1), (5, 6, 1), (7, 6, 1)]) # type E (mutation infinite) elif rank > 9 and twist is None: self._info['simply_laced'] = True self._info['skew_symmetric'] = True self._rank = rank for i in range(rank-2): - self._graph.add_edge( i, i+1, 1 ) - self._graph.add_edge( 2, rank-1 ) + self._graph.add_edge(i, i+1, 1) + self._graph.add_edge(2, rank-1) else: _mutation_type_error(data) # type AE (mutation infinite) elif letter == 'AE': - if isinstance(rank, list) and len(rank) == 2 and all( rank[i] in ZZ and rank[i] > 0 for i in [0,1] ) and twist is None: + if isinstance(rank, list) and len(rank) == 2 and all(rank[i] in ZZ and rank[i] > 0 for i in [0, 1]) and twist is None: if isinstance(rank, tuple): - rank = list( rank ) + rank = list(rank) data[1] = rank rank = sorted(rank) self._bi_rank = rank - self._rank = sum( self._bi_rank ) + 1 + self._rank = sum(self._bi_rank) + 1 if self._rank > 3: self._info['simply_laced'] = True self._info['skew_symmetric'] = True - if self._bi_rank == [1,1]: - self._graph.add_edges( [(0,1,2),(1,2,None)] ) + if self._bi_rank == [1, 1]: + self._graph.add_edges([(0, 1, 2), (1, 2, None)]) else: - self._digraph.add_edge( self._rank - 2, 0 ) + self._digraph.add_edge(self._rank - 2, 0) for i in range(self._rank-2): if i < (2 * self._bi_rank[0]) and i % 2 == 0: self._digraph.add_edge(i + 1, i) @@ -1420,12 +1423,12 @@ def __init__(self, letter, rank, twist=None): if rank > 4 and twist is None: self._rank = rank for i in range(rank-3): - self._graph.add_edge( i, i+1 ) - self._graph.add_edge( 2, rank-1 ) + self._graph.add_edge(i, i+1) + self._graph.add_edge(2, rank-1) if rank % 2 == 0: - self._graph.add_edge( rank-3,rank-2,(2,-1) ) + self._graph.add_edge(rank-3, rank-2, (2, -1)) else: - self._graph.add_edge( rank-3,rank-2,(1,-2) ) + self._graph.add_edge(rank-3, rank-2, (1, -2)) else: _mutation_type_error(data) @@ -1434,12 +1437,12 @@ def __init__(self, letter, rank, twist=None): if rank > 4 and twist is None: self._rank = rank for i in range(rank-3): - self._graph.add_edge( i, i+1 ) - self._graph.add_edge( 2, rank-1 ) + self._graph.add_edge(i, i+1) + self._graph.add_edge(2, rank-1) if rank % 2 == 0: - self._graph.add_edge( rank-3,rank-2,(1,-2) ) + self._graph.add_edge(rank-3, rank-2, (1, -2)) else: - self._graph.add_edge( rank-3,rank-2,(2,-1) ) + self._graph.add_edge(rank-3, rank-2, (2, -1)) else: _mutation_type_error(data) @@ -1450,9 +1453,9 @@ def __init__(self, letter, rank, twist=None): self._info['simply_laced'] = True self._info['skew_symmetric'] = True for i in range(rank-3): - self._graph.add_edge( i, i+1 ) - self._graph.add_edge( 2, rank-2 ) - self._graph.add_edge( rank-4, rank-1 ) + self._graph.add_edge(i, i+1) + self._graph.add_edge(2, rank-2) + self._graph.add_edge(rank-4, rank-1) else: _mutation_type_error(data) @@ -1462,48 +1465,48 @@ def __init__(self, letter, rank, twist=None): self._rank = rank self._info['mutation_finite'] = True self._info['finite'] = True - self._graph.add_edges( [ (0,1,None),(1,2,(2,-1)),(2,3,None) ] ) + self._graph.add_edges([(0, 1, None), (1, 2, (2, -1)), (2, 3, None)]) elif rank == 4 and twist == 1: self._rank = rank + 1 self._info['mutation_finite'] = True self._info['affine'] = True - self._graph.add_edges( [ (0,1,None), (1,2,None), - (2,3,(1,-2)),(3,4,None) ] ) + self._graph.add_edges([(0, 1, None), (1, 2, None), + (2, 3, (1, -2)), (3, 4, None)]) elif rank == 4 and twist == -1: self._rank = rank + 1 self._info['mutation_finite'] = True self._info['affine'] = True - self._graph.add_edges( [ (0,1,None), (1,2,None), - (2,3,(2,-1)),(3,4,None) ] ) - elif rank == 4 and (twist == [1,2]): + self._graph.add_edges([(0, 1, None), (1, 2, None), + (2, 3, (2, -1)), (3, 4, None)]) + elif rank == 4 and (twist == [1, 2]): self._rank = rank + 2 self._info['mutation_finite'] = True self._info['elliptic'] = True - self._digraph.add_edges( [ (0,1,None), (1,2,None), - (2,3,(2,-1)), (4,2,(1,-2)), - (3,4,2), (4,5,None), (5,3,None) ]) - elif rank == 4 and (twist == [2,1]): + self._digraph.add_edges([(0, 1, None), (1, 2, None), + (2, 3, (2, -1)), (4, 2, (1, -2)), + (3, 4, 2), (4, 5, None), (5, 3, None)]) + elif rank == 4 and (twist == [2, 1]): self._rank = rank + 2 self._info['mutation_finite'] = True self._info['elliptic'] = True - self._digraph.add_edges( [ (0,1,None), (1,2,None), - (2,3,(1,-2)), (4,2,(2,-1)), - (3,4,2), (4,5,None), (5,3,None) ]) - elif rank == 4 and twist == [2,2]: + self._digraph.add_edges([(0, 1, None), (1, 2, None), + (2, 3, (1, -2)), (4, 2, (2, -1)), + (3, 4, 2), (4, 5, None), (5, 3, None)]) + elif rank == 4 and twist == [2, 2]: self._rank = rank + 2 self._info['mutation_finite'] = True self._info['elliptic'] = True - self._digraph.add_edges( [ (0,1,None), (1,2,None), - (3,1,None), (2,3,2), - (4,2,(2,-1)), (3,4,(1,-2)), - (5,4,None) ] ) - elif rank == 4 and twist == [1,1]: + self._digraph.add_edges([(0, 1, None), (1, 2, None), + (3, 1, None), (2, 3, 2), + (4, 2, (2, -1)), (3, 4, (1, -2)), + (5, 4, None)]) + elif rank == 4 and twist == [1, 1]: self._rank = rank + 2 self._info['mutation_finite'] = True self._info['elliptic'] = True - self._digraph.add_edges( [ (0,1,None), (1,2,None), - (3,1,None), (2,3,2), (4,2,(1,-2)), - (3,4,(2,-1)), (5,4,None) ] ) + self._digraph.add_edges([(0, 1, None), (1, 2, None), + (3, 1, None), (2, 3, 2), (4, 2, (1, -2)), + (3, 4, (2, -1)), (5, 4, None)]) else: _mutation_type_error(data) @@ -1513,109 +1516,109 @@ def __init__(self, letter, rank, twist=None): self._rank = rank self._info['mutation_finite'] = True self._info['finite'] = True - self._graph.add_edges( [ (0,1,(1,-3)) ] ) + self._graph.add_edges([(0, 1, (1, -3))]) elif rank == 2 and twist == -1: self._rank = rank + 1 self._info['mutation_finite'] = True self._info['affine'] = True - self._graph.add_edges( [ (0,1,None),(1,2,(1,-3)) ] ) + self._graph.add_edges([(0, 1, None), (1, 2, (1, -3))]) elif rank == 2 and twist == 1: self._rank = rank + 1 self._info['mutation_finite'] = True self._info['affine'] = True - self._graph.add_edges( [ (0,1,None),(1,2,(3,-1)) ] ) - elif rank == 2 and (twist == [1,3]): + self._graph.add_edges([(0, 1, None), (1, 2, (3, -1))]) + elif rank == 2 and (twist == [1, 3]): self._rank = rank + 2 self._info['mutation_finite'] = True self._info['elliptic'] = True - self._digraph.add_edges( [ (0,1,None), (1,2,(3,-1)), - (3,1,(1,-3)), (2,3,2)] ) - elif rank == 2 and (twist == [3,1]): + self._digraph.add_edges([(0, 1, None), (1, 2, (3, -1)), + (3, 1, (1, -3)), (2, 3, 2)]) + elif rank == 2 and (twist == [3, 1]): self._rank = rank + 2 self._info['mutation_finite'] = True self._info['elliptic'] = True - self._digraph.add_edges( [ (0,1,None), (1,2,(1,-3)), - (3,1,(3,-1)), (2,3,2)] ) - elif rank == 2 and twist == [3,3]: + self._digraph.add_edges([(0, 1, None), (1, 2, (1, -3)), + (3, 1, (3, -1)), (2, 3, 2)]) + elif rank == 2 and twist == [3, 3]: self._rank = rank + 2 self._info['mutation_finite'] = True self._info['elliptic'] = True - self._digraph.add_edges( [ (1,0,None), (0,2,2), (3,0,(3,-1)), - (2,1,None), (2,3, (1,-3))]) - elif rank == 2 and twist == [1,1]: + self._digraph.add_edges([(1, 0, None), (0, 2, 2), (3, 0, (3, -1)), + (2, 1, None), (2, 3, (1, -3))]) + elif rank == 2 and twist == [1, 1]: self._rank = rank + 2 self._info['mutation_finite'] = True self._info['elliptic'] = True - self._digraph.add_edges( [ (1,0,None), (0,2,2), (3,0,(1,-3)), - (2,1,None), (2,3,(3,-1)) ] ) + self._digraph.add_edges([(1, 0, None), (0, 2, 2), (3, 0, (1, -3)), + (2, 1, None), (2, 3, (3, -1))]) else: _mutation_type_error(data) # type GR (mutation infinite) elif letter == 'GR': - if twist is None and isinstance(rank, list) and len(rank) == 2 and all( rank[i] in ZZ and rank[i] > 0 for i in [0,1] ) and rank[1] - 1 > rank[0] > 1: - gr_rank = (rank[0]-1,rank[1]-rank[0]-1) + if twist is None and isinstance(rank, list) and len(rank) == 2 and all(rank[i] in ZZ and rank[i] > 0 for i in [0, 1]) and rank[1] - 1 > rank[0] > 1: + gr_rank = (rank[0]-1, rank[1]-rank[0]-1) self._rank = prod(gr_rank) self._info['simply_laced'] = True self._info['skew_symmetric'] = True - a,b = gr_rank + a, b = gr_rank for i in range(a): for j in range(b): if i < a-1: if (i+j) % 2 == 0: - self._digraph.add_edge(i*b+j,(i+1)*b+j) + self._digraph.add_edge(i*b+j, (i+1)*b+j) else: - self._digraph.add_edge((i+1)*b+j,i*b+j) + self._digraph.add_edge((i+1)*b+j, i*b+j) if j < b-1: if (i+j) % 2 == 0: - self._digraph.add_edge(i*b+j+1,i*b+j) + self._digraph.add_edge(i*b+j+1, i*b+j) else: - self._digraph.add_edge(i*b+j,i*b+j+1) + self._digraph.add_edge(i*b+j, i*b+j+1) else: _mutation_type_error(data) # type R2 (rank 2 finite mutation types) elif letter == 'R2': - if twist is None and isinstance(rank, list) and len(rank) == 2 and all( rank[i] in ZZ and rank[i] > 0 for i in [0,1] ): + if twist is None and isinstance(rank, list) and len(rank) == 2 and all(rank[i] in ZZ and rank[i] > 0 for i in [0, 1]): rank = sorted(rank) - b,c = rank + b, c = rank self._rank = 2 if b == c: self._info['skew_symmetric'] = True - self._graph.add_edge(0,1,(b,-c)) + self._graph.add_edge(0, 1, (b, -c)) else: _mutation_type_error(data) # type T elif letter == 'T': - if twist is None and isinstance(rank, list) and len(rank) == 3 and all( rank[i] in ZZ and rank[i] > 0 for i in [0,1,2] ): + if twist is None and isinstance(rank, list) and len(rank) == 3 and all(rank[i] in ZZ and rank[i] > 0 for i in [0, 1, 2]): if isinstance(rank, tuple): - rank = list( rank ) + rank = list(rank) data[1] = rank - rank = sorted( rank ) - self._rank = sum( rank ) - 2 + rank = sorted(rank) + self._rank = sum(rank) - 2 self._info['simply_laced'] = True self._info['skew_symmetric'] = True - r,p,q = rank + r, p, q = rank for i in range(q-1): if i == 0: - self._graph.add_edge(0,1) - self._graph.add_edge(0,r) - self._graph.add_edge(0,r+p-1) + self._graph.add_edge(0, 1) + self._graph.add_edge(0, r) + self._graph.add_edge(0, r+p-1) else: if i < r-1: - self._graph.add_edge(i,i+1) + self._graph.add_edge(i, i+1) if i < p-1: - self._graph.add_edge(i+r-1,i+r) - self._graph.add_edge(i+r+p-2,i+r+p-1) + self._graph.add_edge(i+r-1, i+r) + self._graph.add_edge(i+r+p-2, i+r+p-1) else: _mutation_type_error(data) # type TR (mutation infinite if rank > 2) elif letter == 'TR': - # type ['TR',1] needs to be treated on itself (as there is no edge) + # type ['TR', 1] needs to be treated on itself (as there is no edge) if twist is None and rank == 1: - self._graph.add_vertex( 0 ) + self._graph.add_vertex(0) elif twist is None and rank > 1: self._rank = rank*(rank+1)//2 self._info['simply_laced'] = True @@ -1623,25 +1626,25 @@ def __init__(self, letter, rank, twist=None): level = 0 while level < rank: nr = rank*level-sum(range(level)) - for i in range(nr,nr+rank-level-1): - self._digraph.add_edge(i,i+1) - self._digraph.add_edge(i+rank-level,i) - self._digraph.add_edge(i+1,i+rank-level) + for i in range(nr, nr+rank-level-1): + self._digraph.add_edge(i, i+1) + self._digraph.add_edge(i+rank-level, i) + self._digraph.add_edge(i+1, i+rank-level) level += 1 else: _mutation_type_error(data) # type X elif letter == 'X': - if rank in [6,7] and twist is None: + if rank in [6, 7] and twist is None: self._rank = rank self._info['mutation_finite'] = True self._info['skew_symmetric'] = True - self._digraph.add_edges( [ (0,1,2),(1,2,None),(2,0,None), - (2,3,None),(3,4,2),(4,2,None), - (2,5,None) ] ) + self._digraph.add_edges([(0, 1, 2), (1, 2, None), (2, 0, None), + (2, 3, None), (3, 4, 2), (4, 2, None), + (2, 5, None)]) if rank == 7: - self._digraph.add_edges( [ (5,6,2),(6,2,None) ] ) + self._digraph.add_edges([(5, 6, 2), (6, 2, None)]) else: _mutation_type_error(data) @@ -1652,7 +1655,7 @@ def __init__(self, letter, rank, twist=None): # in the bipartite case, the digraph is constructed from the graph if not self._digraph: if self._graph.is_bipartite(): - self._digraph = _bipartite_graph_to_digraph( self._graph ) + self._digraph = _bipartite_graph_to_digraph(self._graph) else: raise ValueError('The QuiverMutationType does not have ' 'a Coxeter diagram.') @@ -1667,7 +1670,7 @@ def __init__(self, letter, rank, twist=None): else: self._description = str([letter, rank]) - def irreducible_components( self ): + def irreducible_components(self): """ Return a list of all irreducible components of ``self``. @@ -1708,7 +1711,7 @@ def class_size(self): sage: mut_type.class_size() 19 - sage: mut_type = QuiverMutationType( ['A',[10,3],1] ); mut_type + sage: mut_type = QuiverMutationType( ['A',[10,3], 1] ); mut_type ['A', [3, 10], 1] sage: mut_type.class_size() 142120 @@ -1718,7 +1721,7 @@ def class_size(self): sage: mut_type.class_size() 132 - sage: mut_type = QuiverMutationType( ['BD',6,1] ); mut_type + sage: mut_type = QuiverMutationType( ['BD',6, 1] ); mut_type ['BD', 6, 1] sage: mut_type.class_size() Warning: This method uses a formula which has not been proved correct. @@ -1726,7 +1729,7 @@ def class_size(self): Check that :trac:`14048` is fixed:: - sage: mut_type = QuiverMutationType( ['F',4,(2,1)] ) + sage: mut_type = QuiverMutationType( ['F',4,(2, 1)] ) sage: mut_type.class_size() 90 """ @@ -1739,29 +1742,29 @@ def class_size(self): # cluster-tilted algebras of type A if self.is_finite(): n = self._rank - a = binomial( 2*(n+1), n+1 ) // (n+2) + a = binomial(2*(n+1), n+1) // (n+2) if n % 2 == 1: - a += binomial( n+1, (n+1)//2 ) + a += binomial(n+1, (n+1)//2) if n % 3 == 0: - a += 2 * binomial( 2*n//3, n//3 ) + a += 2 * binomial(2*n//3, n//3) return a // (n+3) # the formula is taken from Bastian, Prellberg, Rubey, Stump elif self.is_affine(): - i,j = self._bi_rank + i, j = self._bi_rank i = ZZ(i) j = ZZ(j) n = i+j f = euler_phi if i == j: - return ( binomial( 2*i,i ) + - sum( f(k) * binomial(2*i//k,i//k)**2 - for k in [k for k in i.divisors() - if k in j.divisors()] ) // n ) // 4 + return (binomial(2 * i, i) + + sum(f(k) * binomial(2 * i // k, i // k)**2 + for k in i.divisors() + if k in j.divisors()) // n) // 4 else: - return sum( f(k) * binomial(2*i//k,i//k) * - binomial(2*j//k,j//k) - for k in [k for k in i.divisors() - if k in j.divisors()] ) // ( 2 * n ) + return sum(f(k) * binomial(2 * i // k, i // k) * + binomial(2 * j // k, j // k) + for k in i.divisors() + if k in j.divisors()) // (2 * n) # types B and C (finite and affine) elif self._letter in ['B', 'C']: @@ -1771,7 +1774,7 @@ def class_size(self): n = self._rank return binomial(2 * n, n) // (n + 1) - elif self._letter in ['BB','CC']: + elif self._letter in ['BB', 'CC']: # these two formulas are not yet proven print("Warning: This method uses a formula " "which has not been proved correct.") @@ -1795,7 +1798,7 @@ def class_size(self): return binomial(2 * n, n) # types BD and CD (affine) - elif self._letter in ['BD','CD']: + elif self._letter in ['BD', 'CD']: # this formula is not yet proven print("Warning: This method uses a formula " "which has not been proved correct.") @@ -1860,9 +1863,9 @@ def class_size(self): elif self.is_affine(): return 60 elif self.is_elliptic(): - if self._twist == [1,2]: + if self._twist == [1, 2]: return 90 - if self._twist == [1,1] or self._twist == [2,2]: + if self._twist == [1, 1] or self._twist == [2, 2]: return 35 # type G @@ -1872,9 +1875,9 @@ def class_size(self): elif self.is_affine(): return 6 elif self.is_elliptic(): - if self._twist == [1,3]: + if self._twist == [1, 3]: return 7 - if self._twist == [1,1] or self._twist == [3,3]: + if self._twist == [1, 1] or self._twist == [3, 3]: return 2 # type X @@ -1911,7 +1914,7 @@ def dual(self): """ letter = self.letter() # the self-dual cases - if letter != 'BC' and letter[0] in ['B','C']: + if letter != 'BC' and letter[0] in ['B', 'C']: if letter == 'BB': letter = 'CC' elif letter == 'CC': @@ -1924,9 +1927,9 @@ def dual(self): if self.is_affine(): rank -= 1 twist = self._twist - return QuiverMutationType(letter,rank,twist) + return QuiverMutationType(letter, rank, twist) # the cases F and G have non-trivial duality in some cases - elif letter in ['F','G']: + elif letter in ['F', 'G']: if self.is_finite(): return self elif self.is_affine(): @@ -1936,15 +1939,15 @@ def dual(self): twist = self._twist rank = self._rank - 2 if letter == 'F': - if self._twist == [2,2]: - twist == [1,1] - if self._twist == [1,1]: - twist == [2,2] + if self._twist == [2, 2]: + twist == [1, 1] + if self._twist == [1, 1]: + twist == [2, 2] if letter == 'G': - if self._twist == [3,3]: - twist = [1,1] - elif self._twist == [1,1]: - twist = [3,3] + if self._twist == [3, 3]: + twist = [1, 1] + elif self._twist == [1, 1]: + twist = [3, 3] else: rank = self._rank return QuiverMutationType(letter, rank, twist) @@ -1958,6 +1961,7 @@ class QuiverMutationType_Reducible(QuiverMutationType_abstract): called directly, but through QuiverMutationType. Inherits from QuiverMutationType_abstract. """ + def __init__(self, *args): """ Should not be called directly, but through QuiverMutationType. @@ -1973,7 +1977,7 @@ def __init__(self, *args): [ ['A', 4], ['B', 6] ] """ data = args - if len(data) < 2 or not all( isinstance(comp, QuiverMutationType_Irreducible) for comp in data ): + if len(data) < 2 or not all(isinstance(comp, QuiverMutationType_Irreducible) for comp in data): return _mutation_type_error(data) # _info is initialized @@ -2017,7 +2021,7 @@ def __init__(self, *args): self._description += comps[i]._description self._description += " ]" - def irreducible_components( self ): + def irreducible_components(self): """ Return a list of all irreducible components of ``self``. @@ -2085,7 +2089,7 @@ def class_size(self): multiplicities[i]) for i in range(len(sizes))) - def dual(self): + def dual(self) -> QuiverMutationType: """ Return the QuiverMutationType which is dual to ``self``. @@ -2097,10 +2101,10 @@ def dual(self): [ ['A', 5], ['C', 6], ['B', 5], ['D', 4] ] """ comps = self.irreducible_components() - return QuiverMutationType( [comp.dual() for comp in comps ] ) + return QuiverMutationType([comp.dual() for comp in comps]) -def _construct_classical_mutation_classes(n): +def _construct_classical_mutation_classes(n) -> dict: r""" Return a dict with keys being tuples representing regular QuiverMutationTypes of the given rank, and with values being lists @@ -2122,42 +2126,42 @@ def _construct_classical_mutation_classes(n): data = {} # finite A - data[ ('A',n) ] = ClusterQuiver(['A',n]).mutation_class(data_type='dig6') + data[('A', n)] = ClusterQuiver(['A', n]).mutation_class(data_type='dig6') # affine A for j in range(1, n//2+1): - data[ ('A',(n-j,j),1) ] = ClusterQuiver(['A',[n-j,j],1]).mutation_class(data_type='dig6') + data[('A', (n-j, j), 1)] = ClusterQuiver(['A', [n-j, j], 1]).mutation_class(data_type='dig6') # finite B if n > 1: - data[ ('B',n) ] = ClusterQuiver(['B',n]).mutation_class(data_type='dig6') + data[('B', n)] = ClusterQuiver(['B', n]).mutation_class(data_type='dig6') # affine B if n > 2: - data[ ('BB',n-1,1) ] = ClusterQuiver(['BB',n-1,1]).mutation_class(data_type='dig6') + data[('BB', n-1, 1)] = ClusterQuiver(['BB', n-1, 1]).mutation_class(data_type='dig6') # finite C if n > 2: - data[ ('C',n) ] = ClusterQuiver(['C',n]).mutation_class(data_type='dig6') + data[('C', n)] = ClusterQuiver(['C', n]).mutation_class(data_type='dig6') # affine C if n > 1: - data[ ('BC',n-1,1) ] = ClusterQuiver(['BC',n-1,1]).mutation_class(data_type='dig6') + data[('BC', n-1, 1)] = ClusterQuiver(['BC', n-1, 1]).mutation_class(data_type='dig6') # affine CC if n > 2: - data[ ('CC',n-1,1) ] = ClusterQuiver(['CC',n-1,1]).mutation_class(data_type='dig6') + data[('CC', n-1, 1)] = ClusterQuiver(['CC', n-1, 1]).mutation_class(data_type='dig6') # affine BD if n > 3: - data[ ('BD',n-1,1) ] = ClusterQuiver(['BD',n-1,1]).mutation_class(data_type='dig6') + data[('BD', n-1, 1)] = ClusterQuiver(['BD', n-1, 1]).mutation_class(data_type='dig6') # affine CD if n > 3: - data[ ('CD',n-1,1) ] = ClusterQuiver(['CD',n-1,1]).mutation_class(data_type='dig6') + data[('CD', n-1, 1)] = ClusterQuiver(['CD', n-1, 1]).mutation_class(data_type='dig6') # finite D if n > 3: - data[ ('D',n) ] = ClusterQuiver(['D',n]).mutation_class(data_type='dig6') + data[('D', n)] = ClusterQuiver(['D', n]).mutation_class(data_type='dig6') # affine D if n > 4: - data[ ('D',n-1,1) ] = ClusterQuiver(['D',n-1,1]).mutation_class(data_type='dig6') + data[('D', n-1, 1)] = ClusterQuiver(['D', n-1, 1]).mutation_class(data_type='dig6') return data -def _construct_exceptional_mutation_classes(n): +def _construct_exceptional_mutation_classes(n) -> dict: r""" Return a dict with keys being tuples representing exceptional QuiverMutationTypes of the given rank, and with values being lists @@ -2183,41 +2187,41 @@ def _construct_exceptional_mutation_classes(n): from sage.combinat.cluster_algebra_quiver.quiver import ClusterQuiver data = {} # finite E - if n in [6,7,8]: - data[ ('E',n) ] = ClusterQuiver(['E',n]).mutation_class(data_type='dig6') + if n in [6, 7, 8]: + data[('E', n)] = ClusterQuiver(['E', n]).mutation_class(data_type='dig6') # affine E - if n in [7,8,9]: - data[ ('E',n-1,1) ] = ClusterQuiver(['E',n-1,1]).mutation_class(data_type='dig6') + if n in [7, 8, 9]: + data[('E', n - 1, 1)] = ClusterQuiver(['E', n - 1, 1]).mutation_class(data_type='dig6') # elliptic E - if n in [8,9,10]: - data[ ('E',n-2,(1,1)) ] = ClusterQuiver(['E',n-2,[1,1]]).mutation_class(data_type='dig6') + if n in [8, 9, 10]: + data[('E', n - 2, (1, 1))] = ClusterQuiver(['E', n - 2, [1, 1]]).mutation_class(data_type='dig6') # finite F if n == 4: - data[ ('F',4) ] = ClusterQuiver(['F',4]).mutation_class(data_type='dig6') + data[('F', 4)] = ClusterQuiver(['F', 4]).mutation_class(data_type='dig6') # affine F if n == 5: - data[ ('F',4,1) ] = ClusterQuiver(['F',4,1]).mutation_class(data_type='dig6') - data[ ('F',4,-1) ] = ClusterQuiver(['F',4,-1]).mutation_class(data_type='dig6') + data[('F', 4, 1)] = ClusterQuiver(['F', 4, 1]).mutation_class(data_type='dig6') + data[('F', 4, -1)] = ClusterQuiver(['F', 4, -1]).mutation_class(data_type='dig6') # finite G if n == 2: - data[ ('G',2) ] = ClusterQuiver(['G',2]).mutation_class(data_type='dig6') + data[('G', 2)] = ClusterQuiver(['G', 2]).mutation_class(data_type='dig6') # affine G if n == 3: - data[ ('G',2,1) ] = ClusterQuiver(['G',2,1]).mutation_class(data_type='dig6') - data[ ('G',2,-1) ] = ClusterQuiver(['G',2,-1]).mutation_class(data_type='dig6') + data[('G', 2, 1)] = ClusterQuiver(['G', 2, 1]).mutation_class(data_type='dig6') + data[('G', 2, -1)] = ClusterQuiver(['G', 2, -1]).mutation_class(data_type='dig6') # elliptic G if n == 4: - data[ ('G',2,(1,3)) ] = ClusterQuiver(['G',2,(1,3)]).mutation_class(data_type='dig6') - data[ ('G',2,(1,1)) ] = ClusterQuiver(['G',2,(1,1)]).mutation_class(data_type='dig6') - data[ ('G',2,(3,3)) ] = ClusterQuiver(['G',2,(3,3)]).mutation_class(data_type='dig6') + data[('G', 2, (1, 3))] = ClusterQuiver(['G', 2, (1, 3)]).mutation_class(data_type='dig6') + data[('G', 2, (1, 1))] = ClusterQuiver(['G', 2, (1, 1)]).mutation_class(data_type='dig6') + data[('G', 2, (3, 3))] = ClusterQuiver(['G', 2, (3, 3)]).mutation_class(data_type='dig6') # X - if n in [6,7]: - data[ ('X',n) ] = ClusterQuiver(['X',n]).mutation_class(data_type='dig6') + if n in [6, 7]: + data[('X', n)] = ClusterQuiver(['X', n]).mutation_class(data_type='dig6') # elliptic F if n == 6: - data[ ('F',4,(1,2)) ] = ClusterQuiver(['F',4,(1,2)]).mutation_class(data_type='dig6') - data[ ('F',4,(1,1)) ] = ClusterQuiver(['F',4,(1,1)]).mutation_class(data_type='dig6') - data[ ('F',4,(2,2)) ] = ClusterQuiver(['F',4,(2,2)]).mutation_class(data_type='dig6') + data[('F', 4, (1, 2))] = ClusterQuiver(['F', 4, (1, 2)]).mutation_class(data_type='dig6') + data[('F', 4, (1, 1))] = ClusterQuiver(['F', 4, (1, 1)]).mutation_class(data_type='dig6') + data[('F', 4, (2, 2))] = ClusterQuiver(['F', 4, (2, 2)]).mutation_class(data_type='dig6') return data @@ -2268,14 +2272,14 @@ def _save_data_dig6(n, types='ClassicalExceptional', verbose=False): from sage.env import DOT_SAGE from sage.misc.misc import sage_makedirs types_path = os.path.join(DOT_SAGE, 'cluster_algebra_quiver') - types_file = os.path.join(types_path,'mutation_classes_%s.dig6' % n) + types_file = os.path.join(types_path, 'mutation_classes_%s.dig6' % n) sage_makedirs(types_path) from sage.misc.temporary_file import atomic_write with atomic_write(types_file, binary=True) as f: pickle.dump(data, f) if verbose: - keys = sorted(data.keys(),key=str) - print("\nThe following types are saved to file", types_file,"and will now be used to determine quiver mutation types:") + keys = sorted(data, key=str) + print("\nThe following types are saved to file", types_file, "and will now be used to determine quiver mutation types:") print(keys) @@ -2331,16 +2335,16 @@ def save_quiver_data(n, up_to=True, types='ClassicalExceptional', verbose=True): """ from sage.combinat.cluster_algebra_quiver.mutation_type import load_data if up_to is True: - ranks = range(1,n+1) + ranks = range(1, n + 1) elif up_to is False: ranks = [n] for i in ranks: - _save_data_dig6(i,types=types,verbose=verbose) + _save_data_dig6(i, types=types, verbose=verbose) # we finally clear the load_data load_data.clear_cache() -def _bipartite_graph_to_digraph(g): +def _bipartite_graph_to_digraph(g) -> DiGraph: """ Return a digraph obtained from a bipartite graph ``g`` by choosing one set of the bipartition to be the set of sinks and the other to be the @@ -2349,7 +2353,7 @@ def _bipartite_graph_to_digraph(g): EXAMPLES:: sage: from sage.combinat.cluster_algebra_quiver.quiver_mutation_type import _bipartite_graph_to_digraph - sage: G = Graph([(1,2)]) + sage: G = Graph([(1, 2)]) sage: _bipartite_graph_to_digraph(G) Digraph on 2 vertices """ @@ -2364,7 +2368,7 @@ def _bipartite_graph_to_digraph(g): return dg -def _is_mutation_type(data): +def _is_mutation_type(data) -> bool: """ Return ``True`` if ``data`` is a QuiverMutationType. @@ -2412,7 +2416,7 @@ def _mutation_type_error(data): raise ValueError(return_str) -def _edge_list_to_matrix(edges, nlist, mlist): +def _edge_list_to_matrix(edges, nlist, mlist) -> matrix: r""" Return the matrix obtained from the edge list of a quiver. @@ -2429,8 +2433,8 @@ def _edge_list_to_matrix(edges, nlist, mlist): EXAMPLES:: sage: from sage.combinat.cluster_algebra_quiver.quiver_mutation_type import _edge_list_to_matrix - sage: G = QuiverMutationType(['A',2])._digraph - sage: _edge_list_to_matrix(G.edges(), [0,1], []) + sage: G = QuiverMutationType(['A', 2])._digraph + sage: _edge_list_to_matrix(G.edges(), [0, 1], []) [ 0 1] [-1 0] @@ -2446,15 +2450,16 @@ def _edge_list_to_matrix(edges, nlist, mlist): [ 0 -1] """ n = len(nlist) - m = len(mlist) nmlist = nlist + mlist - M = matrix(ZZ, n + m, n, sparse=True) - for edge in edges: - if edge[2] is None: - edge = (edge[0], edge[1], (1, -1)) - elif edge[2] in ZZ: - edge = (edge[0], edge[1], (edge[2], -edge[2])) - v1, v2, (a, b) = edge + nm = len(nmlist) + M = matrix(ZZ, nm, n, sparse=True) + for v1, v2, label in edges: + if label is None: + a, b = 1, -1 + elif label in ZZ: + a, b = label, -label + else: + a, b = label if v1 in nlist: M[nmlist.index(v2), nmlist.index(v1)] = b if v2 in nlist: From c616d52bfeda725ca1d6ae4231489e8d4ce0cd60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Wed, 6 Oct 2021 14:52:16 +0200 Subject: [PATCH 280/359] fix a problem in is_connected --- src/sage/graphs/base/c_graph.pyx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/sage/graphs/base/c_graph.pyx b/src/sage/graphs/base/c_graph.pyx index a3b122c9d81..515ca3076ff 100644 --- a/src/sage/graphs/base/c_graph.pyx +++ b/src/sage/graphs/base/c_graph.pyx @@ -4400,11 +4400,18 @@ cdef class CGraphBackend(GenericGraphBackend): sage: Graph(graphs.CubeGraph(3)).is_connected() True + + TESTS:: + + sage: P = posets.PentagonPoset() + sage: H = P._hasse_diagram + sage: H._backend.is_connected() + True """ cdef int v_int cdef CGraph cg = self.cg() - if cg.num_edges() < cg.num_verts - 1: + if cg.num_arcs < cg.num_verts - 1: return False v_int = bitset_first(cg.active_vertices) From 0f305308bcb2c5860f88ab6e687b3d5b614c6d85 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 6 Oct 2021 09:15:18 -0700 Subject: [PATCH 281/359] src/sage/misc/sageinspect.py: Fix up a doctest on the source code of src/sage/symbolic/expression.pyx --- src/sage/misc/sageinspect.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/misc/sageinspect.py b/src/sage/misc/sageinspect.py index 72c9cdf1d22..be7d50783bc 100644 --- a/src/sage/misc/sageinspect.py +++ b/src/sage/misc/sageinspect.py @@ -2308,7 +2308,7 @@ def sage_getsourcelines(obj): ...) sage: x = var('x') sage: lines, lineno = sage_getsourcelines(x); lines[0:5] - ['cdef class Expression(CommutativeRingElement):\n', + ['cdef class Expression(...):\n', '\n', ' cdef GEx _gobj\n', '\n', From 2a81e0f5a362bafa6612bab4fb4f31ddccc731cd Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 6 Oct 2021 09:15:31 -0700 Subject: [PATCH 282/359] src/sage/symbolic/expression.pyx: Fix markup of doctest output --- src/sage/symbolic/expression.pyx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sage/symbolic/expression.pyx b/src/sage/symbolic/expression.pyx index 3f6cb7b0f3d..518ea825d1e 100644 --- a/src/sage/symbolic/expression.pyx +++ b/src/sage/symbolic/expression.pyx @@ -414,6 +414,7 @@ cpdef bint is_Expression(x): sage: from sage.symbolic.expression import is_Expression sage: is_Expression(x) + doctest:warning... DeprecationWarning: is_Expression is deprecated; use isinstance(..., sage.structure.element.Expression) instead True From 27c53ac6450f789246b1df895bc26950a0cceb65 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 6 Oct 2021 12:55:43 -0700 Subject: [PATCH 283/359] src/sage/features/sagemath.py: Add 'sage.plot' --- src/sage/features/sagemath.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/sage/features/sagemath.py b/src/sage/features/sagemath.py index f18e5e79e88..95676aa2cc1 100644 --- a/src/sage/features/sagemath.py +++ b/src/sage/features/sagemath.py @@ -51,6 +51,12 @@ def __init__(self): PythonModule.__init__(self, 'sage.matrix.matrix_gfpn_dense', spkg='meataxe') +class sage__plot(PythonModule): + + def __init__(self): + PythonModule.__init__(self, 'sage.plot.plot') + + class sage__rings__number_field(PythonModule): def __init__(self): @@ -96,6 +102,8 @@ def sage_optional_tags(): yield 'sage.graphs.mcqd' if sage__matrix__matrix_gfpn_dense().is_present(): yield 'sage.matrix.matrix_gfpn_dense' + if sage__plot().is_present(): + yield 'sage.plot' if sage__rings__number_field().is_present(): yield 'sage.rings.number_field' if sage__rings__real_double().is_present(): From db154ec51e3a22e44cbbd9317e05c8cc9c6b7dec Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 6 Oct 2021 14:50:00 -0700 Subject: [PATCH 284/359] sage.doctest.parsing.RIFtol: Fixup when RealIntervalField not available --- src/sage/doctest/parsing.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/sage/doctest/parsing.py b/src/sage/doctest/parsing.py index 1591dd609cd..7af1b1c8f8c 100644 --- a/src/sage/doctest/parsing.py +++ b/src/sage/doctest/parsing.py @@ -90,9 +90,7 @@ def RIFtol(*args): from warnings import warn warn("RealIntervalField not available, ignoring all tolerance specifications in doctests") def fake_RIFtol(*args): - if len(args) == 2: - return (args[0] + args[1]) / 2 - return args[0] + return 0 _RIFtol = fake_RIFtol else: _RIFtol = RealIntervalField(1044) From 88886ee09c6e402de41ddd415cae0e48d807ce13 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 6 Oct 2021 15:17:03 -0700 Subject: [PATCH 285/359] src/sage/symbolic/expression.pyx: Fix doctest output --- src/sage/symbolic/expression.pyx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/sage/symbolic/expression.pyx b/src/sage/symbolic/expression.pyx index 518ea825d1e..8a75c1c435c 100644 --- a/src/sage/symbolic/expression.pyx +++ b/src/sage/symbolic/expression.pyx @@ -408,7 +408,10 @@ include "pynac_impl.pxi" cpdef bint is_Expression(x): """ - Return True if *x* is a symbolic Expression. + Return True if ``x`` is a symbolic expression. + + This method is deprecated. Use :func:`isinstance` with + :class:`sage.structure.element.Expression` instead. EXAMPLES:: @@ -417,6 +420,7 @@ cpdef bint is_Expression(x): doctest:warning... DeprecationWarning: is_Expression is deprecated; use isinstance(..., sage.structure.element.Expression) instead + See https://trac.sagemath.org/32638 for details. True sage: is_Expression(2) False From f48534bd4dbf4c9612ce0cefd8ef3aedaed10490 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 6 Oct 2021 19:23:30 -0700 Subject: [PATCH 286/359] build/pkgs/sqlite: Update to 3.36.0 --- build/pkgs/sqlite/checksums.ini | 9 +++++---- build/pkgs/sqlite/package-version.txt | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/build/pkgs/sqlite/checksums.ini b/build/pkgs/sqlite/checksums.ini index 72262b7523c..5cb33394ab3 100644 --- a/build/pkgs/sqlite/checksums.ini +++ b/build/pkgs/sqlite/checksums.ini @@ -1,4 +1,5 @@ -tarball=sqlite-autoconf-VERSION.tar.gz -sha1=053d8237eb9741b0e297073810668c2611a8e38e -md5=8f3dfe83387e62ecb91c7c5c09c688dc -cksum=1918823569 +tarball=sqlite-autoconf-3360000.tar.gz +sha1=a4bcf9e951bfb9745214241ba08476299fc2dc1e +md5=f5752052fc5b8e1b539af86a3671eac7 +cksum=763219165 +upstream_url=https://www.sqlite.org/2021/sqlite-autoconf-3360000.tar.gz diff --git a/build/pkgs/sqlite/package-version.txt b/build/pkgs/sqlite/package-version.txt index b4456b4138a..0b477b458f2 100644 --- a/build/pkgs/sqlite/package-version.txt +++ b/build/pkgs/sqlite/package-version.txt @@ -1 +1 @@ -3290000 +3.36.0 From adcd8206905a8ec0bfb6217d9cd8d8d3ecc2765e Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 6 Oct 2021 19:24:22 -0700 Subject: [PATCH 287/359] build/pkgs/sqlite/spkg-install.in: Do not copy in config.* files --- build/pkgs/sqlite/spkg-install.in | 4 ---- 1 file changed, 4 deletions(-) diff --git a/build/pkgs/sqlite/spkg-install.in b/build/pkgs/sqlite/spkg-install.in index f20e4ecdb23..f8151f3ac84 100644 --- a/build/pkgs/sqlite/spkg-install.in +++ b/build/pkgs/sqlite/spkg-install.in @@ -2,10 +2,6 @@ rm -f "$SAGE_LOCAL/bin/sqlite3" cd src -# Use newer version of config.guess and config.sub (see Trac #19711) -cp "$SAGE_ROOT"/config/config.* . - - export CPPFLAGS="$CPPFLAGS -I$SAGE_LOCAL/include" # Old OS X systems need -DSQLITE_WITHOUT_ZONEMALLOC From fb4414d04d250caf3e16ac419b7961635bd56db8 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 6 Oct 2021 19:25:13 -0700 Subject: [PATCH 288/359] build/pkgs/sqlite/spkg-install.in: Remove workaround for ancient OS X --- build/pkgs/sqlite/spkg-install.in | 6 ------ 1 file changed, 6 deletions(-) diff --git a/build/pkgs/sqlite/spkg-install.in b/build/pkgs/sqlite/spkg-install.in index f8151f3ac84..af18b54dd3c 100644 --- a/build/pkgs/sqlite/spkg-install.in +++ b/build/pkgs/sqlite/spkg-install.in @@ -4,12 +4,6 @@ cd src export CPPFLAGS="$CPPFLAGS -I$SAGE_LOCAL/include" -# Old OS X systems need -DSQLITE_WITHOUT_ZONEMALLOC -if uname -sr |grep 'Darwin [0-8][.]' >/dev/null; then - export CPPFLAGS="$CPPFLAGS -DSQLITE_WITHOUT_ZONEMALLOC" -fi - - sdh_configure sdh_make sdh_make_install From 95a51e87c8687ce6458476db47ab32ffae5f81be Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 6 Oct 2021 19:29:09 -0700 Subject: [PATCH 289/359] build/pkgs/sqlite/spkg-install.in: Make sure autotools are not invoked --- build/pkgs/sqlite/spkg-install.in | 3 +++ 1 file changed, 3 insertions(+) diff --git a/build/pkgs/sqlite/spkg-install.in b/build/pkgs/sqlite/spkg-install.in index af18b54dd3c..d071ddebe17 100644 --- a/build/pkgs/sqlite/spkg-install.in +++ b/build/pkgs/sqlite/spkg-install.in @@ -4,6 +4,9 @@ cd src export CPPFLAGS="$CPPFLAGS -I$SAGE_LOCAL/include" +# Trac #32646: configure script does not have --disable-maintainer-mode +rm -f configure.ac */configure.ac Makefile.am + sdh_configure sdh_make sdh_make_install From cf9b75a008388ceaa019e28a3eda883350ba7ee1 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 6 Oct 2021 21:25:22 -0700 Subject: [PATCH 290/359] src/sage/symbolic/relation.py: Remove unused import; use sage.structure.element.Expression for isinstance --- src/sage/symbolic/relation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/symbolic/relation.py b/src/sage/symbolic/relation.py index 698eed45d0e..62eabb3b356 100644 --- a/src/sage/symbolic/relation.py +++ b/src/sage/symbolic/relation.py @@ -1029,7 +1029,7 @@ def solve(f, *args, **kwds): or a list of symbolic expressions. """ from sage.symbolic.ring import is_SymbolicVariable - from sage.symbolic.expression import Expression, is_Expression + from sage.structure.element import Expression explicit_solutions = kwds.get('explicit_solutions', None) multiplicities = kwds.get('multiplicities', None) to_poly_solve = kwds.get('to_poly_solve', None) From 10e8d6395e1c829b6a28750d3035de95862230b8 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 6 Oct 2021 21:36:56 -0700 Subject: [PATCH 291/359] sage.features.sagemath: Use JoinFeature when tag is different from the actually tested module --- src/sage/features/sagemath.py | 75 ++++++++++++++++++++--------------- 1 file changed, 43 insertions(+), 32 deletions(-) diff --git a/src/sage/features/sagemath.py b/src/sage/features/sagemath.py index 95676aa2cc1..f0ecfdddca7 100644 --- a/src/sage/features/sagemath.py +++ b/src/sage/features/sagemath.py @@ -2,21 +2,24 @@ Check for SageMath Python modules """ from . import PythonModule +from .join_feature import JoinFeature -class sage__combinat(PythonModule): +class sage__combinat(JoinFeature): def __init__(self): # sage.combinat will be a namespace package. # Testing whether sage.combinat itself can be imported is meaningless. # Hence, we test a Python module within the package. - PythonModule.__init__(self, 'sage.combinat.combinations') + JoinFeature.__init__(self, 'sage.combinat', + [PythonModule('sage.combinat.combinations')]) -class sage__graphs(PythonModule): +class sage__graphs(JoinFeature): def __init__(self): - PythonModule.__init__(self, 'sage.graphs.graph') + JoinFeature.__init__(self, 'sage.graphs', + [PythonModule('sage.graphs.graph')]) class sage__graphs__bliss(PythonModule): @@ -51,16 +54,18 @@ def __init__(self): PythonModule.__init__(self, 'sage.matrix.matrix_gfpn_dense', spkg='meataxe') -class sage__plot(PythonModule): +class sage__plot(JoinFeature): def __init__(self): - PythonModule.__init__(self, 'sage.plot.plot') + JoinFeature.__init__(self, 'sage.plot', + [PythonModule('sage.plot.plot')]) -class sage__rings__number_field(PythonModule): +class sage__rings__number_field(JoinFeature): def __init__(self): - PythonModule.__init__(self, 'sage.rings.number_field_element') + JoinFeature.__init__(self, 'sage.rings.number_field', + [PythonModule('sage.rings.number_field.number_field_element')]) class sage__rings__real_double(PythonModule): @@ -69,10 +74,12 @@ def __init__(self): PythonModule.__init__(self, 'sage.rings.real_double') -class sage__symbolic(PythonModule): +class sage__symbolic(JoinFeature): def __init__(self): - PythonModule.__init__(self, 'sage.symbolic.expression', spkg="sagemath_symbolics") + JoinFeature.__init__(self, 'sage.symbolic', + [PythonModule('sage.symbolic.expression')], + spkg="sagemath_symbolics") def sage_optional_tags(): @@ -82,31 +89,35 @@ def sage_optional_tags(): These tags are named after Python packages/modules (e.g., :mod:`~sage.symbolic`), not distribution packages (``sagemath-symbolics``). - This is motivated by a separation of concerns: The author of a module that depends + This design is motivated by a separation of concerns: The author of a module that depends on some functionality provided by a Python module usually already knows the name of the Python module, so we do not want to force the author to also know about the distribution package that provides the Python module. Instead, we associate distribution packages to Python modules in - :mod:`sage.features.sagemath` via the ``spkg`` parameter of :class:`PythonModule``. + :mod:`sage.features.sagemath` via the ``spkg`` parameter of :class:`Feature`. + + EXAMPLES:: + + sage: from sage.features.sagemath import sage_optional_tags + sage: list(sage_optional_tags()) # random + ['sage.graphs', + 'sage.graphs.bliss', + 'sage.matrix.matrix_gfpn_dense', + 'sage.plot', + 'sage.rings.number_field', + 'sage.rings.real_double', + 'sage.symbolic'] """ - if sage__combinat().is_present(): - yield 'sage.combinat' - if sage__graphs().is_present(): - yield 'sage.graphs' - if sage__graphs__bliss().is_present(): - yield 'sage.graphs.bliss' - if sage__graphs__graph_decompositions__tdlib().is_present(): - yield 'sage.graphs.graph_decompositions.tdlib' - if sage__graphs__mcqd().is_present(): - yield 'sage.graphs.mcqd' - if sage__matrix__matrix_gfpn_dense().is_present(): - yield 'sage.matrix.matrix_gfpn_dense' - if sage__plot().is_present(): - yield 'sage.plot' - if sage__rings__number_field().is_present(): - yield 'sage.rings.number_field' - if sage__rings__real_double().is_present(): - yield 'sage.rings.real_double' - if sage__symbolic().is_present(): - yield 'sage.symbolic' + for feature in [sage__combinat(), + sage__graphs(), + sage__graphs__bliss(), + sage__graphs__graph_decompositions__tdlib(), + sage__graphs__mcqd(), + sage__matrix__matrix_gfpn_dense(), + sage__plot(), + sage__rings__number_field(), + sage__rings__real_double(), + sage__symbolic()]: + if feature.is_present(): + yield feature.name From 654d09ca4c22f4888d8e511789e57a7627043492 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 6 Oct 2021 22:31:57 -0700 Subject: [PATCH 292/359] sage.features.sagemath: Change sage_optional_tags to sage_features --- src/sage/doctest/control.py | 4 ++-- src/sage/features/sagemath.py | 19 ++++++++----------- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/src/sage/doctest/control.py b/src/sage/doctest/control.py index 05767a50876..3f11a5bf982 100644 --- a/src/sage/doctest/control.py +++ b/src/sage/doctest/control.py @@ -371,8 +371,8 @@ def __init__(self, options, args): from sage.features import package_systems options.optional.update(system.name for system in package_systems()) - from sage.features.sagemath import sage_optional_tags - options.optional.update(sage_optional_tags()) + from sage.features.sagemath import sage_features + options.optional.update(feature.name for feature in sage_features()) # Check that all tags are valid for o in options.optional: diff --git a/src/sage/features/sagemath.py b/src/sage/features/sagemath.py index f0ecfdddca7..91fec0ac498 100644 --- a/src/sage/features/sagemath.py +++ b/src/sage/features/sagemath.py @@ -82,7 +82,7 @@ def __init__(self): spkg="sagemath_symbolics") -def sage_optional_tags(): +def sage_features(): """ Return tags for conditionalizing doctests. @@ -99,15 +99,12 @@ def sage_optional_tags(): EXAMPLES:: - sage: from sage.features.sagemath import sage_optional_tags - sage: list(sage_optional_tags()) # random - ['sage.graphs', - 'sage.graphs.bliss', - 'sage.matrix.matrix_gfpn_dense', - 'sage.plot', - 'sage.rings.number_field', - 'sage.rings.real_double', - 'sage.symbolic'] + sage: from sage.features.sagemath import sage_features + sage: list(sage_features()) # random + [Feature('sage.graphs'), + Feature('sage.graphs.bliss'), + Feature('sage.plot'), + Feature('sage.rings.real_double')] """ for feature in [sage__combinat(), sage__graphs(), @@ -120,4 +117,4 @@ def sage_optional_tags(): sage__rings__real_double(), sage__symbolic()]: if feature.is_present(): - yield feature.name + yield feature From f63a7d0171ba5f753d1755e0aff3fd00e373590c Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 7 Oct 2021 00:19:30 -0700 Subject: [PATCH 293/359] src/sage/features/: Move features depending on optional packages to separate files --- src/sage/features/bliss.py | 14 +++++++----- src/sage/features/mcqd.py | 11 ++++++++++ src/sage/features/meataxe.py | 11 ++++++++++ src/sage/features/sagemath.py | 40 ++--------------------------------- src/sage/features/tdlib.py | 11 ++++++++++ 5 files changed, 44 insertions(+), 43 deletions(-) create mode 100644 src/sage/features/mcqd.py create mode 100644 src/sage/features/meataxe.py create mode 100644 src/sage/features/tdlib.py diff --git a/src/sage/features/bliss.py b/src/sage/features/bliss.py index bda43f4a5f8..d870ade5973 100644 --- a/src/sage/features/bliss.py +++ b/src/sage/features/bliss.py @@ -3,6 +3,7 @@ Checks for bliss """ from . import CythonFeature, PythonModule +from .join_feature import JoinFeature TEST_CODE = """ @@ -45,10 +46,10 @@ def __init__(self): url="http://www.tcs.hut.fi/Software/bliss/") -class Bliss(PythonModule): +class Bliss(JoinFeature): r""" A :class:`Feature` which describes whether the :mod:`sage.graphs.bliss` - module has been enabled for this build of Sage and is functional. + module is available in this installation of Sage. EXAMPLES:: @@ -61,7 +62,10 @@ def __init__(self): sage: from sage.features.bliss import Bliss sage: Bliss() - Feature('sage.graphs.bliss') + Feature('bliss') """ - PythonModule.__init__(self, "sage.graphs.bliss", spkg="bliss", - url="http://www.tcs.hut.fi/Software/bliss/") + # Currently part of sagemath_standard, conditionally built. + # Will be changed to spkg='sagemath_bliss' later + JoinFeature.__init__(self, "bliss", + [PythonModule("sage.graphs.bliss", spkg="bliss", + url="http://www.tcs.hut.fi/Software/bliss/")]) diff --git a/src/sage/features/mcqd.py b/src/sage/features/mcqd.py new file mode 100644 index 00000000000..6539af1d6d5 --- /dev/null +++ b/src/sage/features/mcqd.py @@ -0,0 +1,11 @@ +from . import PythonModule +from .join_feature import JoinFeature + + +class Mcqd(JoinFeature): + + def __init__(self): + # Currently part of sagemath_standard, conditionally built. + # Will be changed to spkg='sagemath_mcqd' later + JoinFeature.__init__(self, 'mcqd', + [PythonModule('sage.graphs.mcqd', spkg='mcqd')]) diff --git a/src/sage/features/meataxe.py b/src/sage/features/meataxe.py new file mode 100644 index 00000000000..a8b65d166dc --- /dev/null +++ b/src/sage/features/meataxe.py @@ -0,0 +1,11 @@ +from . import PythonModule +from .join_feature import JoinFeature + + +class Meataxe(JoinFeature): + + def __init__(self): + # Currently part of sagemath_standard, conditionally built. + # Will be changed to spkg='sagemath_meataxe' later + JoinFeature.__init__(self, 'meataxe', + [PythonModule('sage.matrix.matrix_gfpn_dense', spkg='meataxe')]) diff --git a/src/sage/features/sagemath.py b/src/sage/features/sagemath.py index 91fec0ac498..2af7def3668 100644 --- a/src/sage/features/sagemath.py +++ b/src/sage/features/sagemath.py @@ -22,38 +22,6 @@ def __init__(self): [PythonModule('sage.graphs.graph')]) -class sage__graphs__bliss(PythonModule): - - def __init__(self): - # Currently part of sagemath_standard, conditionally built. - # Will be changed to spkg='sagemath_bliss' later - PythonModule.__init__(self, 'sage.graphs.bliss', spkg='bliss') - - -class sage__graphs__graph_decompositions__tdlib(PythonModule): - - def __init__(self): - # Currently part of sagemath_standard, conditionally built. - # Will be changed to spkg='sagemath_tdlib' later - PythonModule.__init__(self, 'sage.graphs.graph_decompositions.tdlib', spkg='tdlib') - - -class sage__graphs__mcqd(PythonModule): - - def __init__(self): - # Currently part of sagemath_standard, conditionally built. - # Will be changed to spkg='sagemath_mcqd' later - PythonModule.__init__(self, 'sage.graphs.mcqd', spkg='mcqd') - - -class sage__matrix__matrix_gfpn_dense(PythonModule): - - def __init__(self): - # Currently part of sagemath_standard, conditionally built. - # Will be changed to spkg='sagemath_meataxe' later - PythonModule.__init__(self, 'sage.matrix.matrix_gfpn_dense', spkg='meataxe') - - class sage__plot(JoinFeature): def __init__(self): @@ -84,7 +52,7 @@ def __init__(self): def sage_features(): """ - Return tags for conditionalizing doctests. + Return features corresponding to parts of the Sage library. These tags are named after Python packages/modules (e.g., :mod:`~sage.symbolic`), not distribution packages (``sagemath-symbolics``). @@ -102,16 +70,12 @@ def sage_features(): sage: from sage.features.sagemath import sage_features sage: list(sage_features()) # random [Feature('sage.graphs'), - Feature('sage.graphs.bliss'), Feature('sage.plot'), + Feature('sage.rings.number_field'), Feature('sage.rings.real_double')] """ for feature in [sage__combinat(), sage__graphs(), - sage__graphs__bliss(), - sage__graphs__graph_decompositions__tdlib(), - sage__graphs__mcqd(), - sage__matrix__matrix_gfpn_dense(), sage__plot(), sage__rings__number_field(), sage__rings__real_double(), diff --git a/src/sage/features/tdlib.py b/src/sage/features/tdlib.py new file mode 100644 index 00000000000..e01e1bdfdf6 --- /dev/null +++ b/src/sage/features/tdlib.py @@ -0,0 +1,11 @@ +from . import PythonModule +from .join_feature import JoinFeature + + +class Tdlib(JoinFeature): + + def __init__(self): + # Currently part of sagemath_standard, conditionally built. + # Will be changed to spkg='sagemath_tdlib' later + JoinFeature.__init__(self, 'tdlib', + [PythonModule('sage.graphs.graph_decompositions.tdlib', spkg='tdlib')]) From f4e0d26d4eb193da548044d51badaf349d1860dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Thu, 7 Oct 2021 09:45:03 +0200 Subject: [PATCH 294/359] is_linear_interval, in frontend, and another algo in backend --- src/sage/combinat/posets/hasse_diagram.py | 65 ++++++++++++++++------- src/sage/combinat/posets/posets.py | 27 +++++++++- 2 files changed, 71 insertions(+), 21 deletions(-) diff --git a/src/sage/combinat/posets/hasse_diagram.py b/src/sage/combinat/posets/hasse_diagram.py index e8c0d6b92b2..9d0a62a1f5a 100644 --- a/src/sage/combinat/posets/hasse_diagram.py +++ b/src/sage/combinat/posets/hasse_diagram.py @@ -2359,30 +2359,57 @@ def is_linear_interval(self, t_min, t_max) -> bool: This means that this interval is a total order. - .. WARNING:: - - For speed, this assumes that the input is an interval! - EXAMPLES:: sage: P = posets.PentagonPoset() sage: H = P._hasse_diagram - sage: H.is_linear_interval(0,4) + sage: H.is_linear_interval(0, 4) False - sage: H.is_linear_interval(0,3) + sage: H.is_linear_interval(0, 3) True - """ - t = t_max - while t != t_min: - found = False - for u in self.neighbor_in_iterator(t): - if self.is_lequal(t_min, u): - if not found: - found = True - t = u - else: - return False - return True + sage: H.is_linear_interval(1, 3) + False + sage: H.is_linear_interval(1, 1) + True + + TESTS:: + + sage: P = posets.TamariLattice(3) + sage: H = P._hasse_diagram + sage: D = H._leq_storage + sage: a, b = H.bottom(), H.top() + sage: H.is_linear_interval(a, b) + False + sage: H.is_linear_interval(a, a) + True + """ + if '_leq_storage' in self.__dict__: + if not self.is_lequal(t_min, t_max): # very quick check + return False + t = t_max + while t != t_min: + found = False + for u in self.neighbor_in_iterator(t): + if self.is_lequal(t_min, u): + if not found: + found = True + t = u + else: + return False + return True + + # fall back to default implementation + it = self.all_paths_iterator([t_min], [t_max], + simple=True, trivial=True) + try: + next(it) + except StopIteration: # not comparable + return False + try: + next(it) + except StopIteration: # one path + return True + return False def diamonds(self): r""" @@ -3312,7 +3339,7 @@ def principal_congruences_poset(self): D[ab] = cong P[ab] = cong_ - # Todo: Make a function that creates the poset from a set + # TODO: Make a function that creates the poset from a set # by comparison function with minimal number of comparisons. T = SetPartitions(n) diff --git a/src/sage/combinat/posets/posets.py b/src/sage/combinat/posets/posets.py index f987759cae4..9ca16928e51 100644 --- a/src/sage/combinat/posets/posets.py +++ b/src/sage/combinat/posets/posets.py @@ -66,7 +66,6 @@ :meth:`~FinitePoset.height` | Return the number of elements in a longest chain of the poset. :meth:`~FinitePoset.width` | Return the number of elements in a longest antichain of the poset. :meth:`~FinitePoset.relations_number` | Return the number of relations in the poset. - :meth:`~FinitePoset.linear_intervals_count` | Return the enumeration of linear intervals in the poset. :meth:`~FinitePoset.dimension` | Return the dimension of the poset. :meth:`~FinitePoset.jump_number` | Return the jump number of the poset. :meth:`~FinitePoset.magnitude` | Return the magnitude of the poset. @@ -128,7 +127,7 @@ :meth:`~FinitePoset.canonical_label` | Return copy of the poset canonically (re)labelled to integers. :meth:`~FinitePoset.slant_sum` | Return the slant sum poset of two posets. -**Chains & antichains** +**Chains, antichains & linear intervals** .. csv-table:: :class: contentstable @@ -137,6 +136,7 @@ :meth:`~FinitePoset.is_chain_of_poset` | Return ``True`` if elements in the given list are comparable. :meth:`~FinitePoset.is_antichain_of_poset` | Return ``True`` if elements in the given list are incomparable. + :meth:`~FinitePoset.is_linear_interval` | Return whether the given interval is a total order. :meth:`~FinitePoset.chains` | Return the chains of the poset. :meth:`~FinitePoset.antichains` | Return the antichains of the poset. :meth:`~FinitePoset.maximal_chains` | Return the maximal chains of the poset. @@ -146,6 +146,7 @@ :meth:`~FinitePoset.antichains_iterator` | Return an iterator over the antichains of the poset. :meth:`~FinitePoset.random_maximal_chain` | Return a random maximal chain. :meth:`~FinitePoset.random_maximal_antichain` | Return a random maximal antichain. + :meth:`~FinitePoset.linear_intervals_count` | Return the enumeration of linear intervals in the poset. **Drawing** @@ -2659,6 +2660,8 @@ def linear_intervals_count(self) -> list[int]: OUTPUT: list of integers + .. SEEALSO:: :meth:`is_linear_interval` + EXAMPLES:: sage: P = posets.PentagonPoset() @@ -2699,6 +2702,26 @@ def linear_intervals_count(self) -> list[int]: break return poly + def is_linear_interval(self, x, y) -> bool: + """ + Return whether the interval ``[x, y]`` is linear. + + This means that this interval is a total order. + + EXAMPLES:: + + sage: P = posets.PentagonPoset() + sage: P.is_linear_interval(0, 4) + False + sage: P.is_linear_interval(0, 3) + True + sage: P.is_linear_interval(1, 3) + False + """ + a = self._element_to_vertex(x) + b = self._element_to_vertex(y) + return self._hasse_diagram.is_linear_interval(a, b) + def is_incomparable_chain_free(self, m, n=None) -> bool: r""" Return ``True`` if the poset is `(m+n)`-free, and ``False`` otherwise. From bb7b73307961922191a95eb1dda0bb5f8978d355 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Thu, 7 Oct 2021 12:00:49 +0200 Subject: [PATCH 295/359] remove things form namespace (steenrod base and modular forms dimensions) --- src/sage/algebras/steenrod/all.py | 7 ++-- src/sage/modular/all.py | 11 +++--- src/sage/modular/dims.py | 59 +++++++------------------------ 3 files changed, 23 insertions(+), 54 deletions(-) diff --git a/src/sage/algebras/steenrod/all.py b/src/sage/algebras/steenrod/all.py index 77a93db16ed..134b2b032cf 100644 --- a/src/sage/algebras/steenrod/all.py +++ b/src/sage/algebras/steenrod/all.py @@ -1,7 +1,8 @@ """ The Steenrod algebra """ - from .steenrod_algebra import SteenrodAlgebra, Sq -from .steenrod_algebra_bases import steenrod_algebra_basis - +from sage.misc.lazy_import import lazy_import +lazy_import('sage.algebras.steenrod.steenrod_algebra_bases', + 'steenrod_algebra_basis', + deprecation=(32647, 'removed from namespace')) diff --git a/src/sage/modular/all.py b/src/sage/modular/all.py index 2532c33e107..cfccb18e65f 100644 --- a/src/sage/modular/all.py +++ b/src/sage/modular/all.py @@ -20,11 +20,12 @@ from .cusps import Cusp, Cusps -from .dims import (dimension_cusp_forms, - dimension_new_cusp_forms, - dimension_eis, - dimension_modular_forms, - sturm_bound) +lazy_import('sage.modular.dims', ('dimension_cusp_forms', + 'dimension_new_cusp_forms', + 'dimension_eis', + 'dimension_modular_forms', + 'sturm_bound'), + deprecation=(32647, 'removed from main namespace')) from .etaproducts import (EtaGroup, EtaProduct, EtaGroupElement, AllCusps, CuspFamily) diff --git a/src/sage/modular/dims.py b/src/sage/modular/dims.py index 1bf9aba3773..1050a557330 100644 --- a/src/sage/modular/dims.py +++ b/src/sage/modular/dims.py @@ -265,32 +265,25 @@ def dimension_new_cusp_forms(X, k=2, p=0): EXAMPLES:: + sage: from sage.modular.dims import dimension_new_cusp_forms sage: dimension_new_cusp_forms(100,2) 1 - :: - sage: dimension_new_cusp_forms(Gamma0(100),2) 1 sage: dimension_new_cusp_forms(Gamma0(100),4) 5 - :: - sage: dimension_new_cusp_forms(Gamma1(100),2) 141 sage: dimension_new_cusp_forms(Gamma1(100),4) 463 - :: - sage: dimension_new_cusp_forms(DirichletGroup(100).1^2,2) 2 sage: dimension_new_cusp_forms(DirichletGroup(100).1^2,4) 8 - :: - sage: sum(dimension_new_cusp_forms(e,3) for e in DirichletGroup(30)) 12 sage: dimension_new_cusp_forms(Gamma1(30),3) @@ -315,8 +308,7 @@ def dimension_new_cusp_forms(X, k=2, p=0): return Gamma1(N).dimension_new_cusp_forms(k, eps=X, p=p) elif isinstance(X, (int, Integer)): return Gamma0(X).dimension_new_cusp_forms(k, p=p) - else: - raise TypeError("X (=%s) must be an integer, a Dirichlet character or a congruence subgroup of type Gamma0, Gamma1 or GammaH" % X) + raise TypeError(f"X (={X}) must be an integer, a Dirichlet character or a congruence subgroup of type Gamma0, Gamma1 or GammaH") def dimension_cusp_forms(X, k=2): @@ -333,25 +325,20 @@ def dimension_cusp_forms(X, k=2): EXAMPLES:: + sage: from sage.modular.dims import dimension_cusp_forms sage: dimension_cusp_forms(5,4) 1 - :: - sage: dimension_cusp_forms(Gamma0(11),2) 1 sage: dimension_cusp_forms(Gamma1(13),2) 2 - :: - sage: dimension_cusp_forms(DirichletGroup(13).0^2,2) 1 sage: dimension_cusp_forms(DirichletGroup(13).0,3) 1 - :: - sage: dimension_cusp_forms(Gamma0(11),2) 1 sage: dimension_cusp_forms(Gamma0(11),0) @@ -363,8 +350,6 @@ def dimension_cusp_forms(X, k=2): sage: dimension_cusp_forms(Gamma0(1),4) 0 - :: - sage: dimension_cusp_forms(Gamma0(389),2) 32 sage: dimension_cusp_forms(Gamma0(389),4) @@ -374,8 +359,6 @@ def dimension_cusp_forms(X, k=2): sage: dimension_cusp_forms(Gamma0(11),1) 0 - :: - sage: dimension_cusp_forms(Gamma1(11),2) 1 sage: dimension_cusp_forms(Gamma1(1),12) @@ -385,8 +368,6 @@ def dimension_cusp_forms(X, k=2): sage: dimension_cusp_forms(Gamma1(1),4) 0 - :: - sage: dimension_cusp_forms(Gamma1(389),2) 6112 sage: dimension_cusp_forms(Gamma1(389),4) @@ -394,13 +375,9 @@ def dimension_cusp_forms(X, k=2): sage: dimension_cusp_forms(Gamma1(2005),2) 159201 - :: - sage: dimension_cusp_forms(Gamma1(11),1) 0 - :: - sage: e = DirichletGroup(13).0 sage: e.order() 12 @@ -426,9 +403,8 @@ def dimension_cusp_forms(X, k=2): return X.dimension_cusp_forms(k) elif isinstance(X, (int, Integer)): return Gamma0(X).dimension_cusp_forms(k) - else: - raise TypeError("argument 1 must be a Dirichlet character, an integer " - "or a finite index subgroup of SL2Z") + raise TypeError("argument 1 must be a Dirichlet character, an integer " + "or a finite index subgroup of SL2Z") def dimension_eis(X, k=2): @@ -445,11 +421,10 @@ def dimension_eis(X, k=2): EXAMPLES:: + sage: from sage.modular.dims import dimension_eis sage: dimension_eis(5,4) 2 - :: - sage: dimension_eis(Gamma0(11),2) 1 sage: dimension_eis(Gamma1(13),2) @@ -457,8 +432,6 @@ def dimension_eis(X, k=2): sage: dimension_eis(Gamma1(2006),2) 3711 - :: - sage: e = DirichletGroup(13).0 sage: e.order() 12 @@ -467,8 +440,6 @@ def dimension_eis(X, k=2): sage: dimension_eis(e^2,2) 2 - :: - sage: e = DirichletGroup(13).0 sage: e.order() 12 @@ -479,8 +450,6 @@ def dimension_eis(X, k=2): sage: dimension_eis(e,13) 2 - :: - sage: G = DirichletGroup(20) sage: dimension_eis(G.0,3) 4 @@ -489,8 +458,6 @@ def dimension_eis(X, k=2): sage: dimension_eis(G.1^2,2) 6 - :: - sage: G = DirichletGroup(200) sage: e = prod(G.gens(), G(1)) sage: e.conductor() @@ -498,8 +465,7 @@ def dimension_eis(X, k=2): sage: dimension_eis(e,2) 4 - :: - + sage: from sage.modular.dims import dimension_modular_forms sage: dimension_modular_forms(Gamma1(4), 11) 6 """ @@ -509,8 +475,7 @@ def dimension_eis(X, k=2): return Gamma1(X.modulus()).dimension_eis(k, X) elif isinstance(X, (int, Integer)): return Gamma0(X).dimension_eis(k) - else: - raise TypeError("argument in dimension_eis must be an integer, a Dirichlet character, or a finite index subgroup of SL2Z (got %s)" % X) + raise TypeError(f"argument in dimension_eis must be an integer, a Dirichlet character, or a finite index subgroup of SL2Z (got {X})") def dimension_modular_forms(X, k=2): @@ -527,6 +492,7 @@ def dimension_modular_forms(X, k=2): EXAMPLES:: + sage: from sage.modular.dims import dimension_modular_forms sage: dimension_modular_forms(Gamma0(11),2) 2 sage: dimension_modular_forms(Gamma0(11),0) @@ -542,8 +508,10 @@ def dimension_modular_forms(X, k=2): sage: e = DirichletGroup(20).1 sage: dimension_modular_forms(e,3) 9 + sage: from sage.modular.dims import dimension_cusp_forms sage: dimension_cusp_forms(e,3) 3 + sage: from sage.modular.dims import dimension_eis sage: dimension_eis(e,3) 6 sage: dimension_modular_forms(11,2) @@ -576,6 +544,7 @@ def sturm_bound(level, weight=2): EXAMPLES:: + sage: from sage.modular.dims import sturm_bound sage: sturm_bound(11,2) 2 sage: sturm_bound(389,2) @@ -592,8 +561,6 @@ def sturm_bound(level, weight=2): if is_ArithmeticSubgroup(level): if level.is_congruence(): return level.sturm_bound(weight) - else: - raise ValueError("no Sturm bound defined for noncongruence " - "subgroups") + raise ValueError("no Sturm bound defined for noncongruence subgroups") if isinstance(level, (int, Integer)): return Gamma0(level).sturm_bound(weight) From 8c91c6be45c0375d5a7d7a9a6aacd427909b3bc6 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 7 Oct 2021 11:13:34 -0700 Subject: [PATCH 296/359] build/pkgs/sqlite/spkg-install.in: Just make sure that autotools-generated files are newer than sources --- build/pkgs/sqlite/spkg-install.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/pkgs/sqlite/spkg-install.in b/build/pkgs/sqlite/spkg-install.in index d071ddebe17..d13df2ba1b8 100644 --- a/build/pkgs/sqlite/spkg-install.in +++ b/build/pkgs/sqlite/spkg-install.in @@ -5,7 +5,7 @@ cd src export CPPFLAGS="$CPPFLAGS -I$SAGE_LOCAL/include" # Trac #32646: configure script does not have --disable-maintainer-mode -rm -f configure.ac */configure.ac Makefile.am +touch configure */configure Makefile.in sdh_configure sdh_make From c0e73d8531b99e65379a6b9e79e096b380204bbf Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 2 Oct 2021 18:38:09 -0700 Subject: [PATCH 297/359] src/sage/geometry/polyhedron/double_description.py: Add # optional - sage.rings.number_field --- .../geometry/polyhedron/double_description.py | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/sage/geometry/polyhedron/double_description.py b/src/sage/geometry/polyhedron/double_description.py index d8d85adde6e..06d729e12aa 100644 --- a/src/sage/geometry/polyhedron/double_description.py +++ b/src/sage/geometry/polyhedron/double_description.py @@ -28,10 +28,10 @@ `\RR`, for example:: sage: from sage.geometry.polyhedron.double_description import StandardAlgorithm - sage: A = matrix(AA, [(1,0,1), (0,1,1), (-AA(2).sqrt(),-AA(3).sqrt(),1), + sage: A = matrix(AA, [(1,0,1), (0,1,1), (-AA(2).sqrt(),-AA(3).sqrt(),1), # optional - sage.rings.number_field ....: (-AA(3).sqrt(),-AA(2).sqrt(),1)]) - sage: alg = StandardAlgorithm(A) - sage: alg.run().R + sage: alg = StandardAlgorithm(A) # optional - sage.rings.number_field + sage: alg.run().R # optional - sage.rings.number_field [(-0.4177376677004119?, 0.5822623322995881?, 0.4177376677004119?), (-0.2411809548974793?, -0.2411809548974793?, 0.2411809548974793?), (0.07665629029830300?, 0.07665629029830300?, 0.2411809548974793?), @@ -411,11 +411,12 @@ def matrix_space(self, nrows, ncols): sage: DD.matrix_space(3,2) Full MatrixSpace of 3 by 2 dense matrices over Rational Field - sage: K. = QuadraticField(2) - sage: A = matrix([[1,sqrt2],[2,0]]) - sage: DD, _ = Problem(A).initial_pair() - sage: DD.matrix_space(1,2) - Full MatrixSpace of 1 by 2 dense matrices over Number Field in sqrt2 with defining polynomial x^2 - 2 with sqrt2 = 1.414213562373095? + sage: K. = QuadraticField(2) # optional - sage.rings.number_field + sage: A = matrix([[1,sqrt2],[2,0]]) # optional - sage.rings.number_field + sage: DD, _ = Problem(A).initial_pair() # optional - sage.rings.number_field + sage: DD.matrix_space(1,2) # optional - sage.rings.number_field + Full MatrixSpace of 1 by 2 dense matrices + over Number Field in sqrt2 with defining polynomial x^2 - 2 with sqrt2 = 1.414213562373095? """ return MatrixSpace(self.problem.base_ring(), nrows, ncols) @@ -596,9 +597,9 @@ def base_ring(self): EXAMPLES:: - sage: A = matrix(AA, [(1, 1), (-1, 1)]) + sage: A = matrix(AA, [(1, 1), (-1, 1)]) # optional - sage.rings.number_field sage: from sage.geometry.polyhedron.double_description import Problem - sage: Problem(A).base_ring() + sage: Problem(A).base_ring() # optional - sage.rings.number_field Algebraic Real Field """ return self._field From 49658e0b1931df29b01ca914705bd0bd96c242b7 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 4 Oct 2021 19:49:27 -0700 Subject: [PATCH 298/359] src/sage/geometry/polyhedron/backend_normaliz.py: Mark non-rational examples # optional - sage.rings.number_field --- .../geometry/polyhedron/backend_normaliz.py | 114 +++++++++--------- 1 file changed, 57 insertions(+), 57 deletions(-) diff --git a/src/sage/geometry/polyhedron/backend_normaliz.py b/src/sage/geometry/polyhedron/backend_normaliz.py index af8f3287d9a..cfd9b38baab 100644 --- a/src/sage/geometry/polyhedron/backend_normaliz.py +++ b/src/sage/geometry/polyhedron/backend_normaliz.py @@ -47,12 +47,12 @@ def _number_field_elements_from_algebraics_list_of_lists_of_lists(listss, **kwds EXAMPLES:: - sage: rt2 = AA(sqrt(2)); rt2 + sage: rt2 = AA(sqrt(2)); rt2 # optional - sage.rings.number_field 1.414213562373095? - sage: rt3 = AA(sqrt(3)); rt3 + sage: rt3 = AA(sqrt(3)); rt3 # optional - sage.rings.number_field 1.732050807568878? sage: from sage.geometry.polyhedron.backend_normaliz import _number_field_elements_from_algebraics_list_of_lists_of_lists - sage: K, results, hom = _number_field_elements_from_algebraics_list_of_lists_of_lists([[[rt2], [1]], [[rt3]], [[1], []]]); results + sage: K, results, hom = _number_field_elements_from_algebraics_list_of_lists_of_lists([[[rt2], [1]], [[rt3]], [[1], []]]); results # optional - sage.rings.number_field [[[-a^3 + 3*a], [1]], [[-a^2 + 2]], [[1], []]] """ from sage.rings.qqbar import number_field_elements_from_algebraics @@ -171,7 +171,7 @@ class Polyhedron_normaliz(Polyhedron_base): Algebraic polyhedra:: - sage: P = Polyhedron(vertices=[[1], [sqrt(2)]], backend='normaliz', verbose=True) # optional - pynormaliz + sage: P = Polyhedron(vertices=[[1], [sqrt(2)]], backend='normaliz', verbose=True) # optional - pynormaliz # optional - sage.rings.number_field # ----8<---- Equivalent Normaliz input file ----8<---- amb_space 1 number_field min_poly (a^2 - 2) embedding [1.414213562373095 +/- 2.99e-16] @@ -182,16 +182,16 @@ class Polyhedron_normaliz(Polyhedron_base): (a) 1 # ----8<-------------------8<-------------------8<---- # Calling PyNormaliz.NmzCone(cone=[], number_field=['a^2 - 2', 'a', '[1.414213562373095 +/- 2.99e-16]'], subspace=[], vertices=[[1, 1], [[[0, 1], [1, 1]], 1]]) - sage: P # optional - pynormaliz + sage: P # optional - pynormaliz # optional - sage.rings.number_field A 1-dimensional polyhedron in (Symbolic Ring)^1 defined as the convex hull of 2 vertices - sage: P.vertices() # optional - pynormaliz + sage: P.vertices() # optional - pynormaliz # optional - sage.rings.number_field (A vertex at (1), A vertex at (sqrt(2))) - sage: P = polytopes.icosahedron(exact=True, backend='normaliz') # optional - pynormaliz - sage: P # optional - pynormaliz + sage: P = polytopes.icosahedron(exact=True, backend='normaliz') # optional - pynormaliz # optional - sage.rings.number_field + sage: P # optional - pynormaliz # optional - sage.rings.number_field A 3-dimensional polyhedron in (Number Field in sqrt5 with defining polynomial x^2 - 5 with sqrt5 = 2.236067977499790?)^3 defined as the convex hull of 12 vertices - sage: x = polygen(ZZ); P = Polyhedron(vertices=[[sqrt(2)], [AA.polynomial_root(x^3-2, RIF(0,3))]], backend='normaliz', verbose=True) # optional - pynormaliz + sage: x = polygen(ZZ); P = Polyhedron(vertices=[[sqrt(2)], [AA.polynomial_root(x^3-2, RIF(0,3))]], backend='normaliz', verbose=True) # optional - pynormaliz # optional - sage.rings.number_field # ----8<---- Equivalent Normaliz input file ----8<---- amb_space 1 number_field min_poly (a^6 - 2) embedding [1.122462048309373 +/- 5.38e-16] @@ -202,9 +202,9 @@ class Polyhedron_normaliz(Polyhedron_base): (a^2) 1 # ----8<-------------------8<-------------------8<---- # Calling PyNormaliz.NmzCone(cone=[], number_field=['a^6 - 2', 'a', '[1.122462048309373 +/- 5.38e-16]'], subspace=[], vertices=[[[[0, 1], [0, 1], [0, 1], [1, 1], [0, 1], [0, 1]], 1], [[[0, 1], [0, 1], [1, 1], [0, 1], [0, 1], [0, 1]], 1]]) - sage: P # optional - pynormaliz + sage: P # optional - pynormaliz # optional - sage.rings.number_field A 1-dimensional polyhedron in (Symbolic Ring)^1 defined as the convex hull of 2 vertices - sage: P.vertices() # optional - pynormaliz + sage: P.vertices() # optional - pynormaliz # optional - sage.rings.number_field (A vertex at (2^(1/3)), A vertex at (sqrt(2))) """ @@ -255,20 +255,20 @@ def _nmz_result(self, normaliz_cone, property): NormalizError: Some error in the normaliz input data detected: Unknown ConeProperty... sage: x = polygen(QQ, 'x') - sage: K. = NumberField(x^3 - 3, embedding=AA(3)**(1/3)) - sage: p = Polyhedron(vertices=[(0,0),(1,1),(a,3),(-1,a**2)], rays=[(-1,-a)], backend='normaliz') # optional - pynormaliz - sage: sorted(p._nmz_result(p._normaliz_cone, 'VerticesOfPolyhedron')) # optional - pynormaliz + sage: K. = NumberField(x^3 - 3, embedding=AA(3)**(1/3)) # optional - sage.rings.number_field + sage: p = Polyhedron(vertices=[(0,0),(1,1),(a,3),(-1,a**2)], rays=[(-1,-a)], backend='normaliz') # optional - pynormaliz # optional - sage.rings.number_field + sage: sorted(p._nmz_result(p._normaliz_cone, 'VerticesOfPolyhedron')) # optional - pynormaliz # optional - sage.rings.number_field [[-1, a^2, 1], [1, 1, 1], [a, 3, 1]] - sage: triangulation_generators = p._nmz_result(p._normaliz_cone, 'Triangulation')[1] # optional - pynormaliz - sage: sorted(triangulation_generators) # optional - pynormaliz + sage: triangulation_generators = p._nmz_result(p._normaliz_cone, 'Triangulation')[1] # optional - pynormaliz # optional - sage.rings.number_field + sage: sorted(triangulation_generators) # optional - pynormaliz # optional - sage.rings.number_field [[-a^2, -3, 0], [-1, a^2, 1], [0, 0, 1], [1, 1, 1], [a, 3, 1]] - sage: p._nmz_result(p._normaliz_cone, 'AffineDim') == 2 # optional - pynormaliz + sage: p._nmz_result(p._normaliz_cone, 'AffineDim') == 2 # optional - pynormaliz # optional - sage.rings.number_field True - sage: p._nmz_result(p._normaliz_cone, 'EmbeddingDim') == 3 # optional - pynormaliz + sage: p._nmz_result(p._normaliz_cone, 'EmbeddingDim') == 3 # optional - pynormaliz # optional - sage.rings.number_field True - sage: p._nmz_result(p._normaliz_cone, 'ExtremeRays') # optional - pynormaliz + sage: p._nmz_result(p._normaliz_cone, 'ExtremeRays') # optional - pynormaliz # optional - sage.rings.number_field [[-1/3*a^2, -1, 0]] - sage: p._nmz_result(p._normaliz_cone, 'MaximalSubspace') # optional - pynormaliz + sage: p._nmz_result(p._normaliz_cone, 'MaximalSubspace') # optional - pynormaliz # optional - sage.rings.number_field [] """ def rational_handler(list): @@ -313,7 +313,7 @@ def _convert_to_pynormaliz(x): TESTS:: - sage: K. = QuadraticField(2) + sage: K. = QuadraticField(2) # optional - sage.rings.number_field sage: from sage.geometry.polyhedron.backend_normaliz import Polyhedron_normaliz as Pn sage: Pn._convert_to_pynormaliz(17) 17 @@ -325,9 +325,9 @@ def _convert_to_pynormaliz(x): [[28, 5]] sage: Pn._convert_to_pynormaliz(28901824309821093821093812093810928309183091832091/5234573685674784567853456543456456786543456765) [[28901824309821093821093812093810928309183091832091, 5234573685674784567853456543456456786543456765]] - sage: Pn._convert_to_pynormaliz(7 + sqrt2) + sage: Pn._convert_to_pynormaliz(7 + sqrt2) # optional - sage.rings.number_field [[7, 1], [1, 1]] - sage: Pn._convert_to_pynormaliz(7/2 + sqrt2) + sage: Pn._convert_to_pynormaliz(7/2 + sqrt2) # optional - sage.rings.number_field [[7, 2], [1, 1]] sage: Pn._convert_to_pynormaliz([[1, 2], (3, 4)]) [[1, 2], [3, 4]] @@ -335,8 +335,8 @@ def _convert_to_pynormaliz(x): Check that :trac:`29836` is fixed:: sage: P = polytopes.simplex(backend='normaliz') # optional - pynormaliz - sage: K. = QuadraticField(2) # optional - pynormaliz - sage: P.dilation(sqrt2) # optional - pynormaliz + sage: K. = QuadraticField(2) # optional - pynormaliz # optional - sage.rings.number_field + sage: P.dilation(sqrt2) # optional - pynormaliz # optional - sage.rings.number_field A 3-dimensional polyhedron in (Number Field in sqrt2 with defining polynomial x^2 - 2 with sqrt2 = 1.41...)^4 defined as the convex hull of 4 vertices """ def _QQ_pair(x): @@ -369,16 +369,16 @@ def _init_from_normaliz_data(self, data, normaliz_field=None, verbose=False): [[0, -1, 2], [0, 2, -1]] sage: from sage.geometry.polyhedron.backend_normaliz import Polyhedron_normaliz # optional - pynormaliz - sage: from sage.rings.qqbar import AA # optional - pynormaliz - sage: from sage.rings.number_field.number_field import QuadraticField # optional - pynormaliz + sage: from sage.rings.qqbar import AA # optional - pynormaliz # optional - sage.rings.number_field + sage: from sage.rings.number_field.number_field import QuadraticField # optional - pynormaliz # optional - sage.rings.number_field sage: data = {'number_field': ['a^2 - 2', 'a', '[1.4 +/- 0.1]'], # optional - pynormaliz ....: 'inhom_inequalities': [[-1, 2, 0], [0, 0, 1], [2, -1, 0]]} sage: from sage.geometry.polyhedron.parent import Polyhedra_normaliz # optional - pynormaliz - sage: parent = Polyhedra_normaliz(AA, 2, 'normaliz') # optional - pynormaliz - sage: Polyhedron_normaliz(parent, None, None, normaliz_data=data, # indirect doctest, optional - pynormaliz + sage: parent = Polyhedra_normaliz(AA, 2, 'normaliz') # optional - pynormaliz # optional - sage.rings.number_field + sage: Polyhedron_normaliz(parent, None, None, normaliz_data=data, # indirect doctest, optional - pynormaliz # optional - sage.rings.number_field ....: normaliz_field=QuadraticField(2)) A 2-dimensional polyhedron in AA^2 defined as the convex hull of 1 vertex and 2 rays - sage: _.inequalities_list() # optional - pynormaliz + sage: _.inequalities_list() # optional - pynormaliz # optional - sage.rings.number_field [[0, -1/2, 1], [0, 2, -1]] """ if normaliz_field is None: @@ -433,10 +433,10 @@ def _is_zero(self, x): EXAMPLES:: - sage: p = Polyhedron([(sqrt(3),sqrt(2))], base_ring=AA) - sage: p._is_zero(0) + sage: p = Polyhedron([(sqrt(3),sqrt(2))], base_ring=AA) # optional - sage.rings.number_field + sage: p._is_zero(0) # optional - sage.rings.number_field True - sage: p._is_zero(1/100000) + sage: p._is_zero(1/100000) # optional - sage.rings.number_field False """ return x == 0 @@ -455,10 +455,10 @@ def _is_nonneg(self, x): EXAMPLES:: - sage: p = Polyhedron([(sqrt(3),sqrt(2))], base_ring=AA) - sage: p._is_nonneg(1) + sage: p = Polyhedron([(sqrt(3),sqrt(2))], base_ring=AA) # optional - sage.rings.number_field + sage: p._is_nonneg(1) # optional - sage.rings.number_field True - sage: p._is_nonneg(-1/100000) + sage: p._is_nonneg(-1/100000) # optional - sage.rings.number_field False """ return x >= 0 @@ -477,10 +477,10 @@ def _is_positive(self, x): EXAMPLES:: - sage: p = Polyhedron([(sqrt(3),sqrt(2))], base_ring=AA) - sage: p._is_positive(1) + sage: p = Polyhedron([(sqrt(3),sqrt(2))], base_ring=AA) # optional - sage.rings.number_field + sage: p._is_positive(1) # optional - sage.rings.number_field True - sage: p._is_positive(0) + sage: p._is_positive(0) # optional - sage.rings.number_field False """ return x > 0 @@ -595,14 +595,14 @@ def _init_from_Hrepresentation(self, ieqs, eqns, minimize=True, verbose=False): Check that :trac:`30248` is fixed, that maps as input works:: - sage: q = Polyhedron(backend='normaliz', base_ring=AA, # optional - pynormaliz + sage: q = Polyhedron(backend='normaliz', base_ring=AA, # optional - pynormaliz # optional - sage.rings.number_field ....: rays=[(0, 0, 1), (0, 1, -1), (1, 0, -1)]) sage: make_new_Hrep = lambda h: tuple(x if i == 0 else -1*x for i, x in enumerate(h._vector)) - sage: new_inequalities = map(make_new_Hrep, q.inequality_generator()) # optional - pynormaliz - sage: new_equations = map(make_new_Hrep, q.equation_generator()) # optional - pynormaliz - sage: parent = q.parent() # optional - pynormaliz - sage: new_q = parent.element_class(parent,None,[new_inequalities,new_equations]) # optional - pynormaliz - sage: new_q # optional - pynormaliz + sage: new_inequalities = map(make_new_Hrep, q.inequality_generator()) # optional - pynormaliz # optional - sage.rings.number_field + sage: new_equations = map(make_new_Hrep, q.equation_generator()) # optional - pynormaliz # optional - sage.rings.number_field + sage: parent = q.parent() # optional - pynormaliz # optional - sage.rings.number_field + sage: new_q = parent.element_class(parent,None,[new_inequalities,new_equations]) # optional - pynormaliz # optional - sage.rings.number_field + sage: new_q # optional - pynormaliz # optional - sage.rings.number_field A 3-dimensional polyhedron in AA^3 defined as the convex hull of 1 vertex and 3 rays """ @@ -928,15 +928,15 @@ def _compute_nmz_data_lists_and_field(self, data_lists, convert_QQ, convert_NF): sage: p._compute_nmz_data_lists_and_field([[[AA(1)]], [[1/2]]], # optional - pynormaliz ....: convert_QQ, convert_NF) (([[1000]], [[500]]), Rational Field) - sage: p._compute_nmz_data_lists_and_field([[[AA(sqrt(2))]], [[1/2]]], # optional - pynormaliz + sage: p._compute_nmz_data_lists_and_field([[[AA(sqrt(2))]], [[1/2]]], # optional - pynormaliz # optional - sage.rings.number_field ....: convert_QQ, convert_NF) ([[[a]], [[1/2]]], Number Field in a with defining polynomial y^2 - 2 with a = 1.414213562373095?) TESTS:: - sage: K. = QuadraticField(-5) - sage: p = Polyhedron(vertices=[(a,1/2),(2,0),(4,5/6)], # indirect doctest # optional - pynormaliz + sage: K. = QuadraticField(-5) # optional - sage.rings.number_field + sage: p = Polyhedron(vertices=[(a,1/2),(2,0),(4,5/6)], # indirect doctest # optional - pynormaliz # optional - sage.rings.number_field ....: base_ring=K, backend='normaliz') Traceback (most recent call last): ... @@ -944,10 +944,10 @@ def _compute_nmz_data_lists_and_field(self, data_lists, convert_QQ, convert_NF): Checks that :trac:`30248` is fixed:: - sage: q = Polyhedron(backend='normaliz', base_ring=AA, # indirect doctest # optional - pynormaliz + sage: q = Polyhedron(backend='normaliz', base_ring=AA, # indirect doctest # optional - pynormaliz # optional - sage.rings.number_field ....: rays=[(0, 0, 1), (0, 1, -1), (1, 0, -1)]); q A 3-dimensional polyhedron in AA^3 defined as the convex hull of 1 vertex and 3 rays - sage: -q # optional - pynormaliz + sage: -q # optional - pynormaliz # optional - sage.rings.number_field A 3-dimensional polyhedron in AA^3 defined as the convex hull of 1 vertex and 3 rays """ from sage.categories.number_fields import NumberFields @@ -1078,7 +1078,7 @@ def _number_field_triple(normaliz_field): sage: from sage.geometry.polyhedron.backend_normaliz import Polyhedron_normaliz as Pn sage: Pn._number_field_triple(QQ) is None True - sage: Pn._number_field_triple(QuadraticField(5)) + sage: Pn._number_field_triple(QuadraticField(5)) # optional - sage.rings.number_field ['a^2 - 5', 'a', '[2.236067977499789 +/- 8.06e-16]'] """ from sage.rings.real_arb import RealBallField @@ -1327,10 +1327,10 @@ def __setstate__(self, state): sage: P2 == P # optional - pynormaliz True - sage: P = polytopes.dodecahedron(backend='normaliz') # optional - pynormaliz - sage: P1 = loads(dumps(P)) # optional - pynormaliz - sage: P2 = Polyhedron_normaliz(P1.parent(), None, None, P1._normaliz_cone, normaliz_field=P1._normaliz_field) # optional - pynormaliz - sage: P == P2 # optional - pynormaliz + sage: P = polytopes.dodecahedron(backend='normaliz') # optional - pynormaliz # optional - sage.rings.number_field + sage: P1 = loads(dumps(P)) # optional - pynormaliz # optional - sage.rings.number_field + sage: P2 = Polyhedron_normaliz(P1.parent(), None, None, P1._normaliz_cone, normaliz_field=P1._normaliz_field) # optional - pynormaliz # optional - sage.rings.number_field + sage: P == P2 # optional - pynormaliz # optional - sage.rings.number_field True Test that :trac:`31820` is fixed:: @@ -1496,8 +1496,8 @@ def _volume_normaliz(self, measure='euclidean'): Check that :trac:`28872` is fixed:: - sage: P = polytopes.dodecahedron(backend='normaliz') # optional - pynormaliz - sage: P.volume(measure='induced_lattice') # optional - pynormaliz + sage: P = polytopes.dodecahedron(backend='normaliz') # optional - pynormaliz # optional - sage.rings.number_field + sage: P.volume(measure='induced_lattice') # optional - pynormaliz # optional - sage.rings.number_field -1056*sqrt5 + 2400 Some sanity checks that the ambient volume works correctly:: From a47c25bcc0e630feebb5680d694cfd21dc8a68ac Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 5 Oct 2021 21:54:10 -0700 Subject: [PATCH 299/359] src/sage/geometry/polyhedron/constructor.py: Mark doctests # optional - sage.rings.number_field --- src/sage/geometry/polyhedron/constructor.py | 39 +++++++++++---------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/src/sage/geometry/polyhedron/constructor.py b/src/sage/geometry/polyhedron/constructor.py index 7f68ca41ce0..e97a72a4aa3 100644 --- a/src/sage/geometry/polyhedron/constructor.py +++ b/src/sage/geometry/polyhedron/constructor.py @@ -177,8 +177,8 @@ exact way to work with roots in Sage is the :mod:`Algebraic Real Field ` :: - sage: triangle = Polyhedron([(0,0), (1,0), (1/2, sqrt(3)/2)], base_ring=AA) - sage: triangle.Hrepresentation() + sage: triangle = Polyhedron([(0,0), (1,0), (1/2, sqrt(3)/2)], base_ring=AA) # optional - sage.rings.number_field + sage: triangle.Hrepresentation() # optional - sage.rings.number_field (An inequality (-1, -0.5773502691896258?) x + 1 >= 0, An inequality (1, -0.5773502691896258?) x + 0 >= 0, An inequality (0, 1.154700538379252?) x + 0 >= 0) @@ -187,20 +187,20 @@ symbolic ring element and, therefore, the polyhedron defined over the symbolic ring. This is currently not supported as SR is not exact:: - sage: Polyhedron([(0,0), (1,0), (1/2, sqrt(3)/2)]) + sage: Polyhedron([(0,0), (1,0), (1/2, sqrt(3)/2)]) # optional - sage.symbolic Traceback (most recent call last): ... ValueError: no default backend for computations with Symbolic Ring - sage: SR.is_exact() + sage: SR.is_exact() # optional - sage.symbolic False Even faster than all algebraic real numbers (the field ``AA``) is to take the smallest extension field. For the equilateral triangle, that would be:: - sage: K. = NumberField(x^2 - 3, embedding=AA(3)**(1/2)) - sage: Polyhedron([(0,0), (1,0), (1/2, sqrt3/2)]) + sage: K. = NumberField(x^2 - 3, embedding=AA(3)**(1/2)) # optional - sage.rings.number_field + sage: Polyhedron([(0,0), (1,0), (1/2, sqrt3/2)]) # optional - sage.rings.number_field A 2-dimensional polyhedron in (Number Field in sqrt3 with defining polynomial x^2 - 3 with sqrt3 = 1.732050807568878?)^2 defined as the convex hull of 3 vertices .. WARNING:: @@ -441,24 +441,25 @@ def Polyhedron(vertices=None, rays=None, lines=None, by the cyclic shifts of `(0, \pm 1, \pm (1+\sqrt(5))/2)`, cf. :wikipedia:`Regular_icosahedron`. It needs a number field:: - sage: R0. = QQ[] - sage: R1. = NumberField(r0^2-5, embedding=AA(5)**(1/2)) - sage: gold = (1+r1)/2 - sage: v = [[0, 1, gold], [0, 1, -gold], [0, -1, gold], [0, -1, -gold]] - sage: pp = Permutation((1, 2, 3)) - sage: icosah = Polyhedron([(pp^2).action(w) for w in v] - ....: + [pp.action(w) for w in v] + v, base_ring=R1) - sage: len(icosah.faces(2)) + sage: R0. = QQ[] # optional - sage.rings.number_field + sage: R1. = NumberField(r0^2-5, embedding=AA(5)**(1/2)) # optional - sage.rings.number_field + sage: gold = (1+r1)/2 # optional - sage.rings.number_field + sage: v = [[0, 1, gold], [0, 1, -gold], [0, -1, gold], [0, -1, -gold]] # optional - sage.rings.number_field + sage: pp = Permutation((1, 2, 3)) # optional - sage.combinat # optional - sage.rings.number_field + sage: icosah = Polyhedron( # optional - sage.combinat # optional - sage.rings.number_field + ....: [(pp^2).action(w) for w in v] + [pp.action(w) for w in v] + v, + ....: base_ring=R1) + sage: len(icosah.faces(2)) # optional - sage.combinat # optional - sage.rings.number_field 20 When the input contains elements of a Number Field, they require an embedding:: - sage: K = NumberField(x^2-2,'s') - sage: s = K.0 - sage: L = NumberField(x^3-2,'t') - sage: t = L.0 - sage: P = Polyhedron(vertices = [[0,s],[t,0]]) + sage: K = NumberField(x^2-2,'s') # optional - sage.rings.number_field + sage: s = K.0 # optional - sage.rings.number_field + sage: L = NumberField(x^3-2,'t') # optional - sage.rings.number_field + sage: t = L.0 # optional - sage.rings.number_field + sage: P = Polyhedron(vertices = [[0,s],[t,0]]) # optional - sage.rings.number_field Traceback (most recent call last): ... ValueError: invalid base ring From 9ab8040da8700b460adc2fe2f59b344ba23c114a Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 5 Oct 2021 22:52:10 -0700 Subject: [PATCH 300/359] src/sage/geometry/polyhedron/backend_field.py: Mark doctests # optional - sage.rings.number_field --- src/sage/geometry/polyhedron/backend_field.py | 82 +++++++++---------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/src/sage/geometry/polyhedron/backend_field.py b/src/sage/geometry/polyhedron/backend_field.py index d0f50782016..17cba0ed2ef 100644 --- a/src/sage/geometry/polyhedron/backend_field.py +++ b/src/sage/geometry/polyhedron/backend_field.py @@ -9,13 +9,13 @@ sage: p0 = (0, 0) sage: p1 = (1, 0) - sage: p2 = (1/2, AA(3).sqrt()/2) - sage: equilateral_triangle = Polyhedron([p0, p1, p2]) - sage: equilateral_triangle.vertices() + sage: p2 = (1/2, AA(3).sqrt()/2) # optional - sage.rings.number_field + sage: equilateral_triangle = Polyhedron([p0, p1, p2]) # optional - sage.rings.number_field + sage: equilateral_triangle.vertices() # optional - sage.rings.number_field (A vertex at (0, 0), A vertex at (1, 0), A vertex at (0.500000000000000?, 0.866025403784439?)) - sage: equilateral_triangle.inequalities() + sage: equilateral_triangle.inequalities() # optional - sage.rings.number_field (An inequality (-1, -0.5773502691896258?) x + 1 >= 0, An inequality (1, -0.5773502691896258?) x + 0 >= 0, An inequality (0, 1.154700538379252?) x + 0 >= 0) @@ -46,22 +46,22 @@ class Polyhedron_field(Polyhedron_base): EXAMPLES:: - sage: p = Polyhedron(vertices=[(0,0),(AA(2).sqrt(),0),(0,AA(3).sqrt())], + sage: p = Polyhedron(vertices=[(0,0),(AA(2).sqrt(),0),(0,AA(3).sqrt())], # optional - sage.rings.number_field ....: rays=[(1,1)], lines=[], backend='field', base_ring=AA) - sage: TestSuite(p).run() + sage: TestSuite(p).run() # optional - sage.rings.number_field TESTS:: - sage: K. = QuadraticField(3) - sage: p = Polyhedron([(0,0), (1,0), (1/2, sqrt3/2)]) - sage: TestSuite(p).run() + sage: K. = QuadraticField(3) # optional - sage.rings.number_field + sage: p = Polyhedron([(0,0), (1,0), (1/2, sqrt3/2)]) # optional - sage.rings.number_field + sage: TestSuite(p).run() # optional - sage.rings.number_field Check that :trac:`19013` is fixed:: - sage: K. = NumberField(x^2-x-1, embedding=1.618) - sage: P1 = Polyhedron([[0,1],[1,1],[1,-phi+1]]) - sage: P2 = Polyhedron(ieqs=[[-1,-phi,0]]) - sage: P1.intersection(P2) + sage: K. = NumberField(x^2-x-1, embedding=1.618) # optional - sage.rings.number_field + sage: P1 = Polyhedron([[0,1],[1,1],[1,-phi+1]]) # optional - sage.rings.number_field + sage: P2 = Polyhedron(ieqs=[[-1,-phi,0]]) # optional - sage.rings.number_field + sage: P1.intersection(P2) # optional - sage.rings.number_field The empty polyhedron in (Number Field in phi with defining polynomial x^2 - x - 1 with phi = 1.618033988749895?)^2 Check that :trac:`28654` is fixed:: @@ -83,10 +83,10 @@ def _is_zero(self, x): EXAMPLES:: - sage: p = Polyhedron([(sqrt(3),sqrt(2))], base_ring=AA) - sage: p._is_zero(0) + sage: p = Polyhedron([(sqrt(3),sqrt(2))], base_ring=AA) # optional - sage.rings.number_field + sage: p._is_zero(0) # optional - sage.rings.number_field True - sage: p._is_zero(1/100000) + sage: p._is_zero(1/100000) # optional - sage.rings.number_field False """ return x == 0 @@ -105,10 +105,10 @@ def _is_nonneg(self, x): EXAMPLES:: - sage: p = Polyhedron([(sqrt(3),sqrt(2))], base_ring=AA) - sage: p._is_nonneg(1) + sage: p = Polyhedron([(sqrt(3),sqrt(2))], base_ring=AA) # optional - sage.rings.number_field + sage: p._is_nonneg(1) # optional - sage.rings.number_field True - sage: p._is_nonneg(-1/100000) + sage: p._is_nonneg(-1/100000) # optional - sage.rings.number_field False """ return x >= 0 @@ -127,10 +127,10 @@ def _is_positive(self, x): EXAMPLES:: - sage: p = Polyhedron([(sqrt(3),sqrt(2))], base_ring=AA) - sage: p._is_positive(1) + sage: p = Polyhedron([(sqrt(3),sqrt(2))], base_ring=AA) # optional - sage.rings.number_field + sage: p._is_positive(1) # optional - sage.rings.number_field True - sage: p._is_positive(0) + sage: p._is_positive(0) # optional - sage.rings.number_field False """ return x > 0 @@ -150,12 +150,12 @@ def _init_from_Vrepresentation_and_Hrepresentation(self, Vrep, Hrep): sage: from sage.geometry.polyhedron.parent import Polyhedra_field sage: from sage.geometry.polyhedron.backend_field import Polyhedron_field - sage: parent = Polyhedra_field(AA, 1, 'field') + sage: parent = Polyhedra_field(AA, 1, 'field') # optional - sage.rings.number_field sage: Vrep = [[[0], [1]], [], []] sage: Hrep = [[[0, 1], [1, -1]], []] - sage: p = Polyhedron_field(parent, Vrep, Hrep, - ....: Vrep_minimal=True, Hrep_minimal=True) # indirect doctest - sage: p + sage: p = Polyhedron_field(parent, Vrep, Hrep, # indirect doctest # optional - sage.rings.number_field + ....: Vrep_minimal=True, Hrep_minimal=True) + sage: p # optional - sage.rings.number_field A 1-dimensional polyhedron in AA^1 defined as the convex hull of 2 vertices """ self._init_Vrepresentation(*Vrep) @@ -234,12 +234,12 @@ def _init_Vrepresentation(self, vertices, rays, lines): sage: from sage.geometry.polyhedron.parent import Polyhedra_field sage: from sage.geometry.polyhedron.backend_field import Polyhedron_field - sage: parent = Polyhedra_field(AA, 1, 'field') + sage: parent = Polyhedra_field(AA, 1, 'field') # optional - sage.rings.number_field sage: Vrep = [[[0], [1]], [], []] sage: Hrep = [[[0, 1], [1, -1]], []] - sage: p = Polyhedron_field(parent, Vrep, Hrep, # indirect doctest + sage: p = Polyhedron_field(parent, Vrep, Hrep, # indirect doctest # optional - sage.rings.number_field ....: Vrep_minimal=True, Hrep_minimal=True) - sage: p.vertices_list() + sage: p.vertices_list() # optional - sage.rings.number_field [[0], [1]] """ self._Vrepresentation = [] @@ -258,13 +258,13 @@ def _init_Vrepresentation_backend(self, Vrep): EXAMPLES:: - sage: p = Polyhedron(vertices=[(0,1/sqrt(2)),(sqrt(2),0),(4,sqrt(5)/6)], + sage: p = Polyhedron(vertices=[(0,1/sqrt(2)),(sqrt(2),0),(4,sqrt(5)/6)], # optional - sage.rings.number_field ....: base_ring=AA, backend='field') # indirect doctest - sage: p.Hrepresentation() + sage: p.Hrepresentation() # optional - sage.rings.number_field (An inequality (-0.1582178750233332?, 1.097777812326429?) x + 0.2237538646678492? >= 0, An inequality (-0.1419794359520263?, -1.698172434277148?) x + 1.200789243901438? >= 0, An inequality (0.3001973109753594?, 0.600394621950719?) x - 0.4245431085692869? >= 0) - sage: p.Vrepresentation() + sage: p.Vrepresentation() # optional - sage.rings.number_field (A vertex at (0.?e-15, 0.707106781186548?), A vertex at (1.414213562373095?, 0), A vertex at (4.000000000000000?, 0.372677996249965?)) @@ -279,10 +279,10 @@ def _init_Hrepresentation(self, inequalities, equations): sage: from sage.geometry.polyhedron.parent import Polyhedra_field sage: from sage.geometry.polyhedron.backend_field import Polyhedron_field - sage: parent = Polyhedra_field(AA, 1, 'field') + sage: parent = Polyhedra_field(AA, 1, 'field') # optional - sage.rings.number_field sage: Vrep = [[[0], [1]], [], []] sage: Hrep = [[[0, 1], [1, -1]], []] - sage: p = Polyhedron_field(parent, Vrep, Hrep, # indirect doctest + sage: p = Polyhedron_field(parent, Vrep, Hrep, # indirect doctest # optional - sage.rings.number_field ....: Vrep_minimal=True, Hrep_minimal=True) sage: p.inequalities_list() [[0, 1], [1, -1]] @@ -301,13 +301,13 @@ def _init_Hrepresentation_backend(self, Hrep): EXAMPLES:: - sage: p = Polyhedron(vertices=[(0,1/sqrt(2)),(sqrt(2),0),(4,sqrt(5)/6)], + sage: p = Polyhedron(vertices=[(0,1/sqrt(2)),(sqrt(2),0),(4,sqrt(5)/6)], # optional - sage.rings.number_field ....: base_ring=AA, backend='field') # indirect doctest - sage: p.Hrepresentation() + sage: p.Hrepresentation() # optional - sage.rings.number_field (An inequality (-0.1582178750233332?, 1.097777812326429?) x + 0.2237538646678492? >= 0, An inequality (-0.1419794359520263?, -1.698172434277148?) x + 1.200789243901438? >= 0, An inequality (0.3001973109753594?, 0.600394621950719?) x - 0.4245431085692869? >= 0) - sage: p.Vrepresentation() + sage: p.Vrepresentation() # optional - sage.rings.number_field (A vertex at (0.?e-15, 0.707106781186548?), A vertex at (1.414213562373095?, 0), A vertex at (4.000000000000000?, 0.372677996249965?)) @@ -320,13 +320,13 @@ def _init_empty_polyhedron(self): TESTS:: - sage: empty = Polyhedron(backend='field', base_ring=AA); empty + sage: empty = Polyhedron(backend='field', base_ring=AA); empty # optional - sage.rings.number_field The empty polyhedron in AA^0 - sage: empty.Vrepresentation() + sage: empty.Vrepresentation() # optional - sage.rings.number_field () - sage: empty.Hrepresentation() + sage: empty.Hrepresentation() # optional - sage.rings.number_field (An equation -1 == 0,) - sage: Polyhedron(vertices = [], backend='field') + sage: Polyhedron(vertices=[], backend='field') The empty polyhedron in QQ^0 sage: Polyhedron(backend='field')._init_empty_polyhedron() """ From ce90678dd360868bc85908681b230f6795b567ce Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 6 Oct 2021 12:58:06 -0700 Subject: [PATCH 301/359] src/sage/geometry/polyhedron/base_ZZ.py: Mark a doctest # optional - sage.rings.number_field --- src/sage/geometry/polyhedron/base_ZZ.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/geometry/polyhedron/base_ZZ.py b/src/sage/geometry/polyhedron/base_ZZ.py index aabb5806504..d8c1367f7c5 100644 --- a/src/sage/geometry/polyhedron/base_ZZ.py +++ b/src/sage/geometry/polyhedron/base_ZZ.py @@ -79,7 +79,7 @@ def is_lattice_polytope(self): sage: polytopes.cross_polytope(3).is_lattice_polytope() True - sage: polytopes.regular_polygon(5).is_lattice_polytope() + sage: polytopes.regular_polygon(5).is_lattice_polytope() # optional - sage.rings.number_field False TESTS: From 607598a3b82ad3e337b43a93d67cc425f07c8650 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 6 Oct 2021 14:06:26 -0700 Subject: [PATCH 302/359] src/sage/geometry/polyhedron/base.py: Mark more doctests # optional - sage.rings.number_field --- src/sage/geometry/polyhedron/base.py | 144 +++++++++++++-------------- 1 file changed, 72 insertions(+), 72 deletions(-) diff --git a/src/sage/geometry/polyhedron/base.py b/src/sage/geometry/polyhedron/base.py index 47063568802..4272c3b0d29 100644 --- a/src/sage/geometry/polyhedron/base.py +++ b/src/sage/geometry/polyhedron/base.py @@ -641,13 +641,13 @@ def change_ring(self, base_ring, backend=None): ... TypeError: cannot change the base ring to the Integer Ring - sage: P = polytopes.regular_polygon(3); P + sage: P = polytopes.regular_polygon(3); P # optional - sage.rings.number_field A 2-dimensional polyhedron in AA^2 defined as the convex hull of 3 vertices - sage: P.vertices() + sage: P.vertices() # optional - sage.rings.number_field (A vertex at (0.?e-16, 1.000000000000000?), A vertex at (0.866025403784439?, -0.500000000000000?), A vertex at (-0.866025403784439?, -0.500000000000000?)) - sage: P.change_ring(QQ) + sage: P.change_ring(QQ) # optional - sage.rings.number_field Traceback (most recent call last): ... TypeError: cannot change the base ring to the Rational Field @@ -660,11 +660,11 @@ def change_ring(self, base_ring, backend=None): base ring from an exact ring into ``RDF`` may cause a loss of data:: - sage: P = Polyhedron([[2/3,0],[6666666666666667/10^16,0]], base_ring=AA); P + sage: P = Polyhedron([[2/3,0],[6666666666666667/10^16,0]], base_ring=AA); P # optional - sage.rings.number_field A 1-dimensional polyhedron in AA^2 defined as the convex hull of 2 vertices - sage: Q = P.change_ring(RDF); Q + sage: Q = P.change_ring(RDF); Q # optional - sage.rings.number_field A 0-dimensional polyhedron in RDF^2 defined as the convex hull of 1 vertex - sage: P.n_vertices() == Q.n_vertices() + sage: P.n_vertices() == Q.n_vertices() # optional - sage.rings.number_field False """ @@ -3831,8 +3831,8 @@ def is_pyramid(self, certificate=False): True sage: P.is_pyramid(certificate=True) (True, A vertex at (1, 0, 0, 0)) - sage: egyptian_pyramid = polytopes.regular_polygon(4).pyramid() - sage: egyptian_pyramid.is_pyramid() + sage: egyptian_pyramid = polytopes.regular_polygon(4).pyramid() # optional - sage.rings.number_field + sage: egyptian_pyramid.is_pyramid() # optional - sage.rings.number_field True sage: Q = polytopes.octahedron() sage: Q.is_pyramid() @@ -5331,28 +5331,28 @@ def linear_transformation(self, linear_transf, new_base_ring=None): sage: b3_proj = proj_mat * b3; b3_proj A 3-dimensional polyhedron in ZZ^4 defined as the convex hull of 5 vertices - sage: square = polytopes.regular_polygon(4) - sage: square.vertices_list() + sage: square = polytopes.regular_polygon(4) # optional - sage.rings.number_field + sage: square.vertices_list() # optional - sage.rings.number_field [[0, -1], [1, 0], [-1, 0], [0, 1]] - sage: transf = matrix([[1,1],[0,1]]) - sage: sheared = transf * square - sage: sheared.vertices_list() + sage: transf = matrix([[1,1],[0,1]]) # optional - sage.rings.number_field + sage: sheared = transf * square # optional - sage.rings.number_field + sage: sheared.vertices_list() # optional - sage.rings.number_field [[-1, -1], [1, 0], [-1, 0], [1, 1]] - sage: sheared == square.linear_transformation(transf) + sage: sheared == square.linear_transformation(transf) # optional - sage.rings.number_field True Specifying the new base ring may avoid coercion failure:: - sage: K. = QuadraticField(2) - sage: L. = QuadraticField(3) - sage: P = polytopes.cube()*sqrt2 - sage: M = matrix([[sqrt3, 0, 0], [0, sqrt3, 0], [0, 0, 1]]) - sage: P.linear_transformation(M, new_base_ring=K.composite_fields(L)[0]) + sage: K. = QuadraticField(2) # optional - sage.rings.number_field + sage: L. = QuadraticField(3) # optional - sage.rings.number_field + sage: P = polytopes.cube()*sqrt2 # optional - sage.rings.number_field + sage: M = matrix([[sqrt3, 0, 0], [0, sqrt3, 0], [0, 0, 1]]) # optional - sage.rings.number_field + sage: P.linear_transformation(M, new_base_ring=K.composite_fields(L)[0]) # optional - sage.rings.number_field A 3-dimensional polyhedron in (Number Field in sqrt2sqrt3 with defining polynomial x^4 - 10*x^2 + 1 with sqrt2sqrt3 = 0.3178372451957823?)^3 defined as the convex hull of 8 vertices Linear transformation without specified new base ring fails in this case:: - sage: M*P + sage: M*P # optional - sage.rings.number_field Traceback (most recent call last): ... TypeError: unsupported operand parent(s) for *: 'Full MatrixSpace of 3 by 3 dense matrices over Number Field in sqrt3 with defining polynomial x^2 - 3 with sqrt3 = 1.732050807568878?' and 'Full MatrixSpace of 3 by 8 dense matrices over Number Field in sqrt2 with defining polynomial x^2 - 2 with sqrt2 = 1.414213562373095?' @@ -5372,7 +5372,7 @@ def linear_transformation(self, linear_transf, new_base_ring=None): A 3-dimensional polyhedron in RDF^4 defined as the convex hull of 5 vertices sage: (1/1 * proj_mat) * b3 A 3-dimensional polyhedron in QQ^4 defined as the convex hull of 5 vertices - sage: (AA(2).sqrt() * proj_mat) * b3 + sage: (AA(2).sqrt() * proj_mat) * b3 # optional - sage.rings.number_field A 3-dimensional polyhedron in AA^4 defined as the convex hull of 5 vertices Check that zero-matrices act correctly:: @@ -5963,15 +5963,15 @@ def stack(self, face, position=None): (1, 9, 16, 9, 1) sage: stacked_square_large = cube.stack(square_face,position=10) - sage: hexaprism = polytopes.regular_polygon(6).prism() - sage: hexaprism.f_vector() + sage: hexaprism = polytopes.regular_polygon(6).prism() # optional - sage.rings.number_field + sage: hexaprism.f_vector() # optional - sage.rings.number_field (1, 12, 18, 8, 1) - sage: square_face = hexaprism.faces(2)[2] - sage: stacked_hexaprism = hexaprism.stack(square_face) - sage: stacked_hexaprism.f_vector() + sage: square_face = hexaprism.faces(2)[2] # optional - sage.rings.number_field + sage: stacked_hexaprism = hexaprism.stack(square_face) # optional - sage.rings.number_field + sage: stacked_hexaprism.f_vector() # optional - sage.rings.number_field (1, 13, 22, 11, 1) - sage: hexaprism.stack(square_face,position=4) + sage: hexaprism.stack(square_face,position=4) # optional - sage.rings.number_field Traceback (most recent call last): ... ValueError: the chosen position is too large @@ -6318,7 +6318,7 @@ def _test_lawrence(self, tester=None, **options): Check that :trac:`28725` is fixed:: - sage: polytopes.regular_polygon(3)._test_lawrence() + sage: polytopes.regular_polygon(3)._test_lawrence() # optional - sage.rings.number_field Check that :trac:`30293` is fixed:: @@ -6445,8 +6445,8 @@ def barycentric_subdivision(self, subdivision_frac=None): sage: P.barycentric_subdivision() A 2-dimensional polyhedron in QQ^3 defined as the convex hull of 6 vertices - sage: P = polytopes.regular_polygon(4, base_ring=QQ) - sage: P.barycentric_subdivision() + sage: P = polytopes.regular_polygon(4, base_ring=QQ) # optional - sage.rings.number_field + sage: P.barycentric_subdivision() # optional - sage.rings.number_field A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 8 vertices @@ -6662,31 +6662,31 @@ def hasse_diagram(self): EXAMPLES:: - sage: P = polytopes.regular_polygon(4).pyramid() - sage: D = P.hasse_diagram(); D + sage: P = polytopes.regular_polygon(4).pyramid() # optional - sage.rings.number_field + sage: D = P.hasse_diagram(); D # optional - sage.rings.number_field Digraph on 20 vertices - sage: D.degree_polynomial() + sage: D.degree_polynomial() # optional - sage.rings.number_field x^5 + x^4*y + x*y^4 + y^5 + 4*x^3*y + 8*x^2*y^2 + 4*x*y^3 Faces of an mutable polyhedron are not hashable. Hence those are not suitable as vertices of the hasse diagram. Use the combinatorial polyhedron instead:: - sage: P = polytopes.regular_polygon(4).pyramid() - sage: parent = P.parent() - sage: parent = parent.change_ring(QQ, backend='ppl') - sage: Q = parent._element_constructor_(P, mutable=True) - sage: Q.hasse_diagram() + sage: P = polytopes.regular_polygon(4).pyramid() # optional - sage.rings.number_field + sage: parent = P.parent() # optional - sage.rings.number_field + sage: parent = parent.change_ring(QQ, backend='ppl') # optional - sage.rings.number_field + sage: Q = parent._element_constructor_(P, mutable=True) # optional - sage.rings.number_field + sage: Q.hasse_diagram() # optional - sage.rings.number_field Traceback (most recent call last): ... TypeError: mutable polyhedra are unhashable - sage: C = Q.combinatorial_polyhedron() - sage: D = C.hasse_diagram() - sage: set(D.vertices()) == set(range(20)) + sage: C = Q.combinatorial_polyhedron() # optional - sage.rings.number_field + sage: D = C.hasse_diagram() # optional - sage.rings.number_field + sage: set(D.vertices()) == set(range(20)) # optional - sage.rings.number_field True sage: def index_to_combinatorial_face(n): ....: return C.face_by_face_lattice_index(n) - sage: D.relabel(index_to_combinatorial_face, inplace=True) - sage: D.vertices() + sage: D.relabel(index_to_combinatorial_face, inplace=True) # optional - sage.rings.number_field + sage: D.vertices() # optional - sage.rings.number_field [A -1-dimensional face of a 3-dimensional combinatorial polyhedron, A 0-dimensional face of a 3-dimensional combinatorial polyhedron, A 0-dimensional face of a 3-dimensional combinatorial polyhedron, @@ -6707,7 +6707,7 @@ def hasse_diagram(self): A 2-dimensional face of a 3-dimensional combinatorial polyhedron, A 2-dimensional face of a 3-dimensional combinatorial polyhedron, A 3-dimensional face of a 3-dimensional combinatorial polyhedron] - sage: D.degree_polynomial() + sage: D.degree_polynomial() # optional - sage.rings.number_field x^5 + x^4*y + x*y^4 + y^5 + 4*x^3*y + 8*x^2*y^2 + 4*x*y^3 """ @@ -7914,7 +7914,7 @@ def _test_pyramid(self, tester=None, **options): TESTS: - sage: polytopes.regular_polygon(4)._test_pyramid() + sage: polytopes.regular_polygon(4)._test_pyramid() # optional - sage.rings.number_field """ if tester is None: tester = self._tester(**options) @@ -8178,10 +8178,10 @@ def one_point_suspension(self, vertex): sage: ops_cube.f_vector() (1, 9, 24, 24, 9, 1) - sage: pentagon = polytopes.regular_polygon(5) - sage: v = pentagon.vertices()[0] - sage: ops_pentagon = pentagon.one_point_suspension(v) - sage: ops_pentagon.f_vector() + sage: pentagon = polytopes.regular_polygon(5) # optional - sage.rings.number_field + sage: v = pentagon.vertices()[0] # optional - sage.rings.number_field + sage: ops_pentagon = pentagon.one_point_suspension(v) # optional - sage.rings.number_field + sage: ops_pentagon.f_vector() # optional - sage.rings.number_field (1, 6, 12, 8, 1) It works with a polyhedral face as well:: @@ -8228,10 +8228,10 @@ def face_split(self, face): EXAMPLES:: - sage: pentagon = polytopes.regular_polygon(5) - sage: f = pentagon.faces(1)[0] - sage: fsplit_pentagon = pentagon.face_split(f) - sage: fsplit_pentagon.f_vector() + sage: pentagon = polytopes.regular_polygon(5) # optional - sage.rings.number_field + sage: f = pentagon.faces(1)[0] # optional - sage.rings.number_field + sage: fsplit_pentagon = pentagon.face_split(f) # optional - sage.rings.number_field + sage: fsplit_pentagon.f_vector() # optional - sage.rings.number_field (1, 7, 14, 9, 1) TESTS: @@ -8610,13 +8610,13 @@ def volume(self, measure='ambient', engine='auto', **kwds): If the base ring is exact, the answer is exact:: - sage: P5 = polytopes.regular_polygon(5) - sage: P5.volume() + sage: P5 = polytopes.regular_polygon(5) # optional - sage.rings.number_field + sage: P5.volume() # optional - sage.rings.number_field 2.377641290737884? - sage: polytopes.icosahedron().volume() + sage: polytopes.icosahedron().volume() # optional - sage.rings.number_field 5/12*sqrt5 + 5/4 - sage: numerical_approx(_) # abs tol 1e9 + sage: numerical_approx(_) # abs tol 1e9 # optional - sage.rings.number_field 2.18169499062491 When considering lower-dimensional polytopes, we can ask for the @@ -8634,20 +8634,20 @@ def volume(self, measure='ambient', engine='auto', **kwds): sage: P.volume(measure='induced_rational') # optional -- latte_int 1 - sage: S = polytopes.regular_polygon(6); S + sage: S = polytopes.regular_polygon(6); S # optional - sage.rings.number_field A 2-dimensional polyhedron in AA^2 defined as the convex hull of 6 vertices - sage: edge = S.faces(1)[4].as_polyhedron() - sage: edge.vertices() + sage: edge = S.faces(1)[4].as_polyhedron() # optional - sage.rings.number_field + sage: edge.vertices() # optional - sage.rings.number_field (A vertex at (0.866025403784439?, 1/2), A vertex at (0, 1)) - sage: edge.volume() + sage: edge.volume() # optional - sage.rings.number_field 0 - sage: edge.volume(measure='induced') + sage: edge.volume(measure='induced') # optional - sage.rings.number_field 1 sage: P = Polyhedron(backend='normaliz',vertices=[[1,0,0],[0,0,1],[-1,1,1],[-1,2,0]]) # optional - pynormaliz sage: P.volume() # optional - pynormaliz 0 - sage: P.volume(measure='induced') # optional - pynormaliz + sage: P.volume(measure='induced') # optional - pynormaliz # optional - sage.rings.number_field 2.598076211353316? sage: P.volume(measure='induced',engine='normaliz') # optional - pynormaliz 2.598076211353316 @@ -8664,12 +8664,12 @@ def volume(self, measure='ambient', engine='auto', **kwds): sage: P.volume(measure='induced_lattice',engine='latte') # optional - latte_int 3 - sage: Dexact = polytopes.dodecahedron() - sage: v = Dexact.faces(2)[0].as_polyhedron().volume(measure='induced', engine='internal'); v + sage: Dexact = polytopes.dodecahedron() # optional - sage.rings.number_field + sage: v = Dexact.faces(2)[0].as_polyhedron().volume(measure='induced', engine='internal'); v # optional - sage.rings.number_field 1.53406271079097? - sage: v = Dexact.faces(2)[4].as_polyhedron().volume(measure='induced', engine='internal'); v + sage: v = Dexact.faces(2)[4].as_polyhedron().volume(measure='induced', engine='internal'); v # optional - sage.rings.number_field 1.53406271079097? - sage: RDF(v) # abs tol 1e-9 + sage: RDF(v) # abs tol 1e-9 # optional - sage.rings.number_field 1.53406271079044 sage: Dinexact = polytopes.dodecahedron(exact=False) @@ -8680,13 +8680,13 @@ def volume(self, measure='ambient', engine='auto', **kwds): True sage: I = Polyhedron([[-3, 0], [0, 9]]) - sage: I.volume(measure='induced') + sage: I.volume(measure='induced') # optional - sage.rings.number_field 9.48683298050514? sage: I.volume(measure='induced_rational') # optional -- latte_int 3 sage: T = Polyhedron([[3, 0, 0], [0, 4, 0], [0, 0, 5]]) - sage: T.volume(measure='induced') + sage: T.volume(measure='induced') # optional - sage.rings.number_field 13.86542462386205? sage: T.volume(measure='induced_rational') # optional -- latte_int 1/2 @@ -9505,7 +9505,7 @@ def is_lattice_polytope(self): sage: polytopes.cross_polytope(3).is_lattice_polytope() True - sage: polytopes.regular_polygon(5).is_lattice_polytope() + sage: polytopes.regular_polygon(5).is_lattice_polytope() # optional - sage.rings.number_field False """ if not self.is_compact(): @@ -10623,7 +10623,7 @@ def is_combinatorially_isomorphic(self, other, algorithm='bipartite_graph'): All the faces of the 3-dimensional permutahedron are either combinatorially isomorphic to a square or a hexagon:: - sage: H = polytopes.regular_polygon(6) + sage: H = polytopes.regular_polygon(6) # optional - sage.rings.number_field sage: S = polytopes.hypercube(2) sage: P = polytopes.permutahedron(4) sage: all(F.as_polyhedron().is_combinatorially_isomorphic(S) or F.as_polyhedron().is_combinatorially_isomorphic(H) for F in P.faces(2)) @@ -10643,7 +10643,7 @@ def is_combinatorially_isomorphic(self, other, algorithm='bipartite_graph'): ....: return C.intersection(H) sage: [simplex_intersection(k).is_combinatorially_isomorphic(cube_intersection(k)) for k in range(2,5)] [True, True, True] - sage: simplex_intersection(2).is_combinatorially_isomorphic(polytopes.regular_polygon(6)) + sage: simplex_intersection(2).is_combinatorially_isomorphic(polytopes.regular_polygon(6)) # optional - sage.rings.number_field True sage: simplex_intersection(3).is_combinatorially_isomorphic(polytopes.octahedron()) True From b84efa55878dfc84a75887a7c4669a489491d838 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 6 Oct 2021 23:15:39 -0700 Subject: [PATCH 303/359] src/sage/geometry/polyhedron/base.py: Mark more doctests # optional - sage.rings.number_field --- src/sage/geometry/polyhedron/base.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sage/geometry/polyhedron/base.py b/src/sage/geometry/polyhedron/base.py index 4272c3b0d29..49b3b645c3d 100644 --- a/src/sage/geometry/polyhedron/base.py +++ b/src/sage/geometry/polyhedron/base.py @@ -3635,8 +3635,8 @@ def is_compact(self): EXAMPLES:: - sage: p = polytopes.icosahedron() - sage: p.is_compact() + sage: p = polytopes.icosahedron() # optional - sage.rings.number_field + sage: p.is_compact() # optional - sage.rings.number_field True sage: p = Polyhedron(ieqs = [[0,1,0,0],[0,0,1,0],[0,0,0,1],[1,-1,0,0]]) sage: p.is_compact() @@ -8928,8 +8928,8 @@ def integrate(self, function, measure='ambient', **kwds): Testing a polytope with non-rational vertices:: - sage: P = polytopes.icosahedron() - sage: P.integrate(x^2*y^2*z^2) # optional - latte_int + sage: P = polytopes.icosahedron() # optional - sage.rings.number_field + sage: P.integrate(x^2*y^2*z^2) # optional - latte_int # optional - sage.rings.number_field Traceback (most recent call last): ... TypeError: the base ring must be ZZ, QQ, or RDF From add89fa38eb90d798ea24b797641d4242e57699d Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 4 Oct 2021 15:56:21 -0700 Subject: [PATCH 304/359] src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx: Mark doctests using combinatorial polytopes # optional - sage.combinat or # optional - sage.rings.number_field --- .../combinatorial_polyhedron/base.pyx | 132 +++++++++--------- 1 file changed, 67 insertions(+), 65 deletions(-) diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx b/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx index dd1a2ba54d7..612a4da19b9 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx @@ -600,12 +600,13 @@ cdef class CombinatorialPolyhedron(SageObject): TESTS:: - sage: P = polytopes.permutahedron(4) - sage: C = CombinatorialPolyhedron(P) - sage: C1 = loads(C.dumps()) - sage: it = C.face_iter() - sage: it1 = C1.face_iter() - sage: tup = tuple((face.ambient_Vrepresentation(), face.ambient_Hrepresentation()) for face in it) + sage: P = polytopes.permutahedron(4) # optional - sage.combinat + sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat + sage: C1 = loads(C.dumps()) # optional - sage.combinat + sage: it = C.face_iter() # optional - sage.combinat + sage: it1 = C1.face_iter() # optional - sage.combinat + sage: tup = tuple((face.ambient_Vrepresentation(), # optional - sage.combinat + ....: face.ambient_Hrepresentation()) for face in it) sage: tup1 = tuple((face.ambient_Vrepresentation(), face.ambient_Hrepresentation()) for face in it1) sage: tup == tup1 True @@ -705,9 +706,9 @@ cdef class CombinatorialPolyhedron(SageObject): EXAMPLES:: - sage: P = polytopes.permutahedron(3) - sage: C = CombinatorialPolyhedron(P) - sage: C.Hrepresentation() + sage: P = polytopes.permutahedron(3) # optional - sage.combinat + sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat + sage: C.Hrepresentation() # optional - sage.combinat (An inequality (1, 1, 0) x - 3 >= 0, An inequality (-1, -1, 0) x + 5 >= 0, An inequality (0, 1, 0) x - 1 >= 0, @@ -1060,10 +1061,10 @@ cdef class CombinatorialPolyhedron(SageObject): :: - sage: P = polytopes.permutahedron(5, backend='field') - sage: C = P.combinatorial_polyhedron() - sage: C.incidence_matrix.clear_cache() - sage: C.incidence_matrix() == P.incidence_matrix() + sage: P = polytopes.permutahedron(5, backend='field') # optional - sage.combinat + sage: C = P.combinatorial_polyhedron() # optional - sage.combinat + sage: C.incidence_matrix.clear_cache() # optional - sage.combinat + sage: C.incidence_matrix() == P.incidence_matrix() # optional - sage.combinat True The incidence matrix is consistent with @@ -1294,11 +1295,11 @@ cdef class CombinatorialPolyhedron(SageObject): EXAMPLES:: - sage: P = polytopes.permutahedron(2) - sage: C = CombinatorialPolyhedron(P) - sage: C.ridges() + sage: P = polytopes.permutahedron(2) # optional - sage.combinat + sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat + sage: C.ridges() # optional - sage.combinat ((An inequality (1, 0) x - 1 >= 0, An inequality (-1, 0) x + 2 >= 0),) - sage: C.ridges(add_equations=True) + sage: C.ridges(add_equations=True) # optional - sage.combinat (((An inequality (1, 0) x - 1 >= 0, An equation (1, 1) x - 3 == 0), (An inequality (-1, 0) x + 2 >= 0, An equation (1, 1) x - 3 == 0)),) @@ -1608,9 +1609,9 @@ cdef class CombinatorialPolyhedron(SageObject): EXAMPLES:: - sage: P = polytopes.permutahedron(5) - sage: C = CombinatorialPolyhedron(P) - sage: C.f_vector() + sage: P = polytopes.permutahedron(5) # optional - sage.combinat + sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat + sage: C.f_vector() # optional - sage.combinat (1, 120, 240, 150, 30, 1) sage: P = polytopes.cyclic_polytope(6,10) @@ -1620,9 +1621,9 @@ cdef class CombinatorialPolyhedron(SageObject): Using two threads:: - sage: P = polytopes.permutahedron(5) - sage: C = CombinatorialPolyhedron(P) - sage: C.f_vector(num_threads=2) + sage: P = polytopes.permutahedron(5) # optional - sage.combinat + sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat + sage: C.f_vector(num_threads=2) # optional - sage.combinat (1, 120, 240, 150, 30, 1) TESTS:: @@ -2320,15 +2321,15 @@ cdef class CombinatorialPolyhedron(SageObject): EXAMPLES:: - sage: P = polytopes.permutahedron(4) - sage: C = CombinatorialPolyhedron(P) - sage: C.join_of_Vrep(0,1) + sage: P = polytopes.permutahedron(4) # optional - sage.combinat + sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat + sage: C.join_of_Vrep(0,1) # optional - sage.combinat A 1-dimensional face of a 3-dimensional combinatorial polyhedron - sage: C.join_of_Vrep(0,11).ambient_V_indices() + sage: C.join_of_Vrep(0,11).ambient_V_indices() # optional - sage.combinat (0, 1, 10, 11, 12, 13) - sage: C.join_of_Vrep(8).ambient_V_indices() + sage: C.join_of_Vrep(8).ambient_V_indices() # optional - sage.combinat (8,) - sage: C.join_of_Vrep().ambient_V_indices() + sage: C.join_of_Vrep().ambient_V_indices() # optional - sage.combinat () """ return self.face_iter().join_of_Vrep(*indices) @@ -2343,19 +2344,19 @@ cdef class CombinatorialPolyhedron(SageObject): EXAMPLES:: - sage: P = polytopes.dodecahedron() - sage: C = CombinatorialPolyhedron(P) - sage: C.meet_of_Hrep(0) + sage: P = polytopes.dodecahedron() # optional - sage.rings.number_field + sage: C = CombinatorialPolyhedron(P) # optional - sage.rings.number_field + sage: C.meet_of_Hrep(0) # optional - sage.rings.number_field A 2-dimensional face of a 3-dimensional combinatorial polyhedron - sage: C.meet_of_Hrep(0).ambient_H_indices() + sage: C.meet_of_Hrep(0).ambient_H_indices() # optional - sage.rings.number_field (0,) - sage: C.meet_of_Hrep(0,1).ambient_H_indices() + sage: C.meet_of_Hrep(0,1).ambient_H_indices() # optional - sage.rings.number_field (0, 1) - sage: C.meet_of_Hrep(0,2).ambient_H_indices() + sage: C.meet_of_Hrep(0,2).ambient_H_indices() # optional - sage.rings.number_field (0, 2) - sage: C.meet_of_Hrep(0,2,3).ambient_H_indices() + sage: C.meet_of_Hrep(0,2,3).ambient_H_indices() # optional - sage.rings.number_field (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11) - sage: C.meet_of_Hrep().ambient_H_indices() + sage: C.meet_of_Hrep().ambient_H_indices() # optional - sage.rings.number_field () """ return self.face_iter().meet_of_Hrep(*indices) @@ -2382,38 +2383,38 @@ cdef class CombinatorialPolyhedron(SageObject): EXAMPLES:: - sage: P = polytopes.permutahedron(5) - sage: C = CombinatorialPolyhedron(P) - sage: it = C.face_iter(dimension=2) - sage: face = next(it); face + sage: P = polytopes.permutahedron(5) # optional - sage.rings.number_field + sage: C = CombinatorialPolyhedron(P) # optional - sage.rings.number_field + sage: it = C.face_iter(dimension=2) # optional - sage.rings.number_field + sage: face = next(it); face # optional - sage.rings.number_field A 2-dimensional face of a 4-dimensional combinatorial polyhedron - sage: face.ambient_Vrepresentation() + sage: face.ambient_Vrepresentation() # optional - sage.rings.number_field (A vertex at (1, 3, 2, 5, 4), A vertex at (2, 3, 1, 5, 4), A vertex at (3, 1, 2, 5, 4), A vertex at (3, 2, 1, 5, 4), A vertex at (2, 1, 3, 5, 4), A vertex at (1, 2, 3, 5, 4)) - sage: face = next(it); face + sage: face = next(it); face # optional - sage.rings.number_field A 2-dimensional face of a 4-dimensional combinatorial polyhedron - sage: face.ambient_Vrepresentation() + sage: face.ambient_Vrepresentation() # optional - sage.rings.number_field (A vertex at (2, 1, 4, 5, 3), A vertex at (3, 2, 4, 5, 1), A vertex at (3, 1, 4, 5, 2), A vertex at (1, 3, 4, 5, 2), A vertex at (1, 2, 4, 5, 3), A vertex at (2, 3, 4, 5, 1)) - sage: face.ambient_Hrepresentation() + sage: face.ambient_Hrepresentation() # optional - sage.rings.number_field (An inequality (0, 0, -1, -1, 0) x + 9 >= 0, An inequality (0, 0, 0, -1, 0) x + 5 >= 0, An equation (1, 1, 1, 1, 1) x - 15 == 0) - sage: face.ambient_H_indices() + sage: face.ambient_H_indices() # optional - sage.rings.number_field (25, 29, 30) - sage: face = next(it); face + sage: face = next(it); face # optional - sage.rings.number_field A 2-dimensional face of a 4-dimensional combinatorial polyhedron - sage: face.ambient_H_indices() + sage: face.ambient_H_indices() # optional - sage.rings.number_field (24, 29, 30) - sage: face.ambient_V_indices() + sage: face.ambient_V_indices() # optional - sage.rings.number_field (32, 89, 90, 94) sage: C = CombinatorialPolyhedron([[0,1,2],[0,1,3],[0,2,3],[1,2,3]]) @@ -2508,9 +2509,9 @@ cdef class CombinatorialPolyhedron(SageObject): sage: C.face_lattice().is_isomorphic(C1.face_lattice()) True - sage: P = polytopes.permutahedron(5) - sage: C = CombinatorialPolyhedron(P) - sage: C.face_lattice() + sage: P = polytopes.permutahedron(5) # optional - sage.combinat + sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat + sage: C.face_lattice() # optional - sage.combinat Finite lattice containing 542 elements TESTS:: @@ -2520,9 +2521,9 @@ cdef class CombinatorialPolyhedron(SageObject): sage: C.face_lattice().is_isomorphic(P.face_lattice()) True - sage: P = polytopes.permutahedron(4) - sage: C = CombinatorialPolyhedron(P) - sage: C.face_lattice().is_isomorphic(P.face_lattice()) + sage: P = polytopes.permutahedron(4) # optional - sage.combinat + sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat + sage: C.face_lattice().is_isomorphic(P.face_lattice()) # optional - sage.combinat True """ from sage.combinat.posets.lattices import FiniteLatticePoset @@ -2731,9 +2732,9 @@ cdef class CombinatorialPolyhedron(SageObject): sage: [face.ambient_V_indices() for face in chain] [(15,), (6, 15), (5, 6, 14, 15), (0, 5, 6, 7, 8, 9, 14, 15)] - sage: P = polytopes.permutahedron(4) - sage: C = P.combinatorial_polyhedron() - sage: chain = C.a_maximal_chain(); chain + sage: P = polytopes.permutahedron(4) # optional - sage.combinat + sage: C = P.combinatorial_polyhedron() # optional - sage.combinat + sage: chain = C.a_maximal_chain(); chain # optional - sage.combinat [A 0-dimensional face of a 3-dimensional combinatorial polyhedron, A 1-dimensional face of a 3-dimensional combinatorial polyhedron, A 2-dimensional face of a 3-dimensional combinatorial polyhedron] @@ -3493,14 +3494,15 @@ cdef class CombinatorialPolyhedron(SageObject): TESTS:: - sage: P = polytopes.permutahedron(4) - sage: C = CombinatorialPolyhedron(P) - sage: it = C.face_iter() - sage: tup = tuple((face.ambient_Vrepresentation(),face.ambient_Hrepresentation()) for face in it) - sage: rg = range(1,sum(C.f_vector()) - 1) - sage: tup2 = tuple((C.face_by_face_lattice_index(i).ambient_Vrepresentation(), + sage: P = polytopes.permutahedron(4) # optional - sage.combinat + sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat + sage: it = C.face_iter() # optional - sage.combinat + sage: tup = tuple((face.ambient_Vrepresentation(), # optional - sage.combinat + ....: face.ambient_Hrepresentation()) for face in it) + sage: rg = range(1,sum(C.f_vector()) - 1) # optional - sage.combinat + sage: tup2 = tuple((C.face_by_face_lattice_index(i).ambient_Vrepresentation(), # optional - sage.combinat ....: C.face_by_face_lattice_index(i).ambient_Hrepresentation()) for i in rg) - sage: sorted(tup) == sorted(tup2) + sage: sorted(tup) == sorted(tup2) # optional - sage.combinat True sage: P = polytopes.cyclic_polytope(4,10) From a307e92f14c5b6067e36b1e0ee85dacb579fd853 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 4 Oct 2021 15:56:45 -0700 Subject: [PATCH 305/359] src/sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pyx: Mark doctests # optional - sage.combinat --- .../polyhedron/combinatorial_polyhedron/conversions.pyx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pyx b/src/sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pyx index eb1666b99f6..35f8902ad0a 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pyx +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pyx @@ -33,9 +33,9 @@ Obtain the Vrepresentation of a polyhedron as facet-incidences stored in sage: from sage.geometry.polyhedron.combinatorial_polyhedron.conversions \ ....: import incidence_matrix_to_bit_rep_of_Vrep - sage: P = polytopes.associahedron(['A',4]) - sage: face_list = incidence_matrix_to_bit_rep_of_Vrep(P.incidence_matrix()) - sage: face_list.compute_dimension() + sage: P = polytopes.associahedron(['A',4]) # optional - sage.combinat + sage: face_list = incidence_matrix_to_bit_rep_of_Vrep(P.incidence_matrix()) # optional - sage.combinat + sage: face_list.compute_dimension() # optional - sage.combinat 4 Obtain the facets of a polyhedron as :class:`~sage.geometry.polyhedron.combinatorial_polyhedron.list_of_faces.ListOfFaces` from a facet list:: From b9ce371da02b21845c29eb8d3633c41406f5fe1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Fri, 8 Oct 2021 13:47:09 +0200 Subject: [PATCH 306/359] remove some deprecations in rings/polynomial/ --- .../multi_polynomial_ring_generic.py | 17 ------ .../rings/polynomial/ore_polynomial_ring.py | 52 +++++-------------- 2 files changed, 12 insertions(+), 57 deletions(-) delete mode 100644 src/sage/rings/polynomial/multi_polynomial_ring_generic.py diff --git a/src/sage/rings/polynomial/multi_polynomial_ring_generic.py b/src/sage/rings/polynomial/multi_polynomial_ring_generic.py deleted file mode 100644 index 06198d9d289..00000000000 --- a/src/sage/rings/polynomial/multi_polynomial_ring_generic.py +++ /dev/null @@ -1,17 +0,0 @@ -""" -TESTS:: - - sage: R. = QQbar[] - sage: from sage.rings.polynomial.multi_polynomial_ring_generic import MPolynomialRing_generic - doctest:...: DeprecationWarning: the module sage.rings.polynomial.multi_polynomial_ring_generic is deprecated, use sage.rings.polynomial.multi_polynomial_ring_base instead. - See https://trac.sagemath.org/25563 for details. - sage: isinstance(R, MPolynomialRing_generic) - True -""" - -from sage.misc.superseded import deprecation -deprecation(25563, "the module sage.rings.polynomial.multi_polynomial_ring_generic is deprecated, " - "use sage.rings.polynomial.multi_polynomial_ring_base instead.") - -from .multi_polynomial_ring_base import MPolynomialRing_base -MPolynomialRing_generic = MPolynomialRing_base diff --git a/src/sage/rings/polynomial/ore_polynomial_ring.py b/src/sage/rings/polynomial/ore_polynomial_ring.py index 69d218b9cc9..05ebcf6d1c7 100644 --- a/src/sage/rings/polynomial/ore_polynomial_ring.py +++ b/src/sage/rings/polynomial/ore_polynomial_ring.py @@ -21,7 +21,6 @@ # https://www.gnu.org/licenses/ # *************************************************************************** - from sage.misc.prandom import randint from sage.misc.cachefunc import cached_method from sage.rings.infinity import Infinity @@ -338,7 +337,7 @@ def __classcall_private__(cls, base_ring, twist=None, names=None, sparse=False): raise NotImplementedError("sparse Ore polynomial rings are not implemented") from sage.rings.polynomial import skew_polynomial_ring - constructors = [ ] + constructors = [] if derivation is None: if base_ring in _Fields: try: @@ -467,6 +466,7 @@ def _element_constructor_(self, a=None, check=True, construct=False, **kwds): return C(self, a, check=check, construct=construct) if isinstance(a, Element): P = a.parent() + def build(check): if a.is_zero(): return P.zero() @@ -574,7 +574,7 @@ def _coerce_map_from_(self, P): if P.variable_name() == self.variable_name(): return base_ring.has_coerce_map_from(P.base_ring()) - def _repr_(self): + def _repr_(self) -> str: r""" Return a string representation of ``self``. @@ -602,7 +602,7 @@ def _repr_(self): s = "Sparse " + s return s - def _latex_(self): + def _latex_(self) -> str: r""" Return a latex representation of ``self``. @@ -754,34 +754,6 @@ def twisting_morphism(self, n=1): else: raise ValueError("Unexpected error in iterating the twisting morphism: %s", e) - def twist_map(self, n=1): - r""" - Return the twisting endomorphism defining this Ore polynomial ring - iterated ``n`` times or ``None`` if this Ore polynomial ring is not - twisted by an endomorphism. - - This method is deprecated. Use :meth:`twisting_morphism` instead. - - INPUT: - - - ``n`` - an integer (default: 1) - - EXAMPLES:: - - sage: R. = QQ[] - sage: sigma = R.hom([t+1]) - sage: S. = R['x', sigma] - sage: S.twist_map() - ... - DeprecationWarning: The method twist_map is deprecated; use twisting_morphism (same semantic) instead - See https://trac.sagemath.org/29629 for details. - Ring endomorphism of Univariate Polynomial Ring in t over Rational Field - Defn: t |--> t + 1 - """ - from sage.misc.superseded import deprecation - deprecation(29629, "The method twist_map is deprecated; use twisting_morphism (same semantic) instead") - return self.twisting_morphism(n) - def twisting_derivation(self): r""" Return the twisting derivation defining this Ore polynomial ring @@ -846,7 +818,7 @@ def gen(self, n=0): """ if n != 0: raise IndexError("generator %s not defined" % n) - return self.Element(self, [0,1]) + return self.Element(self, [0, 1]) parameter = gen @@ -943,7 +915,7 @@ def ngens(self): """ return 1 - def random_element(self, degree=(-1,2), monic=False, *args, **kwds): + def random_element(self, degree=(-1, 2), monic=False, *args, **kwds): r""" Return a random Ore polynomial in this ring. @@ -1022,11 +994,11 @@ def random_element(self, degree=(-1,2), monic=False, *args, **kwds): degree = randint(*degree) if degree < 0: return self.zero() - coeffs = [ R.random_element(*args, **kwds) for _ in range(degree) ] + coeffs = [R.random_element(*args, **kwds) for _ in range(degree)] if monic: - return self(coeffs + [ R.one() ]) + return self(coeffs + [R.one()]) else: - return self(coeffs + [ R._random_nonzero_element() ]) + return self(coeffs + [R._random_nonzero_element()]) def random_irreducible(self, degree=2, monic=True, *args, **kwds): r""" @@ -1068,11 +1040,11 @@ def random_irreducible(self, degree=2, monic=True, *args, **kwds): raise ValueError("minimum degree must be less or equal than maximum degree") degree = randint(*degree) while True: - irred = self.random_element((degree,degree), monic=monic) + irred = self.random_element((degree, degree), monic=monic) if irred.is_irreducible(): return irred - def is_commutative(self): + def is_commutative(self) -> bool: r""" Return ``True`` if this Ore polynomial ring is commutative, i.e. if the twisting morphism is the identity and the twisting derivation vanishes. @@ -1101,7 +1073,7 @@ def is_commutative(self): """ return self._morphism is None and self._derivation is None - def is_field(self, proof=False): + def is_field(self, proof=False) -> bool: r""" Return always ``False`` since Ore polynomial rings are never fields. From ee21b90476390af07b88ac03116f00d0c1471678 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Fri, 8 Oct 2021 14:01:00 +0200 Subject: [PATCH 307/359] fix some doctests --- src/doc/en/constructions/modular_forms.rst | 3 ++- .../explicit_methods_in_number_theory/level_one_forms.rst | 3 ++- .../modular_forms_and_hecke_operators.rst | 6 +++--- src/sage/modular/arithgroup/arithgroup_generic.py | 6 ++---- src/sage/modular/modform/ambient_R.py | 1 + src/sage/modular/modform/ring.py | 1 + src/sage/modular/overconvergent/hecke_series.py | 7 ++++--- src/sage/tests/book_stein_modform.py | 1 + 8 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/doc/en/constructions/modular_forms.rst b/src/doc/en/constructions/modular_forms.rst index 34ab41622db..d3c76fd2d33 100644 --- a/src/doc/en/constructions/modular_forms.rst +++ b/src/doc/en/constructions/modular_forms.rst @@ -4,7 +4,7 @@ Modular forms ************* -One of 's computational specialities is (the very technical field +One of SageMath's computational specialities is (the very technical field of) modular forms and can do a lot more than is even suggested in this very brief introduction. @@ -19,6 +19,7 @@ section "Modular forms" in the Tutorial: :: + sage: from sage.modular.dims import dimension_cusp_forms sage: dimension_cusp_forms(Gamma0(11),2) 1 sage: dimension_cusp_forms(Gamma0(1),12) diff --git a/src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/level_one_forms.rst b/src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/level_one_forms.rst index 42841173aa0..e2777d45512 100644 --- a/src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/level_one_forms.rst +++ b/src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/level_one_forms.rst @@ -52,6 +52,7 @@ rather nice diagonal shape. q + 195660*q^3 + 12080128*q^4 + 44656110*q^5 + O(q^6), q^2 - 48*q^3 + 1080*q^4 - 15040*q^5 + O(q^6) ] + sage: from sage.modular.dims import dimension_modular_forms sage: dimension_modular_forms(1,200) 17 sage: B = victor_miller_basis(200, 18) #5 seconds @@ -64,7 +65,7 @@ rather nice diagonal shape. ] Note: Craig Citro has made the above computation an order of -magnitude faster in code he hasn't quite got into Sage yet. +magnitude faster in code he has not quite got into Sage yet. "I'll clean those up and submit them soon, since I need them for something I'm working on ... I'm currently in the process of making diff --git a/src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/modular_forms_and_hecke_operators.rst b/src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/modular_forms_and_hecke_operators.rst index e9cf689d171..4d223f282d3 100644 --- a/src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/modular_forms_and_hecke_operators.rst +++ b/src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/modular_forms_and_hecke_operators.rst @@ -164,14 +164,14 @@ dimension formulas. sage: ModularForms(Gamma1(949284), 456).dimension() 11156973844800 + sage: from sage.modular.dims import dimension_cusp_forms sage: a = [dimension_cusp_forms(Gamma0(N),2) for N in [1..25]]; a [0, 0, ..., 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 2, 2, 1, 0] sage: oeis(a) # optional - internet 0: A001617: Genus of modular group Gamma_0(n). Or, genus of modular curve X_0(n). -Sage doesn't have simple formulas for dimensions of spaces of -modular forms of weight :math:`1`, since such formulas perhaps do -not exist. +Sage does not have simple formulas for dimensions of spaces of modular +forms of weight :math:`1`, since such formulas perhaps do not exist. Diamond Bracket Operators ~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/src/sage/modular/arithgroup/arithgroup_generic.py b/src/sage/modular/arithgroup/arithgroup_generic.py index a2a97d403d9..58b74d9851b 100644 --- a/src/sage/modular/arithgroup/arithgroup_generic.py +++ b/src/sage/modular/arithgroup/arithgroup_generic.py @@ -952,7 +952,7 @@ def is_congruence(self): def genus(self): r""" - Return the genus of the modular curve of self. + Return the genus of the modular curve of ``self``. EXAMPLES:: @@ -960,6 +960,7 @@ def genus(self): 0 sage: Gamma1(31).genus() 26 + sage: from sage.modular.dims import dimension_cusp_forms sage: Gamma1(157).genus() == dimension_cusp_forms(Gamma1(157), 2) True sage: GammaH(7, [2]).genus() @@ -968,10 +969,7 @@ def genus(self): [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 2, 2] sage: [n for n in [1..200] if Gamma0(n).genus() == 1] [11, 14, 15, 17, 19, 20, 21, 24, 27, 32, 36, 49] - - """ - return ZZ(1 + (self.projective_index()) / ZZ(12) - (self.nu2())/ZZ(4) - (self.nu3())/ZZ(3) - self.ncusps()/ZZ(2)) def farey_symbol(self): diff --git a/src/sage/modular/modform/ambient_R.py b/src/sage/modular/modform/ambient_R.py index 97ac8ef61eb..b64334dd231 100644 --- a/src/sage/modular/modform/ambient_R.py +++ b/src/sage/modular/modform/ambient_R.py @@ -95,6 +95,7 @@ def _compute_q_expansion_basis(self, prec=None): sage: S = M.cuspidal_subspace() sage: 0 in [f.valuation() for f in S.basis()] False + sage: from sage.modular.dims import dimension_cusp_forms sage: len(S.basis()) == dimension_cusp_forms(Gamma1(29), 2) True """ diff --git a/src/sage/modular/modform/ring.py b/src/sage/modular/modform/ring.py index 45c9c16126f..8d77f47d7f0 100644 --- a/src/sage/modular/modform/ring.py +++ b/src/sage/modular/modform/ring.py @@ -698,6 +698,7 @@ def generators(self, maxweight=8, prec=10, start_gens=[], start_weight=2): 3 sage: [k for k, _ in v] [2, 2, 4] + sage: from sage.modular.dims import dimension_modular_forms sage: dimension_modular_forms(11,2) 2 sage: dimension_modular_forms(11,4) diff --git a/src/sage/modular/overconvergent/hecke_series.py b/src/sage/modular/overconvergent/hecke_series.py index 220d34696e6..eb5cf8b362c 100644 --- a/src/sage/modular/overconvergent/hecke_series.py +++ b/src/sage/modular/overconvergent/hecke_series.py @@ -66,8 +66,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.functions.all import floor, ceil from sage.arith.all import valuation @@ -75,7 +75,7 @@ from sage.rings.finite_rings.finite_field_constructor import GF from sage.modular.modform.all import ModularForms, ModularFormsRing, delta_qexp, eisenstein_series_qexp from sage.modular.dims import dimension_modular_forms -from sage.misc.functional import dimension,transpose,charpoly +from sage.misc.functional import dimension, transpose, charpoly from sage.matrix.constructor import matrix, random_matrix from sage.matrix.matrix_space import MatrixSpace from sage.misc.misc import cputime @@ -858,6 +858,7 @@ def compute_Wi(k,p,h,hj,E4,E6): sage: E4 = eisenstein_series_qexp(4, prec, K=S, normalization="constant") sage: E6 = eisenstein_series_qexp(6, prec, K=S, normalization="constant") sage: h = delta_qexp(prec, K=S) / E6^2 + sage: from sage.modular.dims import dimension_modular_forms sage: j = dimension_modular_forms(1, k - (p-1)) sage: hj = h**j sage: c = compute_Wi(k,p,h,hj,E4,E6); c diff --git a/src/sage/tests/book_stein_modform.py b/src/sage/tests/book_stein_modform.py index 14bcacf8888..b0e909c0017 100644 --- a/src/sage/tests/book_stein_modform.py +++ b/src/sage/tests/book_stein_modform.py @@ -444,6 +444,7 @@ (Dirichlet character modulo 13 of conductor 13 mapping 2 |--> -zeta6, Dirichlet character modulo 13 of conductor 1 mapping 2 |--> 1, 1) (Dirichlet character modulo 13 of conductor 1 mapping 2 |--> 1, Dirichlet character modulo 13 of conductor 13 mapping 2 |--> -zeta6 + 1, 1) (Dirichlet character modulo 13 of conductor 13 mapping 2 |--> -zeta6 + 1, Dirichlet character modulo 13 of conductor 1 mapping 2 |--> 1, 1) +sage: from sage.modular.dims import * sage: dimension_cusp_forms(Gamma0(2007),2) 221 sage: dimension_eis(Gamma0(2007),2) From 32c87b932eef87707d1acf6c5965a2850df39f15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sat, 9 Oct 2021 11:16:24 +0200 Subject: [PATCH 308/359] fix doctests in doc/ --- src/doc/de/tutorial/tour_advanced.rst | 1 + src/doc/en/constructions/modular_forms.rst | 3 +-- src/doc/en/tutorial/tour_advanced.rst | 1 + src/doc/fr/tutorial/tour_advanced.rst | 1 + src/doc/ja/tutorial/tour_advanced.rst | 1 + src/doc/pt/tutorial/tour_advanced.rst | 1 + src/doc/ru/tutorial/tour_advanced.rst | 1 + 7 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/doc/de/tutorial/tour_advanced.rst b/src/doc/de/tutorial/tour_advanced.rst index b36e8ae8fff..7ee92b357df 100644 --- a/src/doc/de/tutorial/tour_advanced.rst +++ b/src/doc/de/tutorial/tour_advanced.rst @@ -405,6 +405,7 @@ Räumen von Modulformen zur Verfügung. Zum Beispiel, :: + sage: from sage.modular.dims import dimension_cusp_forms sage: dimension_cusp_forms(Gamma0(11),2) 1 sage: dimension_cusp_forms(Gamma0(1),12) diff --git a/src/doc/en/constructions/modular_forms.rst b/src/doc/en/constructions/modular_forms.rst index d3c76fd2d33..7979214859d 100644 --- a/src/doc/en/constructions/modular_forms.rst +++ b/src/doc/en/constructions/modular_forms.rst @@ -32,8 +32,6 @@ dimensions of newforms), ``dimension_modular_forms`` (for modular forms), and ``dimension_eis`` (for Eisenstein series). The syntax is similar - see the Reference Manual for examples. -In future versions of Sage, more related commands will be added. - .. index:: cosets of Gamma_0 Coset representatives @@ -116,6 +114,7 @@ and related curves. Here are some examples of the syntax: :: + sage: from sage.modular.dims import dimension_cusp_forms sage: dimension_cusp_forms(Gamma0(22)) 2 sage: dimension_cusp_forms(Gamma0(30)) diff --git a/src/doc/en/tutorial/tour_advanced.rst b/src/doc/en/tutorial/tour_advanced.rst index db8f363d5bc..a34bb01f5e4 100644 --- a/src/doc/en/tutorial/tour_advanced.rst +++ b/src/doc/en/tutorial/tour_advanced.rst @@ -402,6 +402,7 @@ spaces of modular forms. For example, :: + sage: from sage.modular.dims import dimension_cusp_forms sage: dimension_cusp_forms(Gamma0(11),2) 1 sage: dimension_cusp_forms(Gamma0(1),12) diff --git a/src/doc/fr/tutorial/tour_advanced.rst b/src/doc/fr/tutorial/tour_advanced.rst index d9ec556934a..c6a0f2078e8 100644 --- a/src/doc/fr/tutorial/tour_advanced.rst +++ b/src/doc/fr/tutorial/tour_advanced.rst @@ -402,6 +402,7 @@ d'espaces de formes modulaires. Par exemple, :: + sage: from sage.modular.dims import dimension_cusp_forms sage: dimension_cusp_forms(Gamma0(11),2) 1 sage: dimension_cusp_forms(Gamma0(1),12) diff --git a/src/doc/ja/tutorial/tour_advanced.rst b/src/doc/ja/tutorial/tour_advanced.rst index 431cb2a8a16..a2b53ffc07a 100644 --- a/src/doc/ja/tutorial/tour_advanced.rst +++ b/src/doc/ja/tutorial/tour_advanced.rst @@ -383,6 +383,7 @@ Sageを使ってモジュラー空間の次元,モジュラー・シンポル :: + sage: from sage.modular.dims import dimension_cusp_forms sage: dimension_cusp_forms(Gamma0(11),2) 1 sage: dimension_cusp_forms(Gamma0(1),12) diff --git a/src/doc/pt/tutorial/tour_advanced.rst b/src/doc/pt/tutorial/tour_advanced.rst index dcd0969fb8e..075b3b1551e 100644 --- a/src/doc/pt/tutorial/tour_advanced.rst +++ b/src/doc/pt/tutorial/tour_advanced.rst @@ -402,6 +402,7 @@ de formas modulares. Por exemplo, :: + sage: from sage.modular.dims import dimension_cusp_forms sage: dimension_cusp_forms(Gamma0(11),2) 1 sage: dimension_cusp_forms(Gamma0(1),12) diff --git a/src/doc/ru/tutorial/tour_advanced.rst b/src/doc/ru/tutorial/tour_advanced.rst index 6d1d3bbb34c..69eb42dfd4c 100644 --- a/src/doc/ru/tutorial/tour_advanced.rst +++ b/src/doc/ru/tutorial/tour_advanced.rst @@ -364,6 +364,7 @@ Sage может выполнять вычисления, связанные с :: + sage: from sage.modular.dims import dimension_cusp_forms sage: dimension_cusp_forms(Gamma0(11),2) 1 sage: dimension_cusp_forms(Gamma0(1),12) From 4a8f4096e3bdd9b0845a2fd17a19983b00caca3c Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 9 Oct 2021 22:15:13 -0700 Subject: [PATCH 309/359] src/sage/misc/lazy_import.pyx: Warnings suppress duplicates, so use a different import for the repeated test --- src/sage/misc/lazy_import.pyx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sage/misc/lazy_import.pyx b/src/sage/misc/lazy_import.pyx index fb06fa01f56..c7c9c5400a5 100644 --- a/src/sage/misc/lazy_import.pyx +++ b/src/sage/misc/lazy_import.pyx @@ -234,11 +234,11 @@ cdef class LazyImport(object): Integer Ring sage: my_integer_ring._object is None False - sage: my_integer_ring = LazyImport('sage.rings.all', 'ZZ', at_startup=True) - sage: my_integer_ring + sage: my_rats = LazyImport('sage.rings.rational_field', 'QQ', at_startup=True) + sage: my_rats doctest:warning... - UserWarning: Option ``at_startup=True`` for lazy import ZZ not needed anymore - Integer Ring + UserWarning: Option ``at_startup=True`` for lazy import QQ not needed anymore + Rational Field """ if self._object is not None: return self._object From cf5d26697d96fcee871f6393491c241e8ab83522 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sun, 10 Oct 2021 10:15:36 +0200 Subject: [PATCH 310/359] fix some annotations in combinat --- src/sage/combinat/gelfand_tsetlin_patterns.py | 6 ++-- src/sage/combinat/parking_functions.py | 29 +++++++++++-------- src/sage/combinat/plane_partition.py | 17 ++++++----- 3 files changed, 29 insertions(+), 23 deletions(-) diff --git a/src/sage/combinat/gelfand_tsetlin_patterns.py b/src/sage/combinat/gelfand_tsetlin_patterns.py index a7c245f13ea..b8b79764817 100644 --- a/src/sage/combinat/gelfand_tsetlin_patterns.py +++ b/src/sage/combinat/gelfand_tsetlin_patterns.py @@ -150,7 +150,7 @@ def __classcall_private__(self, gt): """ return GelfandTsetlinPatterns()(gt) - def check(self) -> bool: + def check(self): """ Check that this is a valid Gelfand-Tsetlin pattern. @@ -159,8 +159,8 @@ def check(self) -> bool: sage: G = GelfandTsetlinPatterns() sage: G([[3,2,1],[2,1],[1]]).check() """ - assert all( self[i-1][j] >= self[i][j] >= self[i-1][j+1] - for i in range(1, len(self)) for j in range(len(self[i])) ) + assert all(self[i - 1][j] >= self[i][j] >= self[i - 1][j + 1] + for i in range(1, len(self)) for j in range(len(self[i]))) def _hash_(self) -> int: """ diff --git a/src/sage/combinat/parking_functions.py b/src/sage/combinat/parking_functions.py index d1a551ffc40..3a859dbaf6b 100644 --- a/src/sage/combinat/parking_functions.py +++ b/src/sage/combinat/parking_functions.py @@ -62,7 +62,8 @@ # the License, or (at your option) any later version. # https://www.gnu.org/licenses/ # **************************************************************************** -from typing import NewType, Iterator, Tuple +from __future__ import annotations +from typing import Iterator from sage.rings.integer import Integer from sage.rings.rational_field import QQ @@ -81,9 +82,6 @@ from sage.structure.unique_representation import UniqueRepresentation -PF = NewType('PF', 'ParkingFunction') - - def is_a(x, n=None) -> bool: r""" Check whether a list is a parking function. @@ -108,6 +106,7 @@ def is_a(x, n=None) -> bool: A = sorted(x) return check_NDPF(A, n) + class ParkingFunction(ClonableArray, metaclass=InheritComparisonClasscallMetaclass): r""" A Parking Function. @@ -308,8 +307,9 @@ def diagonal_reading_word(self) -> Permutation: L = self.to_labelling_permutation() D = self.to_area_sequence() m = max(D) - return Permutation([L[-j - 1] for i in range(m + 1) - for j in range(len(L)) if D[-j - 1] == m - i]) + data = [L[-j - 1] for i in range(m + 1) + for j in range(len(L)) if D[-j - 1] == m - i] + return Permutation(data) # type: ignore diagonal_word = diagonal_reading_word @@ -385,7 +385,8 @@ def cars_permutation(self) -> Permutation: while self[i] + j in out: j += 1 out[self[i] + j] = i - return Permutation([out[i + 1] + 1 for i in range(len(self))]) + data = [out[i + 1] + 1 for i in range(len(self))] + return Permutation(data) # type: ignore def jump_list(self) -> list: # cars displacements r""" @@ -893,7 +894,7 @@ def to_dyck_word(self) -> DyckWord: sage: ParkingFunction([2,1,4,1]).to_dyck_word() [1, 1, 0, 1, 0, 0, 1, 0] """ - return DyckWord(area_sequence=self.to_area_sequence()) + return DyckWord(area_sequence=self.to_area_sequence()) # type: ignore def to_labelled_dyck_word(self): r""" @@ -930,7 +931,7 @@ def to_labelled_dyck_word(self): out.insert(i, 0) return out - def to_labelling_dyck_word_pair(self) -> Tuple[Permutation, DyckWord]: + def to_labelling_dyck_word_pair(self) -> tuple[Permutation, DyckWord]: r""" Return the pair ``(L, D)`` where ``L`` is a labelling and ``D`` is the Dyck word of the parking function. @@ -988,7 +989,7 @@ def to_NonDecreasingParkingFunction(self) -> PF: sage: ParkingFunction([4,1,2,1]).to_NonDecreasingParkingFunction() [1, 1, 2, 4] """ - return ParkingFunction(sorted(self)) + return ParkingFunction(sorted(self)) # type: ignore def characteristic_quasisymmetric_function(self, q=None, R=QQ['q', 't'].fraction_field()): @@ -1138,6 +1139,9 @@ def pretty_print(self, underpath=True): else: dw.pretty_print(labelling=L, underpath=False) + +PF = ParkingFunction + # ***************************************************************************** # CONSTRUCTIONS # ***************************************************************************** @@ -1218,9 +1222,10 @@ def from_labelled_dyck_word(LDW) -> PF: [2, 1, 4, 1] """ L = [ell for ell in LDW if ell != 0] - D = DyckWord([Integer(not x.is_zero()) for x in LDW]) + D = DyckWord([Integer(not x.is_zero()) for x in LDW]) # type: ignore return from_labelling_and_area_sequence(L, D.to_area_sequence()) + class ParkingFunctions(UniqueRepresentation, Parent): r""" Return the combinatorial class of Parking Functions. @@ -1319,6 +1324,7 @@ def __classcall_private__(cls, n=None): raise ValueError("%s is not a non-negative integer" % n) return ParkingFunctions_n(n) + class ParkingFunctions_all(ParkingFunctions): def __init__(self): """ @@ -1606,4 +1612,3 @@ def random_element(self) -> PF: position += Zm.one() free.remove(position) return self.element_class(self, [(i - free[0]).lift() for i in fun]) - diff --git a/src/sage/combinat/plane_partition.py b/src/sage/combinat/plane_partition.py index 0675a1000c4..865dd2cb3d4 100644 --- a/src/sage/combinat/plane_partition.py +++ b/src/sage/combinat/plane_partition.py @@ -22,7 +22,8 @@ # # https://www.gnu.org/licenses/ # **************************************************************************** -from typing import NewType, Iterator, Tuple +from __future__ import annotations +from typing import Iterator from sage.structure.list_clone import ClonableArray from sage.misc.inherit_comparison import InheritComparisonClasscallMetaclass @@ -36,9 +37,6 @@ from sage.plot.plot3d.platonic import cube -PP = NewType('PP', 'PlanePartition') - - class PlanePartition(ClonableArray, metaclass=InheritComparisonClasscallMetaclass): r""" @@ -141,7 +139,7 @@ def to_tableau(self) -> Tableau: sage: PP.to_tableau() [[4, 3, 3, 1], [2, 1, 1], [1, 1]] """ - return Tableau(self) + return Tableau(self) # type: ignore def z_tableau(self): r""" @@ -768,6 +766,9 @@ def is_TSSCPP(self) -> bool: return self.is_TSPP() and self.is_SCPP() +PP = PlanePartition + + class PlanePartitions(UniqueRepresentation, Parent): r""" All plane partitions inside a rectangular box of given side lengths. @@ -832,7 +833,7 @@ def _repr_(self) -> str: return "Plane partitions inside a {} x {} x {} box".format( self._box[0], self._box[1], self._box[2]) - def __iter__(self) -> Iterator: + def __iter__(self) -> Iterator[PP]: """ Iterate over ``self``. @@ -848,7 +849,7 @@ def __iter__(self) -> Iterator: C = self._box[2] from sage.combinat.tableau import SemistandardTableaux for T in SemistandardTableaux([B for i in range(A)], max_entry=C + A): - PP = [[0 for i in range(B)] for j in range(A)] + PP = [[0 for _ in range(B)] for _ in range(A)] for r in range(A): for c in range(B): PP[A - 1 - r][B - 1 - c] = T[r][c] - r - 1 @@ -880,7 +881,7 @@ def cardinality(self) -> Integer: for j in range(1, B + 1) for k in range(1, C + 1))) - def box(self) -> Tuple: + def box(self) -> tuple: """ Return the sizes of the box of the plane partitions of ``self`` are contained in. From 1eb5b843970c47f2bad9e720da5da7c78c35b9bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sun, 10 Oct 2021 10:54:35 +0200 Subject: [PATCH 311/359] more conversions for trig functions, pep8 cleanup --- src/sage/functions/hyperbolic.py | 24 +++++++++++--- src/sage/functions/trig.py | 57 +++++++++++++++++++++++++------- 2 files changed, 64 insertions(+), 17 deletions(-) diff --git a/src/sage/functions/hyperbolic.py b/src/sage/functions/hyperbolic.py index 58f3eb0c846..2ca5284f505 100644 --- a/src/sage/functions/hyperbolic.py +++ b/src/sage/functions/hyperbolic.py @@ -80,6 +80,7 @@ def __init__(self): """ GinacFunction.__init__(self, "sinh", latex_name=r"\sinh") + sinh = Function_sinh() @@ -116,6 +117,7 @@ def __init__(self): """ GinacFunction.__init__(self, "cosh", latex_name=r"\cosh") + cosh = Function_cosh() @@ -180,6 +182,7 @@ def __init__(self): """ GinacFunction.__init__(self, "tanh", latex_name=r"\tanh") + tanh = Function_tanh() @@ -235,6 +238,7 @@ def _eval_numpy_(self, x): """ return 1.0 / tanh(x) + coth = Function_coth() @@ -288,6 +292,7 @@ def _eval_numpy_(self, x): """ return 1.0 / cosh(x) + sech = Function_sech() @@ -339,6 +344,7 @@ def _eval_numpy_(self, x): """ return 1.0 / sinh(x) + csch = Function_csch() @@ -403,7 +409,8 @@ def __init__(self): GinacFunction.__init__(self, "arcsinh", latex_name=r"\operatorname{arsinh}", conversions=dict(maxima='asinh', sympy='asinh', fricas='asinh', - giac='asinh')) + giac='asinh', mathematica='ArcSinh')) + arcsinh = asinh = Function_arcsinh() @@ -488,7 +495,8 @@ def __init__(self): GinacFunction.__init__(self, "arccosh", latex_name=r"\operatorname{arcosh}", conversions=dict(maxima='acosh', sympy='acosh', fricas='acosh', - giac='acosh')) + giac='acosh', mathematica='ArcCosh')) + arccosh = acosh = Function_arccosh() @@ -547,7 +555,8 @@ def __init__(self): GinacFunction.__init__(self, "arctanh", latex_name=r"\operatorname{artanh}", conversions=dict(maxima='atanh', sympy='atanh', fricas='atanh', - giac='atanh')) + giac='atanh', mathematica='ArcTanh')) + arctanh = atanh = Function_arctanh() @@ -594,7 +603,8 @@ def __init__(self): """ GinacFunction.__init__(self, "arccoth", latex_name=r"\operatorname{arcoth}", - conversions=dict(maxima='acoth', sympy='acoth', fricas='acoth')) + conversions=dict(maxima='acoth', sympy='acoth', + giac='acoth', fricas='acoth')) def _eval_numpy_(self, x): """ @@ -607,6 +617,7 @@ def _eval_numpy_(self, x): """ return arctanh(1.0 / x) + arccoth = acoth = Function_arccoth() @@ -637,7 +648,8 @@ def __init__(self): """ GinacFunction.__init__(self, "arcsech", latex_name=r"\operatorname{arsech}", - conversions=dict(maxima='asech', sympy='asech', fricas='asech')) + conversions=dict(maxima='asech', sympy='asech', + fricas='asech')) def _eval_numpy_(self, x): """ @@ -651,6 +663,7 @@ def _eval_numpy_(self, x): """ return arccosh(1.0 / x) + arcsech = asech = Function_arcsech() @@ -702,4 +715,5 @@ def _eval_numpy_(self, x): """ return arcsinh(1.0 / x) + arccsch = acsch = Function_arccsch() diff --git a/src/sage/functions/trig.py b/src/sage/functions/trig.py index fbee1cd0cc8..a705648a8ce 100644 --- a/src/sage/functions/trig.py +++ b/src/sage/functions/trig.py @@ -118,7 +118,9 @@ def __init__(self): sin(1/42*pi) """ GinacFunction.__init__(self, 'sin', latex_name=r"\sin", - conversions=dict(maxima='sin',mathematica='Sin',giac='sin')) + conversions=dict(maxima='sin', mathematica='Sin', + giac='sin', fricas='sin', sympy='sin')) + sin = Function_sin() @@ -181,7 +183,9 @@ def __init__(self): -cos(1/42*pi) """ GinacFunction.__init__(self, 'cos', latex_name=r"\cos", - conversions=dict(maxima='cos',mathematica='Cos',giac='cos')) + conversions=dict(maxima='cos', mathematica='Cos', + giac='cos', fricas='cos', sympy='cos')) + cos = Function_cos() @@ -243,8 +247,10 @@ def __init__(self): """ GinacFunction.__init__(self, 'tan', latex_name=r"\tan") + tan = Function_tan() + class Function_cot(GinacFunction): def __init__(self): r""" @@ -337,6 +343,7 @@ def _eval_numpy_(self, x): """ return 1.0 / tan(x) + cot = Function_cot() @@ -406,8 +413,10 @@ def _eval_numpy_(self, x): """ return 1 / cos(x) + sec = Function_sec() + class Function_csc(GinacFunction): def __init__(self): r""" @@ -474,8 +483,10 @@ def _eval_numpy_(self, x): """ return 1 / sin(x) + csc = Function_csc() + ################################### # Inverse Trigonometric Functions # ################################### @@ -535,10 +546,14 @@ def __init__(self): 1.57079632679490 - 1.37285914424258*I """ GinacFunction.__init__(self, 'arcsin', latex_name=r"\arcsin", - conversions=dict(maxima='asin', sympy='asin', fricas="asin", giac="asin")) + conversions=dict(maxima='asin', sympy='asin', + mathematica='ArcSin', + fricas="asin", giac="asin")) + arcsin = asin = Function_arcsin() + class Function_arccos(GinacFunction): def __init__(self): """ @@ -596,10 +611,14 @@ def __init__(self): 1.37285914424258*I """ GinacFunction.__init__(self, 'arccos', latex_name=r"\arccos", - conversions=dict(maxima='acos', sympy='acos', fricas='acos', giac='acos')) + conversions=dict(maxima='acos', sympy='acos', + mathematica='ArcCos', + fricas='acos', giac='acos')) + arccos = acos = Function_arccos() + class Function_arctan(GinacFunction): def __init__(self): """ @@ -664,10 +683,14 @@ def __init__(self): 1/2*pi """ GinacFunction.__init__(self, 'arctan', latex_name=r"\arctan", - conversions=dict(maxima='atan', sympy='atan', fricas='atan', giac='atan')) + conversions=dict(maxima='atan', sympy='atan', + mathematica='ArcTan', + fricas='atan', giac='atan')) + arctan = atan = Function_arctan() + class Function_arccot(GinacFunction): def __init__(self): """ @@ -714,7 +737,8 @@ def __init__(self): """ GinacFunction.__init__(self, 'arccot', latex_name=r"\operatorname{arccot}", - conversions=dict(maxima='acot', sympy='acot', fricas='acot',giac='acot')) + conversions=dict(maxima='acot', sympy='acot', + fricas='acot', giac='acot')) def _eval_numpy_(self, x): """ @@ -725,10 +749,12 @@ def _eval_numpy_(self, x): sage: arccot(a) array([0.46364761, 0.32175055, 0.24497866]) """ - return math.pi/2 - arctan(x) + return math.pi / 2 - arctan(x) + arccot = acot = Function_arccot() + class Function_arccsc(GinacFunction): def __init__(self): """ @@ -770,7 +796,8 @@ def __init__(self): (0.45227844715119064-0.5306375309525178j) """ GinacFunction.__init__(self, 'arccsc', latex_name=r"\operatorname{arccsc}", - conversions=dict(maxima='acsc', sympy='acsc', fricas='acsc', giac='acsc')) + conversions=dict(maxima='acsc', sympy='acsc', + fricas='acsc', giac='acsc')) def _eval_numpy_(self, x): """ @@ -781,10 +808,12 @@ def _eval_numpy_(self, x): sage: arccsc(a) array([0.52359878, 0.33983691, 0.25268026]) """ - return arcsin(1.0/x) + return arcsin(1.0 / x) + arccsc = acsc = Function_arccsc() + class Function_arcsec(GinacFunction): def __init__(self): """ @@ -828,7 +857,8 @@ def __init__(self): (1.118517879643706+0.5306375309525178j) """ GinacFunction.__init__(self, 'arcsec', latex_name=r"\operatorname{arcsec}", - conversions=dict(maxima='asec', sympy='asec', fricas='asec', giac='asec')) + conversions=dict(maxima='asec', sympy='asec', + fricas='asec', giac='asec')) def _eval_numpy_(self, x): """ @@ -839,10 +869,12 @@ def _eval_numpy_(self, x): sage: arcsec(a) array([1.04719755, 1.23095942, 1.31811607]) """ - return arccos(1.0/x) + return arccos(1.0 / x) + arcsec = asec = Function_arcsec() + class Function_arctan2(GinacFunction): def __init__(self): r""" @@ -961,6 +993,7 @@ def __init__(self): pi """ GinacFunction.__init__(self, 'arctan2', nargs=2, latex_name=r"\arctan", - conversions=dict(maxima='atan2', sympy='atan2')) + conversions=dict(maxima='atan2', sympy='atan2', giac='atan2')) + arctan2 = atan2 = Function_arctan2() From bc62348b32e1a06d88a66359c977fac9e15c68a5 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 10 Oct 2021 13:54:33 -0700 Subject: [PATCH 312/359] src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx: Add some missing # optional - sage.combinat --- .../geometry/polyhedron/combinatorial_polyhedron/base.pyx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx b/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx index 612a4da19b9..fe2ae912c0b 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx @@ -607,8 +607,9 @@ cdef class CombinatorialPolyhedron(SageObject): sage: it1 = C1.face_iter() # optional - sage.combinat sage: tup = tuple((face.ambient_Vrepresentation(), # optional - sage.combinat ....: face.ambient_Hrepresentation()) for face in it) - sage: tup1 = tuple((face.ambient_Vrepresentation(), face.ambient_Hrepresentation()) for face in it1) - sage: tup == tup1 + sage: tup1 = tuple((face.ambient_Vrepresentation(), # optional - sage.combinat + ....: face.ambient_Hrepresentation()) for face in it1) + sage: tup == tup1 # optional - sage.combinat True sage: P = polytopes.cyclic_polytope(4,10) @@ -2738,7 +2739,7 @@ cdef class CombinatorialPolyhedron(SageObject): [A 0-dimensional face of a 3-dimensional combinatorial polyhedron, A 1-dimensional face of a 3-dimensional combinatorial polyhedron, A 2-dimensional face of a 3-dimensional combinatorial polyhedron] - sage: [face.ambient_V_indices() for face in chain] + sage: [face.ambient_V_indices() for face in chain] # optional - sage.combinat [(16,), (15, 16), (8, 9, 14, 15, 16, 17)] sage: P = Polyhedron(rays=[[1,0]], lines=[[0,1]]) From 1dee580c54c956d81f17f0fadd80e6e6ed9947f0 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 10 Oct 2021 13:58:34 -0700 Subject: [PATCH 313/359] src/sage/geometry/polyhedron/{base,backend_field}.py: Add some missing # optional --- src/sage/geometry/polyhedron/backend_field.py | 2 +- src/sage/geometry/polyhedron/base.py | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/sage/geometry/polyhedron/backend_field.py b/src/sage/geometry/polyhedron/backend_field.py index 17cba0ed2ef..4ddf271143e 100644 --- a/src/sage/geometry/polyhedron/backend_field.py +++ b/src/sage/geometry/polyhedron/backend_field.py @@ -284,7 +284,7 @@ def _init_Hrepresentation(self, inequalities, equations): sage: Hrep = [[[0, 1], [1, -1]], []] sage: p = Polyhedron_field(parent, Vrep, Hrep, # indirect doctest # optional - sage.rings.number_field ....: Vrep_minimal=True, Hrep_minimal=True) - sage: p.inequalities_list() + sage: p.inequalities_list() # optional - sage.rings.number_field [[0, 1], [1, -1]] """ self._Hrepresentation = [] diff --git a/src/sage/geometry/polyhedron/base.py b/src/sage/geometry/polyhedron/base.py index 49b3b645c3d..34f0fd50083 100644 --- a/src/sage/geometry/polyhedron/base.py +++ b/src/sage/geometry/polyhedron/base.py @@ -10626,7 +10626,9 @@ def is_combinatorially_isomorphic(self, other, algorithm='bipartite_graph'): sage: H = polytopes.regular_polygon(6) # optional - sage.rings.number_field sage: S = polytopes.hypercube(2) sage: P = polytopes.permutahedron(4) - sage: all(F.as_polyhedron().is_combinatorially_isomorphic(S) or F.as_polyhedron().is_combinatorially_isomorphic(H) for F in P.faces(2)) + sage: all(F.as_polyhedron().is_combinatorially_isomorphic(S) # optional - sage.rings.number_field + ....: or F.as_polyhedron().is_combinatorially_isomorphic(H) + ....: for F in P.faces(2)) True Checking that a regular simplex intersected with its reflection From c1bf35690044b88f2cfec4b6879c4669c138aeaf Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 10 Oct 2021 17:28:16 -0700 Subject: [PATCH 314/359] m4/sage_spkg_collect.m4: Fix up in_sdist logic --- m4/sage_spkg_collect.m4 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/m4/sage_spkg_collect.m4 b/m4/sage_spkg_collect.m4 index 9eccc15ff7f..40ef945e295 100644 --- a/m4/sage_spkg_collect.m4 +++ b/m4/sage_spkg_collect.m4 @@ -144,7 +144,7 @@ for DIR in $SAGE_ROOT/build/pkgs/*; do SPKG_NAME=$(basename $DIR) SPKG_VERSION=$(newest_version $SPKG_NAME) - in_sdist=no + in_sdist=yes dnl Determine package source dnl @@ -221,9 +221,9 @@ for DIR in $SAGE_ROOT/build/pkgs/*; do case "$SPKG_TYPE" in standard) - in_sdist=yes ;; optional|experimental) + in_sdist=no uninstall_message=", use \"$srcdir/configure --disable-$SPKG_NAME\" to uninstall" stampfile="" for f in "$SAGE_SPKG_INST/$SPKG_NAME"-*; do From 8cf915089c3d4d18f2c2def8f093fa6d75902dcc Mon Sep 17 00:00:00 2001 From: Jonathan Kliem Date: Sat, 2 Oct 2021 21:31:35 +0200 Subject: [PATCH 315/359] fix mistake from #32498 --- src/sage/graphs/generic_graph.py | 36 ++++++++++++++++---------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/sage/graphs/generic_graph.py b/src/sage/graphs/generic_graph.py index 6a966a01e3f..6b597dd2a69 100644 --- a/src/sage/graphs/generic_graph.py +++ b/src/sage/graphs/generic_graph.py @@ -23480,18 +23480,18 @@ def edge_polytope(self, backend=None): sage: P.is_combinatorially_isomorphic(polytopes.cross_polytope(3)) True - The EP of a graph with edges is isomorphic - to the product of it's connected components with edges:: + The EP of a graph is isomorphic to the subdirect sum of + it's connected components EPs:: sage: n = randint(5, 12) - sage: G = Graph() - sage: while not G.num_edges(): - ....: G = graphs.RandomGNP(n, 0.2) + sage: G1 = graphs.RandomGNP(n, 0.2) + sage: n = randint(5, 12) + sage: G2 = graphs.RandomGNP(n, 0.2) + sage: G = G1.disjoint_union(G2) sage: P = G.edge_polytope() - sage: components = [G.subgraph(c).edge_polytope() - ....: for c in G.connected_components() - ....: if G.subgraph(c).num_edges()] - sage: P.is_combinatorially_isomorphic(product(components)) + sage: P1 = G1.edge_polytope() + sage: P2 = G2.edge_polytope() + sage: P.is_combinatorially_isomorphic(P1.subdirect_sum(P2)) True All trees on `n` vertices have isomorphic EPs:: @@ -23582,18 +23582,18 @@ def symmetric_edge_polytope(self, backend=None): sage: P.dim() == n - G.connected_components_number() True - The SEP of a graph with edges is isomorphic - to the product of it's connected components with edges:: + The SEP of a graph is isomorphic to the subdirect sum of + it's connected components SEP's:: sage: n = randint(5, 12) - sage: G = Graph() - sage: while not G.num_edges(): - ....: G = graphs.RandomGNP(n, 0.2) + sage: G1 = graphs.RandomGNP(n, 0.2) + sage: n = randint(5, 12) + sage: G2 = graphs.RandomGNP(n, 0.2) + sage: G = G1.disjoint_union(G2) sage: P = G.symmetric_edge_polytope() - sage: components = [G.subgraph(c).symmetric_edge_polytope() - ....: for c in G.connected_components() - ....: if G.subgraph(c).num_edges()] - sage: P.is_combinatorially_isomorphic(product(components)) + sage: P1 = G1.symmetric_edge_polytope() + sage: P2 = G2.symmetric_edge_polytope() + sage: P.is_combinatorially_isomorphic(P1.subdirect_sum(P2)) True All trees on `n` vertices have isomorphic SEPs:: From dccd8a29e4777aa229607b5eda36d3026932b359 Mon Sep 17 00:00:00 2001 From: Jonathan Kliem Date: Mon, 4 Oct 2021 10:16:25 +0200 Subject: [PATCH 316/359] reasonable graph size for doctets --- src/sage/graphs/generic_graph.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sage/graphs/generic_graph.py b/src/sage/graphs/generic_graph.py index 6b597dd2a69..8efe2ee7f77 100644 --- a/src/sage/graphs/generic_graph.py +++ b/src/sage/graphs/generic_graph.py @@ -23483,9 +23483,9 @@ def edge_polytope(self, backend=None): The EP of a graph is isomorphic to the subdirect sum of it's connected components EPs:: - sage: n = randint(5, 12) + sage: n = randint(3, 6) sage: G1 = graphs.RandomGNP(n, 0.2) - sage: n = randint(5, 12) + sage: n = randint(3, 6) sage: G2 = graphs.RandomGNP(n, 0.2) sage: G = G1.disjoint_union(G2) sage: P = G.edge_polytope() @@ -23585,9 +23585,9 @@ def symmetric_edge_polytope(self, backend=None): The SEP of a graph is isomorphic to the subdirect sum of it's connected components SEP's:: - sage: n = randint(5, 12) + sage: n = randint(3, 6) sage: G1 = graphs.RandomGNP(n, 0.2) - sage: n = randint(5, 12) + sage: n = randint(3, 6) sage: G2 = graphs.RandomGNP(n, 0.2) sage: G = G1.disjoint_union(G2) sage: P = G.symmetric_edge_polytope() From 1bb9d96fce8964851245aee75d25a1ab793878cb Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 10 Oct 2021 22:42:30 -0700 Subject: [PATCH 317/359] src/sage/geometry/polyhedron/constructor.py: More # optional - sage.symbolic --- src/sage/geometry/polyhedron/constructor.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/geometry/polyhedron/constructor.py b/src/sage/geometry/polyhedron/constructor.py index e97a72a4aa3..b3986c501c7 100644 --- a/src/sage/geometry/polyhedron/constructor.py +++ b/src/sage/geometry/polyhedron/constructor.py @@ -177,8 +177,8 @@ exact way to work with roots in Sage is the :mod:`Algebraic Real Field ` :: - sage: triangle = Polyhedron([(0,0), (1,0), (1/2, sqrt(3)/2)], base_ring=AA) # optional - sage.rings.number_field - sage: triangle.Hrepresentation() # optional - sage.rings.number_field + sage: triangle = Polyhedron([(0,0), (1,0), (1/2, sqrt(3)/2)], base_ring=AA) # optional - sage.rings.number_field # optional - sage.symbolic + sage: triangle.Hrepresentation() # optional - sage.rings.number_field # optional - sage.symbolic (An inequality (-1, -0.5773502691896258?) x + 1 >= 0, An inequality (1, -0.5773502691896258?) x + 0 >= 0, An inequality (0, 1.154700538379252?) x + 0 >= 0) From cf86501d9edb82a4a50871adf95fa105335af3bf Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 10 Oct 2021 22:44:39 -0700 Subject: [PATCH 318/359] src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx: Fix some # optional --- .../combinatorial_polyhedron/base.pyx | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx b/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx index fe2ae912c0b..4ae37f27804 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx @@ -2384,38 +2384,38 @@ cdef class CombinatorialPolyhedron(SageObject): EXAMPLES:: - sage: P = polytopes.permutahedron(5) # optional - sage.rings.number_field - sage: C = CombinatorialPolyhedron(P) # optional - sage.rings.number_field - sage: it = C.face_iter(dimension=2) # optional - sage.rings.number_field - sage: face = next(it); face # optional - sage.rings.number_field + sage: P = polytopes.permutahedron(5) # optional - sage.combinat + sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat + sage: it = C.face_iter(dimension=2) # optional - sage.combinat + sage: face = next(it); face # optional - sage.combinat A 2-dimensional face of a 4-dimensional combinatorial polyhedron - sage: face.ambient_Vrepresentation() # optional - sage.rings.number_field + sage: face.ambient_Vrepresentation() # optional - sage.combinat (A vertex at (1, 3, 2, 5, 4), A vertex at (2, 3, 1, 5, 4), A vertex at (3, 1, 2, 5, 4), A vertex at (3, 2, 1, 5, 4), A vertex at (2, 1, 3, 5, 4), A vertex at (1, 2, 3, 5, 4)) - sage: face = next(it); face # optional - sage.rings.number_field + sage: face = next(it); face # optional - sage.combinat A 2-dimensional face of a 4-dimensional combinatorial polyhedron - sage: face.ambient_Vrepresentation() # optional - sage.rings.number_field + sage: face.ambient_Vrepresentation() # optional - sage.combinat (A vertex at (2, 1, 4, 5, 3), A vertex at (3, 2, 4, 5, 1), A vertex at (3, 1, 4, 5, 2), A vertex at (1, 3, 4, 5, 2), A vertex at (1, 2, 4, 5, 3), A vertex at (2, 3, 4, 5, 1)) - sage: face.ambient_Hrepresentation() # optional - sage.rings.number_field + sage: face.ambient_Hrepresentation() # optional - sage.combinat (An inequality (0, 0, -1, -1, 0) x + 9 >= 0, An inequality (0, 0, 0, -1, 0) x + 5 >= 0, An equation (1, 1, 1, 1, 1) x - 15 == 0) - sage: face.ambient_H_indices() # optional - sage.rings.number_field + sage: face.ambient_H_indices() # optional - sage.combinat (25, 29, 30) - sage: face = next(it); face # optional - sage.rings.number_field + sage: face = next(it); face # optional - sage.combinat A 2-dimensional face of a 4-dimensional combinatorial polyhedron - sage: face.ambient_H_indices() # optional - sage.rings.number_field + sage: face.ambient_H_indices() # optional - sage.combinat (24, 29, 30) - sage: face.ambient_V_indices() # optional - sage.rings.number_field + sage: face.ambient_V_indices() # optional - sage.combinat (32, 89, 90, 94) sage: C = CombinatorialPolyhedron([[0,1,2],[0,1,3],[0,2,3],[1,2,3]]) From 73a4ca698825c3937a68d2c3a91502c6d736082f Mon Sep 17 00:00:00 2001 From: Jonathan Kliem Date: Mon, 11 Oct 2021 08:03:05 +0200 Subject: [PATCH 319/359] the affine tangent cone of the empty face should be empty --- src/sage/geometry/polyhedron/face.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/sage/geometry/polyhedron/face.py b/src/sage/geometry/polyhedron/face.py index 2d127ceda1c..476072f35fc 100644 --- a/src/sage/geometry/polyhedron/face.py +++ b/src/sage/geometry/polyhedron/face.py @@ -952,7 +952,17 @@ def affine_tangent_cone(self): A ray in the direction (0, 0, 1), A vertex at (1, 0, -1), A ray in the direction (-1, 0, 0)) + + TESTS: + + Check that :trac:`32658` is fixed:: + + sage: P = polytopes.hypercube(2) + sage: P.faces(-1)[0].affine_tangent_cone() + The empty polyhedron in ZZ^2 """ + if self.dim() == -1: + return self.as_polyhedron() parent = self.polyhedron().parent() new_ieqs = [H for H in self.ambient_Hrepresentation() if H.is_inequality()] From 4340762275c36e14ec1fc7dda2d5f477de2150b5 Mon Sep 17 00:00:00 2001 From: Jonathan Kliem Date: Mon, 11 Oct 2021 08:11:39 +0200 Subject: [PATCH 320/359] throw an error, because it is not a cone --- src/sage/geometry/polyhedron/face.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/sage/geometry/polyhedron/face.py b/src/sage/geometry/polyhedron/face.py index 476072f35fc..9d1f53343e7 100644 --- a/src/sage/geometry/polyhedron/face.py +++ b/src/sage/geometry/polyhedron/face.py @@ -959,10 +959,12 @@ def affine_tangent_cone(self): sage: P = polytopes.hypercube(2) sage: P.faces(-1)[0].affine_tangent_cone() - The empty polyhedron in ZZ^2 + Traceback (most recent call last): + ... + ValueError: affine tangent cone of the empty face not defined """ if self.dim() == -1: - return self.as_polyhedron() + raise ValueError("affine tangent cone of the empty face not defined") parent = self.polyhedron().parent() new_ieqs = [H for H in self.ambient_Hrepresentation() if H.is_inequality()] From ca963074e9a932c5f3d28e7a72b8df3d5ddd5d89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sun, 10 Oct 2021 21:08:11 +0200 Subject: [PATCH 321/359] more conversions for Bessel functions --- src/sage/functions/bessel.py | 94 +++++++++++++++++++++--------------- 1 file changed, 55 insertions(+), 39 deletions(-) diff --git a/src/sage/functions/bessel.py b/src/sage/functions/bessel.py index 3adee3b0c94..6de793a1545 100644 --- a/src/sage/functions/bessel.py +++ b/src/sage/functions/bessel.py @@ -332,7 +332,8 @@ def __init__(self): besselj(x, x) """ BuiltinFunction.__init__(self, 'bessel_J', nargs=2, - conversions=dict(mathematica='BesselJ', + conversions=dict(maple='BesselJ', + mathematica='BesselJ', maxima='bessel_j', sympy='besselj', fricas='besselJ', @@ -366,10 +367,10 @@ def _eval_(self, n, x): return ZZ(0) elif n.real() < 0: return unsigned_infinity - if n == QQ(1)/2: - return sqrt(2/pi/x) * sin(x) - elif n == QQ(-1)/2: - return sqrt(2/pi/x) * cos(x) + if n == QQ(1) / 2: + return sqrt(2 / pi / x) * sin(x) + elif n == QQ(-1) / 2: + return sqrt(2 / pi / x) * cos(x) def _evalf_(self, n, x, parent=None, algorithm=None): """ @@ -437,6 +438,7 @@ def _print_latex_(self, n, z): """ return r"J_{%s}(%s)" % (latex(n), latex(z)) + bessel_J = Function_Bessel_J() @@ -549,7 +551,8 @@ def __init__(self): bessely(x, x) """ BuiltinFunction.__init__(self, 'bessel_Y', nargs=2, - conversions=dict(mathematica='BesselY', + conversions=dict(maple='BesselY', + mathematica='BesselY', maxima='bessel_y', sympy='bessely', fricas='besselY', @@ -579,10 +582,10 @@ def _eval_(self, n, x): return -infinity elif n.real() > 0 or n.real() < 0: return unsigned_infinity - if n == QQ(1)/2: - return -sqrt(2/pi/x) * cos(x) - elif n == QQ(-1)/2: - return sqrt(2/pi/x) * sin(x) + if n == QQ((1, 2)): + return -sqrt(2 / pi / x) * cos(x) + elif n == QQ(-1) / 2: + return sqrt(2 / pi / x) * sin(x) def _evalf_(self, n, x, parent=None, algorithm=None): """ @@ -649,6 +652,7 @@ def _print_latex_(self, n, z): """ return r"Y_{%s}(%s)" % (latex(n), latex(z)) + bessel_Y = Function_Bessel_Y() @@ -755,7 +759,8 @@ def __init__(self): besseli(x, x) """ BuiltinFunction.__init__(self, 'bessel_I', nargs=2, - conversions=dict(mathematica='BesselI', + conversions=dict(maple='BesselI', + mathematica='BesselI', maxima='bessel_i', sympy='besseli', fricas='besselI')) @@ -788,12 +793,11 @@ def _eval_(self, n, x): return ZZ(0) elif n.real() < 0: return unsigned_infinity - if n == QQ(1)/2: + if n == QQ(1) / 2: return sqrt(2 / (pi * x)) * sinh(x) - elif n == -QQ(1)/2: + elif n == -QQ(1) / 2: return sqrt(2 / (pi * x)) * cosh(x) - def _evalf_(self, n, x, parent=None, algorithm=None): """ EXAMPLES:: @@ -838,6 +842,7 @@ def _print_latex_(self, n, z): """ return r"I_{%s}(%s)" % (latex(n), latex(z)) + bessel_I = Function_Bessel_I() @@ -955,7 +960,8 @@ def __init__(self): besselk(x, x) """ BuiltinFunction.__init__(self, 'bessel_K', nargs=2, - conversions=dict(mathematica='BesselK', + conversions=dict(maple='BesselK', + mathematica='BesselK', maxima='bessel_k', sympy='besselk', fricas='besselK')) @@ -983,10 +989,9 @@ def _eval_(self, n, x): return infinity elif n.real() > 0 or n.real() < 0: return unsigned_infinity - if n == QQ(1)/2 or n == -QQ(1)/2 and x > 0: + if n == QQ(1) / 2 or n == -QQ(1) / 2 and x > 0: return sqrt(pi / 2) * exp(-x) * x ** (-Integer(1) / Integer(2)) - def _evalf_(self, n, x, parent=None, algorithm=None): """ EXAMPLES:: @@ -1032,6 +1037,7 @@ def _print_latex_(self, n, z): """ return r"K_{%s}(%s)" % (latex(n), latex(z)) + bessel_K = Function_Bessel_K() @@ -1246,7 +1252,8 @@ def __init__(self): conversions=dict(maple='StruveH', mathematica='StruveH', maxima='struve_h', - fricas='struveH')) + fricas='struveH', + sympy='struveh')) def _eval_(self, a, z): """ @@ -1271,17 +1278,17 @@ def _eval_(self, a, z): if z.is_zero() \ and (SR(a).is_numeric() or SR(a).is_constant()) \ and a.real() >= -1: - return ZZ(0) - if a == -Integer(1)/2: + return ZZ(0) + from sage.rings.rational_field import QQ + if a == -QQ((1, 2)): from sage.functions.trig import sin - return sqrt(2/(pi*z)) * sin(z) - if a == Integer(1)/2: + return sqrt(2 / (pi * z)) * sin(z) + if a == QQ((1, 2)): from sage.functions.trig import cos - return sqrt(2/(pi*z)) * (1-cos(z)) - if a < 0 and not SR(a).is_integer() and SR(2*a).is_integer(): - from sage.rings.rational_field import QQ - n = (a*(-2) - 1)/2 - return Integer(-1)**n * bessel_J(n+QQ(1)/2, z) + return sqrt(2 / (pi * z)) * (1 - cos(z)) + if a < 0 and not SR(a).is_integer() and SR(2 * a).is_integer(): + n = (a * (-2) - 1) / 2 + return Integer(-1)**n * bessel_J(n + QQ(1) / 2, z) def _evalf_(self, a, z, parent=None, algorithm=None): """ @@ -1307,7 +1314,7 @@ def _derivative_(self, a, z, diff_param=None): from .gamma import gamma from .other import sqrt - return (z**a/(sqrt(pi)*2**a*gamma(a+Integer(3)/Integer(2)))-struve_H(a+1,z)+struve_H(a-1,z))/2 + return (z**a / (sqrt(pi) * 2**a * gamma(a + Integer(3) / Integer(2))) - struve_H(a + 1, z) + struve_H(a - 1, z)) / 2 def _print_latex_(self, a, z): """ @@ -1318,8 +1325,10 @@ def _print_latex_(self, a, z): """ return r"H_{{%s}}({%s})" % (a, z) + struve_H = Function_Struve_H() + class Function_Struve_L(BuiltinFunction): r""" The modified Struve functions. @@ -1361,7 +1370,8 @@ def __init__(self): conversions=dict(maple='StruveL', mathematica='StruveL', maxima='struve_l', - fricas='struveL')) + fricas='struveL', + sympy='struvel')) def _eval_(self, a, z): """ @@ -1386,17 +1396,17 @@ def _eval_(self, a, z): if z.is_zero() \ and (SR(a).is_numeric() or SR(a).is_constant()) \ and a.real() >= -1: - return ZZ(0) - if a == -Integer(1)/2: + return ZZ(0) + if a == -Integer(1) / 2: from sage.functions.hyperbolic import sinh - return sqrt(2/(pi*z)) * sinh(z) - if a == Integer(1)/2: + return sqrt(2 / (pi * z)) * sinh(z) + if a == Integer(1) / 2: from sage.functions.hyperbolic import cosh - return sqrt(2/(pi*z)) * (cosh(z)-1) - if a < 0 and not SR(a).is_integer() and SR(2*a).is_integer(): + return sqrt(2 / (pi * z)) * (cosh(z) - 1) + if a < 0 and not SR(a).is_integer() and SR(2 * a).is_integer(): from sage.rings.rational_field import QQ - n = (a*(-2) - 1)/2 - return Integer(-1)**n * bessel_I(n+QQ(1)/2, z) + n = (a * (-2) - 1) / 2 + return Integer(-1)**n * bessel_I(n + QQ(1) / 2, z) def _evalf_(self, a, z, parent=None, algorithm=None): """ @@ -1422,7 +1432,7 @@ def _derivative_(self, a, z, diff_param=None): from .gamma import gamma from .other import sqrt - return (z**a/(sqrt(pi)*2**a*gamma(a+Integer(3)/Integer(2)))-struve_L(a+1,z)+struve_L(a-1,z))/2 + return (z**a / (sqrt(pi) * 2**a * gamma(a + Integer(3) / Integer(2))) - struve_L(a + 1, z) + struve_L(a - 1, z)) / 2 def _print_latex_(self, a, z): """ @@ -1431,6 +1441,7 @@ def _print_latex_(self, a, z): """ return r"L_{{%s}}({%s})" % (a, z) + struve_L = Function_Struve_L() @@ -1518,6 +1529,7 @@ def _derivative_(self, nu, z, diff_param): else: raise NotImplementedError('derivative with respect to order') + hankel1 = Function_Hankel1() @@ -1605,6 +1617,7 @@ def _derivative_(self, nu, z, diff_param): else: raise NotImplementedError('derivative with respect to order') + hankel2 = Function_Hankel2() @@ -1704,6 +1717,7 @@ def _derivative_(self, n, z, diff_param): else: raise NotImplementedError('derivative with respect to order') + spherical_bessel_J = SphericalBesselJ() @@ -1803,6 +1817,7 @@ def _derivative_(self, n, z, diff_param): else: raise NotImplementedError('derivative with respect to order') + spherical_bessel_Y = SphericalBesselY() @@ -1899,6 +1914,7 @@ def _derivative_(self, n, z, diff_param): else: raise NotImplementedError('derivative with respect to order') + spherical_hankel1 = SphericalHankel1() @@ -2007,6 +2023,7 @@ def _derivative_(self, n, z, diff_param): else: raise NotImplementedError('derivative with respect to order') + spherical_hankel2 = SphericalHankel2() @@ -2053,4 +2070,3 @@ def spherical_bessel_f(F, n, z): return quotient * Fz finally: ctx.prec = prec - From 7db923eba8e39a66672c58be42ecc727043c6581 Mon Sep 17 00:00:00 2001 From: Jonathan Kliem Date: Mon, 11 Oct 2021 09:12:41 +0200 Subject: [PATCH 322/359] compute vertex adjacency matrix from edges --- src/sage/geometry/polyhedron/base.py | 35 +---------- .../combinatorial_polyhedron/base.pyx | 60 +++++++++++++++++++ 2 files changed, 61 insertions(+), 34 deletions(-) diff --git a/src/sage/geometry/polyhedron/base.py b/src/sage/geometry/polyhedron/base.py index 47063568802..80ba3d0f2a4 100644 --- a/src/sage/geometry/polyhedron/base.py +++ b/src/sage/geometry/polyhedron/base.py @@ -469,39 +469,6 @@ def set_adjacent(h1, h2): M.set_immutable() return M - def _vertex_adjacency_matrix(self): - """ - Compute the vertex adjacency matrix in case it has not been - computed during initialization. - - EXAMPLES:: - - sage: p = Polyhedron(vertices=[(0,0),(1,0),(0,1)]) - sage: p._vertex_adjacency_matrix() - [0 1 1] - [1 0 1] - [1 1 0] - """ - # TODO: This implementation computes the whole face lattice, - # which is much more information than necessary. - M = matrix(ZZ, self.n_Vrepresentation(), self.n_Vrepresentation(), 0) - - def set_adjacent(v1, v2): - if v1 is v2: - return - i = v1.index() - j = v2.index() - M[i, j] = 1 - M[j, i] = 1 - - face_lattice = self.face_lattice() - for face in face_lattice: - Vrep = face.ambient_Vrepresentation() - if len(Vrep) == 2: - set_adjacent(Vrep[0], Vrep[1]) - M.set_immutable() - return M - def _delete(self): """ Delete this polyhedron. @@ -2785,7 +2752,7 @@ def vertex_adjacency_matrix(self): sage: P.adjacency_matrix().is_immutable() True """ - return self._vertex_adjacency_matrix() + return self.combinatorial_polyhedron().vertex_adjacency_matrix() adjacency_matrix = vertex_adjacency_matrix diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx b/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx index dd1a2ba54d7..f024355796c 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx @@ -1245,6 +1245,66 @@ cdef class CombinatorialPolyhedron(SageObject): graph = vertex_graph + @cached_method + def vertex_adjacency_matrix(self): + """ + Return the binary matrix of vertex adjacencies. + + .. SEEALSO:: + + :meth:`~sage.geometry.polyhedron.base.Polyhedron_base.vertex_adjacency_matrix`. + + EXAMPLES:: + + sage: P = polytopes.cube() + sage: C = P.combinatorial_polyhedron() + sage: C.vertex_adjacency_matrix() + [0 1 0 1 0 1 0 0] + [1 0 1 0 0 0 1 0] + [0 1 0 1 0 0 0 1] + [1 0 1 0 1 0 0 0] + [0 0 0 1 0 1 0 1] + [1 0 0 0 1 0 1 0] + [0 1 0 0 0 1 0 1] + [0 0 1 0 1 0 1 0] + + TESTS:: + + sage: CombinatorialPolyhedron(-1).vertex_adjacency_matrix() + [] + sage: CombinatorialPolyhedron(0).vertex_adjacency_matrix() + [0] + sage: polytopes.cube().vertex_adjacency_matrix().is_immutable() + True + """ + from sage.rings.all import ZZ + from sage.matrix.constructor import matrix + cdef Matrix_integer_dense adjacency_matrix = matrix( + ZZ, self.n_Vrepresentation(), self.n_Vrepresentation(), 0) + + if self._edges is NULL: + # compute the edges. + if not self.is_bounded(): + self._compute_edges(dual=False) + elif self.n_Vrepresentation() > self.n_facets()*self.n_facets(): + # This is a wild estimate + # that in this case it is better not to use the dual. + self._compute_edges(dual=False) + else: + # In most bounded cases, one should use the dual. + self._compute_edges(dual=True) + if self._edges is NULL: + raise ValueError('could not determine edges') + + cdef size_t i, a, b + for i in range(self._n_edges): + a = self._get_edge(self._edges, i, 0) + b = self._get_edge(self._edges, i, 1) + adjacency_matrix.set_unsafe_si(a, b, 1) + adjacency_matrix.set_unsafe_si(b, a, 1) + adjacency_matrix.set_immutable() + return adjacency_matrix + def edge_graph(self, names=True): r""" Return the edge graph. From 21a6c945088d0b4467e2a02d0028743f2ca402c2 Mon Sep 17 00:00:00 2001 From: Jonathan Kliem Date: Mon, 11 Oct 2021 09:30:14 +0200 Subject: [PATCH 323/359] remove code duplications --- .../combinatorial_polyhedron/base.pxd | 2 +- .../combinatorial_polyhedron/base.pyx | 75 ++++++++----------- 2 files changed, 34 insertions(+), 43 deletions(-) diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pxd b/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pxd index 4fc293961c5..2d88b7c7496 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pxd +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pxd @@ -71,7 +71,7 @@ cdef class CombinatorialPolyhedron(SageObject): cdef inline int _compute_ridges(self, dual) except -1: return self._compute_edges_or_ridges(dual, False) - cdef int _compute_edges_or_ridges(self, bint dual, bint do_edges) except -1 + cdef int _compute_edges_or_ridges(self, int dual, bint do_edges) except -1 cdef size_t _compute_edges_or_ridges_with_iterator( self, FaceIterator face_iter, const bint do_atom_rep, const bint do_f_vector, size_t ***edges_pt, size_t *counter_pt, size_t *current_length_pt, diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx b/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx index f024355796c..9cff71d08b7 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx @@ -1183,19 +1183,7 @@ cdef class CombinatorialPolyhedron(SageObject): ('a', 'c'), ('a', 'b')) """ - if self._edges is NULL: - # compute the edges. - if not self.is_bounded(): - self._compute_edges(dual=False) - elif self.n_Vrepresentation() > self.n_facets()*self.n_facets(): - # This is a wild estimate - # that in this case it is better not to use the dual. - self._compute_edges(dual=False) - else: - # In most bounded cases, one should use the dual. - self._compute_edges(dual=True) - if self._edges is NULL: - raise ValueError('could not determine edges') + self._compute_edges(-1) # Mapping the indices of the Vrep to the names, if requested. if self.Vrep() is not None and names is True: @@ -1281,22 +1269,9 @@ cdef class CombinatorialPolyhedron(SageObject): from sage.matrix.constructor import matrix cdef Matrix_integer_dense adjacency_matrix = matrix( ZZ, self.n_Vrepresentation(), self.n_Vrepresentation(), 0) - - if self._edges is NULL: - # compute the edges. - if not self.is_bounded(): - self._compute_edges(dual=False) - elif self.n_Vrepresentation() > self.n_facets()*self.n_facets(): - # This is a wild estimate - # that in this case it is better not to use the dual. - self._compute_edges(dual=False) - else: - # In most bounded cases, one should use the dual. - self._compute_edges(dual=True) - if self._edges is NULL: - raise ValueError('could not determine edges') - cdef size_t i, a, b + + self._compute_edges(-1) for i in range(self._n_edges): a = self._get_edge(self._edges, i, 0) b = self._get_edge(self._edges, i, 1) @@ -1429,19 +1404,7 @@ cdef class CombinatorialPolyhedron(SageObject): from sage.misc.superseded import deprecation deprecation(31834, "the keyword ``add_equalities`` is deprecated; use ``add_equations``", 3) add_equations = True - if self._ridges is NULL: - # compute the ridges. - if not self.is_bounded(): - self._compute_ridges(dual=False) - elif self.n_Vrepresentation()*self.n_Vrepresentation() < self.n_facets(): - # This is a wild estimate - # that in this case it is better to use the dual. - self._compute_ridges(dual=True) - else: - # In most bounded cases, one should not use the dual. - self._compute_ridges(dual=False) - if self._ridges is NULL: - raise ValueError('could not determine ridges') + self._compute_ridges(-1) n_ridges = self._n_ridges # Mapping the indices of the Vepr to the names, if requested. @@ -3267,11 +3230,12 @@ cdef class CombinatorialPolyhedron(SageObject): self._f_vector = tuple(smallInteger(f_vector[i]) for i in range(dim+2)) - cdef int _compute_edges_or_ridges(self, bint dual, bint do_edges) except -1: + cdef int _compute_edges_or_ridges(self, int dual, bint do_edges) except -1: r""" Compute the edges of the polyhedron if ``edges`` else the ridges. If ``dual``, use the face iterator in dual mode, else in non-dual. + If ``dual`` is ``-1`` determine this automatically. If the ``f_vector`` is unkown computes it as well if computing the edges in non-dual mode or the ridges in dual-mode. @@ -3281,6 +3245,27 @@ cdef class CombinatorialPolyhedron(SageObject): if (self._edges is not NULL and do_edges) or (self._ridges is not NULL and not do_edges): return 0 # There is no need to recompute. + if dual == -1: + # Determine whether to use dual mode or not. + if not self.is_bounded(): + dual = 0 + elif do_edges: + if self.n_Vrepresentation() > self.n_facets()*self.n_facets(): + # This is a wild estimate + # that in this case it is better not to use the dual. + dual = 0 + else: + # In most bounded cases, one should use the dual. + dual = 1 + else: + if self.n_Vrepresentation()*self.n_Vrepresentation() < self.n_facets(): + # This is a wild estimate + # that in this case it is better to use the dual. + dual = 1 + else: + # In most bounded cases, one should not use the dual. + dual = 0 + cdef MemoryAllocator mem = MemoryAllocator() cdef FaceIterator face_iter cdef int dim = self.dimension() @@ -3355,6 +3340,12 @@ cdef class CombinatorialPolyhedron(SageObject): self._mem_tuple += (mem,) sig_unblock() + if do_edges and self._edges is NULL: + raise ValueError('could not determine edges') + elif not do_edges and self._ridges is NULL: + raise ValueError('could not determine ridges') + + cdef size_t _compute_edges_or_ridges_with_iterator( self, FaceIterator face_iter, const bint do_atom_rep, const bint do_f_vector, size_t ***edges_pt, size_t *counter_pt, size_t *current_length_pt, From 595c41cdc28bb30281849adadfd64389ae11fe1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Mon, 11 Oct 2021 09:49:29 +0200 Subject: [PATCH 324/359] replace + Auch eine Funktion (siehe unten) ist ein symbolischer Ausdruck:: sage: f(x) = x + 1 sage: type(f) - + Benutzen wir jedoch eine Variable, um etwas zu speichern und nicht als symbolischen Parameter, so ist ein Ausdruck, welcher sie enthält, nicht mehr ein symbolischer @@ -329,7 +329,7 @@ Ausdruck:: sage: x = 3 sage: type(x*2) - + Terme können auch in Variablen gespeichert werden. Dazu benutzen wir wie bei Zahlenwerten den Operator ``=`` für die Zuordnung:: diff --git a/src/doc/de/tutorial/interactive_shell.rst b/src/doc/de/tutorial/interactive_shell.rst index 048f1c6f0ac..b62b865330f 100644 --- a/src/doc/de/tutorial/interactive_shell.rst +++ b/src/doc/de/tutorial/interactive_shell.rst @@ -410,7 +410,7 @@ Zum Beispiel: Automatic pdb calling has been turned ON sage: EllipticCurve([1,infinity]) --------------------------------------------------------------------------- - Traceback (most recent call last) + Traceback (most recent call last) ... ipdb> @@ -519,7 +519,7 @@ Funktionsnamen ein ``?`` an, um die Dokumentation dazu aufzurufen. sage: V = QQ^3 sage: V.coordinates? Type: instancemethod - Base Class: + Base Class: String Form: Namespace: Interactive diff --git a/src/doc/de/tutorial/interfaces.rst b/src/doc/de/tutorial/interfaces.rst index 68e4ea2994f..edb4f383363 100644 --- a/src/doc/de/tutorial/interfaces.rst +++ b/src/doc/de/tutorial/interfaces.rst @@ -61,7 +61,7 @@ mehr referenziert wird. Die Objekte haben außerdem verschiedene Typen: sage: type(gp('znprimroot(10007)')) sage: type(pari('znprimroot(10007)')) - + Welche Variante sollten Sie also nutzen? Das kommt darauf an was Sie tun. Die GP-Schnittstelle kann alles was ein normales @@ -98,7 +98,7 @@ Zuerst erstellen wir eine PARI-Liste aus einer Python-Liste. sage: v [1, 2, 3, 4, 5] sage: type(v) - + Jedes PARI-Objekt ist vom Typ ``Gen``. Den PARI Typ des vorliegenden Objekts können Sie mit der ``type`` Unterfunktion herausfinden. diff --git a/src/doc/de/tutorial/programming.rst b/src/doc/de/tutorial/programming.rst index 236fb8e9c29..7d86c01e30b 100644 --- a/src/doc/de/tutorial/programming.rst +++ b/src/doc/de/tutorial/programming.rst @@ -396,7 +396,7 @@ Folge haben einen gemeinsamen Obertyp, der das Folgenuniversum genannt wird. sage: type(v) sage: type(v[1]) - + sage: v.universe() Rational Field sage: v.is_immutable() diff --git a/src/doc/de/tutorial/tour_assignment.rst b/src/doc/de/tutorial/tour_assignment.rst index e406ab4621c..2bc72cae3e1 100644 --- a/src/doc/de/tutorial/tour_assignment.rst +++ b/src/doc/de/tutorial/tour_assignment.rst @@ -91,10 +91,10 @@ beliebigen Python-Typs innerhalb eines Sichtbarkeitsbereich aufnehmen. sage: a = 5 # a ist eine ganze Zahl sage: type(a) - + sage: a = 5/3 # jetzt ist a eine rationale Zahl sage: type(a) - + sage: a = 'hello' # jetzt ist a ein String sage: type(a) <... 'str'> diff --git a/src/doc/de/tutorial/tour_functions.rst b/src/doc/de/tutorial/tour_functions.rst index 501a2f9dbd9..18cbbf00ced 100644 --- a/src/doc/de/tutorial/tour_functions.rst +++ b/src/doc/de/tutorial/tour_functions.rst @@ -61,7 +61,7 @@ können geplottet, differenziert und integriert werden. sage: Dg(3) 6 sage: type(g) - + sage: plot(g, 0, 2) Graphics object consisting of 1 graphics primitive @@ -78,7 +78,7 @@ Erläuterung zu erhalten. sage: g(x) x^2 sage: type(g(x)) - + sage: g(x).derivative() 2*x sage: plot(g(x), 0, 2) @@ -95,7 +95,7 @@ werden. sage: plot(sin, 0, 2) Graphics object consisting of 1 graphics primitive sage: type(sin(x)) - + sage: plot(sin(x), 0, 2) Graphics object consisting of 1 graphics primitive @@ -143,7 +143,7 @@ wird, was wiederum bedeutet, dass ``x<2`` ausgewertet wird. :: sage: type(x<2) - + Wenn eine symbolische Gleichung ausgewertet wird, wie in der Definition von ``h``, wird falls sie nicht offensichtlicherweise wahr @@ -176,9 +176,9 @@ Das Problem: ``g(3)``, zum Beispiel, gibt folgenden Fehler zurück: :: sage: type(f) - + sage: type(g) - + ``g`` ist keine Funktion, es ist eine Konstante, hat also keine zugehörigen Variablen, und man kann in sie nichts einsetzen. @@ -196,7 +196,7 @@ Die Lösung: Es gibt mehrere Möglichkeiten. sage: g(3) 1 sage: type(g) - + - Oder mit der ursprünglichen Definition von ``f``, definieren Sie ``g`` als symbolischen Ausdruck. @@ -210,7 +210,7 @@ Die Lösung: Es gibt mehrere Möglichkeiten. sage: g(3) 1 sage: type(g) - + - Oder mit den ursprünglichen Definitionen von ``f`` and ``g``, geben Sie die Variable an, in diese Sie den Wert einsetzen. diff --git a/src/doc/en/constructions/interface_issues.rst b/src/doc/en/constructions/interface_issues.rst index e6cb1c30da6..efe93c7edbc 100644 --- a/src/doc/en/constructions/interface_issues.rst +++ b/src/doc/en/constructions/interface_issues.rst @@ -382,7 +382,7 @@ help interface to find the file name: sage: PermutationGroup.center? Type: instancemethod - Base Class: + Base Class: String Form: Namespace: Interactive File: /home/wdj/sage/local/lib/python2.4/site-packages/sage/groups/permgroup.py diff --git a/src/doc/en/developer/coding_in_python.rst b/src/doc/en/developer/coding_in_python.rst index 1d8b7c1d3bf..09b7c831b4b 100644 --- a/src/doc/en/developer/coding_in_python.rst +++ b/src/doc/en/developer/coding_in_python.rst @@ -261,7 +261,7 @@ replacements are made: <... 'int'> sage: b = 393939 sage: type(b) - + sage: a == b True diff --git a/src/doc/en/prep/Programming.rst b/src/doc/en/prep/Programming.rst index d74ed1e9f42..f495c872f48 100644 --- a/src/doc/en/prep/Programming.rst +++ b/src/doc/en/prep/Programming.rst @@ -524,12 +524,12 @@ Luckily, it's possible to restore symbolic constants. :: sage: type(e) - + :: sage: type(pi) - + Variables are another thing to keep in mind. As mentioned briefly in earlier tutorials, in order to maintain maximum flexibility while not @@ -539,7 +539,7 @@ nothing else. :: sage: type(x) - + :: diff --git a/src/doc/en/prep/Quickstarts/Linear-Algebra.rst b/src/doc/en/prep/Quickstarts/Linear-Algebra.rst index 666e4b48765..58cb44edd3c 100644 --- a/src/doc/en/prep/Quickstarts/Linear-Algebra.rst +++ b/src/doc/en/prep/Quickstarts/Linear-Algebra.rst @@ -192,7 +192,7 @@ for our purposes. sage: type( ring_vec ) sage: type( field_vec ) - + Left\-Handed or Right\-handed? ------------------------------- diff --git a/src/doc/en/prep/Quickstarts/Number-Theory.rst b/src/doc/en/prep/Quickstarts/Number-Theory.rst index 5b1f73d8138..aa46ee12a86 100644 --- a/src/doc/en/prep/Quickstarts/Number-Theory.rst +++ b/src/doc/en/prep/Quickstarts/Number-Theory.rst @@ -31,7 +31,7 @@ For instance, we can create a number in :math:`\ZZ/11\ZZ`. The sage: a = mod(2,11); a; type(a); a^10; a^1000000 2 - + 1 1 diff --git a/src/doc/en/reference/coercion/index.rst b/src/doc/en/reference/coercion/index.rst index 04666bda51b..d8d7c2ade79 100644 --- a/src/doc/en/reference/coercion/index.rst +++ b/src/doc/en/reference/coercion/index.rst @@ -74,9 +74,9 @@ There is an important distinction between Parents and types:: sage: a = GF(5).random_element() sage: b = GF(7).random_element() sage: type(a) - + sage: type(b) - + sage: type(a) == type(b) True sage: parent(a) diff --git a/src/doc/en/thematic_tutorials/sandpile.rst b/src/doc/en/thematic_tutorials/sandpile.rst index 7dd7091415a..282889a9f15 100644 --- a/src/doc/en/thematic_tutorials/sandpile.rst +++ b/src/doc/en/thematic_tutorials/sandpile.rst @@ -5002,7 +5002,7 @@ Documentation for each method is available through the Sage online help system: :: sage: SandpileConfig.fire_vertex? - Base Class: + Base Class: String Form: Namespace: Interactive File: /usr/local/sage-4.7/local/lib/python2.6/site-packages/sage/sandpiles/sandpile.py diff --git a/src/doc/en/thematic_tutorials/tutorial-objects-and-classes.rst b/src/doc/en/thematic_tutorials/tutorial-objects-and-classes.rst index cbaff12746b..a295508e0ab 100644 --- a/src/doc/en/thematic_tutorials/tutorial-objects-and-classes.rst +++ b/src/doc/en/thematic_tutorials/tutorial-objects-and-classes.rst @@ -314,7 +314,7 @@ http://docs.python.org/library/ for a complete list. :: sage: e = Integer(9) sage: type(e) - + sage: e.__dict__ Traceback (most recent call last): ... @@ -322,7 +322,7 @@ http://docs.python.org/library/ for a complete list. :: sage: id4 = SymmetricGroup(4).one() sage: type(id4) - + sage: id4.__dict__ Traceback (most recent call last): ... diff --git a/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_cartesian.rst b/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_cartesian.rst index d7eed347d92..978aa129395 100644 --- a/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_cartesian.rst +++ b/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_cartesian.rst @@ -38,7 +38,7 @@ Thanks to the notation ```` in the above declaration, the coordinates sage: z is E.cartesian_coordinates()[3] True sage: type(z) - + Besides, `\mathbb{E}^3` is endowed with the *orthonormal vector frame* `(e_x, e_y, e_z)` associated with Cartesian coordinates:: diff --git a/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_change.rst b/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_change.rst index 188b65ed596..d7164e7c363 100644 --- a/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_change.rst +++ b/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_change.rst @@ -59,7 +59,7 @@ type ``x, y, z = var('x y z')``; they are immediately available:: sage: y is cartesian[2] True sage: type(y) - + Each of the Cartesian coordinates spans the entire real line:: diff --git a/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_curvilinear.rst b/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_curvilinear.rst index a244b427839..96617135972 100644 --- a/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_curvilinear.rst +++ b/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_curvilinear.rst @@ -36,7 +36,7 @@ type ``r, th, ph = var('r th ph')``):: sage: (r, th, ph) == E.spherical_coordinates()[:] True sage: type(r) - + Moreover, the coordinate LaTeX symbols are already set:: diff --git a/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_plane.rst b/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_plane.rst index 0286c70c467..d5e35cc552d 100644 --- a/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_plane.rst +++ b/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_plane.rst @@ -32,7 +32,7 @@ the Cartesian coordinates (there is no need to declare them via :func:`var`, i.e. to type ``x, y = var('x y')``):: sage: type(y) - + Instead of using the variables ``x`` and ``y``, one may also access to the coordinates by their indices in the chart of Cartesian coordinates:: diff --git a/src/doc/en/tutorial/interactive_shell.rst b/src/doc/en/tutorial/interactive_shell.rst index 564de65aa24..68c9a17f17a 100644 --- a/src/doc/en/tutorial/interactive_shell.rst +++ b/src/doc/en/tutorial/interactive_shell.rst @@ -488,7 +488,7 @@ execution stack. For example, Automatic pdb calling has been turned ON sage: EllipticCurve([1,infinity]) --------------------------------------------------------------------------- - Traceback (most recent call last) + Traceback (most recent call last) ... ipdb> @@ -597,7 +597,7 @@ followed by ? for the documentation for that function. sage: V = QQ^3 sage: V.coordinates? Type: instancemethod - Base Class: + Base Class: String Form: Namespace: Interactive diff --git a/src/doc/en/tutorial/interfaces.rst b/src/doc/en/tutorial/interfaces.rst index 4ddbb146db3..b0e55345669 100644 --- a/src/doc/en/tutorial/interfaces.rst +++ b/src/doc/en/tutorial/interfaces.rst @@ -64,7 +64,7 @@ objects have different types: sage: type(gp('znprimroot(10007)')) sage: type(pari('znprimroot(10007)')) - + So which should you use? It depends on what you're doing. The GP interface can do absolutely anything you could do in the usual @@ -100,7 +100,7 @@ First we create a PARI list from a Python list. sage: v [1, 2, 3, 4, 5] sage: type(v) - + Every PARI object is of type ``Gen``. The PARI type of the underlying object can be obtained using the ``type`` member diff --git a/src/doc/en/tutorial/programming.rst b/src/doc/en/tutorial/programming.rst index e7ce161cc4f..56ecb369559 100644 --- a/src/doc/en/tutorial/programming.rst +++ b/src/doc/en/tutorial/programming.rst @@ -378,7 +378,7 @@ a common parent, called the sequences universe. sage: type(v) sage: type(v[1]) - + sage: v.universe() Rational Field sage: v.is_immutable() diff --git a/src/doc/en/tutorial/tour_assignment.rst b/src/doc/en/tutorial/tour_assignment.rst index b7194a7d81d..6d863b15893 100644 --- a/src/doc/en/tutorial/tour_assignment.rst +++ b/src/doc/en/tutorial/tour_assignment.rst @@ -89,10 +89,10 @@ hold values of any Python type within a given scope: sage: a = 5 # a is an integer sage: type(a) - + sage: a = 5/3 # now a is a rational number sage: type(a) - + sage: a = 'hello' # now a is a string sage: type(a) <... 'str'> diff --git a/src/doc/en/tutorial/tour_coercion.rst b/src/doc/en/tutorial/tour_coercion.rst index 0ee15f3c808..65b28fa0968 100644 --- a/src/doc/en/tutorial/tour_coercion.rst +++ b/src/doc/en/tutorial/tour_coercion.rst @@ -55,9 +55,9 @@ providing different implementations of the same mathematical structure sage: Q. = PolynomialRing(ZZ, sparse=True) sage: R. = PolynomialRing(ZZ, implementation='NTL') sage: type(a); type(b); type(c) - + - + That poses two problems: On the one hand, if one has elements that are two instances of the same class, then one may expect that their diff --git a/src/doc/en/tutorial/tour_functions.rst b/src/doc/en/tutorial/tour_functions.rst index 6c006f5180a..f00991813c2 100644 --- a/src/doc/en/tutorial/tour_functions.rst +++ b/src/doc/en/tutorial/tour_functions.rst @@ -59,7 +59,7 @@ differentiated, and integrated. sage: Dg(3) 6 sage: type(g) - + sage: plot(g, 0, 2) Graphics object consisting of 1 graphics primitive @@ -75,7 +75,7 @@ illustration. sage: g(x) x^2 sage: type(g(x)) - + sage: g(x).derivative() 2*x sage: plot(g(x), 0, 2) @@ -91,7 +91,7 @@ and with a little help, differentiated, and integrated. sage: plot(sin, 0, 2) Graphics object consisting of 1 graphics primitive sage: type(sin(x)) - + sage: plot(sin(x), 0, 2) Graphics object consisting of 1 graphics primitive @@ -174,9 +174,9 @@ The problem: ``g(3)``, for example, returns an error, saying :: sage: type(f) - + sage: type(g) - + ``g`` is not a function, it's a constant, so it has no variables associated to it, and you can't plug anything into it. @@ -194,7 +194,7 @@ The solution: there are several options. sage: g(3) 1 sage: type(g) - + - Or with ``f`` as defined originally, define ``g`` to be a symbolic expression. @@ -208,7 +208,7 @@ The solution: there are several options. sage: g(3) 1 sage: type(g) - + - Or with ``f`` and ``g`` as defined originally, specify the variable for which you are substituting. diff --git a/src/doc/es/tutorial/tour_assignment.rst b/src/doc/es/tutorial/tour_assignment.rst index d5144f74e29..12297921cc2 100644 --- a/src/doc/es/tutorial/tour_assignment.rst +++ b/src/doc/es/tutorial/tour_assignment.rst @@ -88,10 +88,10 @@ contener valores de cualquier tipo Python dentro de un ámbito dado: sage: a = 5 # a es un entero sage: type(a) - + sage: a = 5/3 # ahora es un número racional sage: type(a) - + sage: a = 'hello' # ahora es una cadena sage: type(a) <... 'str'> diff --git a/src/doc/fr/tutorial/interactive_shell.rst b/src/doc/fr/tutorial/interactive_shell.rst index 3f28f110c3a..43cdd051014 100644 --- a/src/doc/fr/tutorial/interactive_shell.rst +++ b/src/doc/fr/tutorial/interactive_shell.rst @@ -495,7 +495,7 @@ pile d'exécution. Par exemple : Automatic pdb calling has been turned ON sage: EllipticCurve([1,infinity]) --------------------------------------------------------------------------- - Traceback (most recent call last) + Traceback (most recent call last) ... ipdb> @@ -604,7 +604,7 @@ d'une fonction, tapez son nom suivi d'un point d'interrogation. sage: V = QQ^3 sage: V.coordinates? Type: instancemethod - Base Class: + Base Class: String Form: Namespace: Interactive diff --git a/src/doc/fr/tutorial/interfaces.rst b/src/doc/fr/tutorial/interfaces.rst index 647189f65d7..1cd662f3083 100644 --- a/src/doc/fr/tutorial/interfaces.rst +++ b/src/doc/fr/tutorial/interfaces.rst @@ -64,7 +64,7 @@ commandes sont de types différents : sage: type(gp('znprimroot(10007)')) sage: type(pari('znprimroot(10007)')) - + Alors, laquelle des interfaces utiliser ? Tout dépend de ce que vous cherchez à faire. L'interface GP permet de faire absolument tout ce que @@ -102,7 +102,7 @@ Commençons par créer une liste PARI à partir d'une liste Python. sage: v [1, 2, 3, 4, 5] sage: type(v) - + En Sage, les objets PARI sont de type ``Gen``. Le type PARI de l'objet sous-jacent est donné par la méthode ``type``. diff --git a/src/doc/fr/tutorial/programming.rst b/src/doc/fr/tutorial/programming.rst index 4e1b372a070..69b4182508e 100644 --- a/src/doc/fr/tutorial/programming.rst +++ b/src/doc/fr/tutorial/programming.rst @@ -391,7 +391,7 @@ l'univers de la séquence. sage: type(v) sage: type(v[1]) - + sage: v.universe() Rational Field sage: v.is_immutable() diff --git a/src/doc/fr/tutorial/tour_assignment.rst b/src/doc/fr/tutorial/tour_assignment.rst index 70e0767586a..6607ebc5a62 100644 --- a/src/doc/fr/tutorial/tour_assignment.rst +++ b/src/doc/fr/tutorial/tour_assignment.rst @@ -93,10 +93,10 @@ sein d'une même portée : sage: a = 5 # a est un entier sage: type(a) - + sage: a = 5/3 # a est maintenant un rationnel... sage: type(a) - + sage: a = 'hello' # ...et maintenant une chaîne sage: type(a) <... 'str'> diff --git a/src/doc/fr/tutorial/tour_coercion.rst b/src/doc/fr/tutorial/tour_coercion.rst index 72846896985..9d666684313 100644 --- a/src/doc/fr/tutorial/tour_coercion.rst +++ b/src/doc/fr/tutorial/tour_coercion.rst @@ -57,9 +57,9 @@ contre matrices creuses par exemple). sage: Q. = PolynomialRing(ZZ, sparse=True) sage: R. = PolynomialRing(ZZ, implementation='NTL') sage: type(a); type(b); type(c) - + - + Deux problèmes se posent alors. D'une part, si deux éléments sont instances de la même classe, on s'attend à ce que leur méthode ``__add__`` soit capable de diff --git a/src/doc/fr/tutorial/tour_functions.rst b/src/doc/fr/tutorial/tour_functions.rst index 4465b92413c..cc88b77a071 100644 --- a/src/doc/fr/tutorial/tour_functions.rst +++ b/src/doc/fr/tutorial/tour_functions.rst @@ -59,7 +59,7 @@ et que l'on peut aussi dériver ou intégrer symboliquement :: sage: Dg(3) 6 sage: type(g) - + sage: plot(g, 0, 2) Graphics object consisting of 1 graphics primitive @@ -76,7 +76,7 @@ illustrées dans le point 5 ci-dessous. sage: g(x) x^2 sage: type(g(x)) - + sage: g(x).derivative() 2*x sage: plot(g(x), 0, 2) @@ -90,7 +90,7 @@ servir à tracer des courbes, et, indirectement, être dérivées ou intégrées sage: plot(sin, 0, 2) Graphics object consisting of 1 graphics primitive sage: type(sin(x)) - + sage: plot(sin(x), 0, 2) Graphics object consisting of 1 graphics primitive @@ -132,7 +132,7 @@ est donc évaluée. :: sage: type(x < 2) - + Or, l'évaluation d'une inégalité symbolique renvoie ``False`` quand la condition n'est pas clairement vraie. Ainsi, ``h(x)`` s'évalue en @@ -167,9 +167,9 @@ the number of arguments must be less than or equal to 0 ». :: sage: type(f) - + sage: type(g) - + En effet, ``g`` n'est pas une fonction, mais une constante, sans variable en laquelle on peut l'évaluer. @@ -185,7 +185,7 @@ Solution : il y a plusieurs possibilités. sage: g(3) 1 sage: type(g) - + - Ou, sans changer la définition de ``f``, définir ``g`` comme une expression symbolique fonctionnelle :: @@ -197,7 +197,7 @@ Solution : il y a plusieurs possibilités. sage: g(3) 1 sage: type(g) - + - Ou encore, avec ``f`` et ``g`` définies comme dans l'exemple de départ, donner explicitement la variable à remplacer par sa valeur :: diff --git a/src/doc/ja/tutorial/interactive_shell.rst b/src/doc/ja/tutorial/interactive_shell.rst index eae3aeaaafc..452914bd12a 100644 --- a/src/doc/ja/tutorial/interactive_shell.rst +++ b/src/doc/ja/tutorial/interactive_shell.rst @@ -442,7 +442,7 @@ IPythonのクイック レファレンスガイドを見たければ, ``%quick Automatic pdb calling has been turned ON sage: EllipticCurve([1,infinity]) --------------------------------------------------------------------------- - Traceback (most recent call last) + Traceback (most recent call last) ... ipdb> @@ -542,7 +542,7 @@ Sageの特長の一つは,総合的なヘルプ機能の装備である. sage: V = QQ^3 sage: V.coordinates? Type: instancemethod - Base Class: + Base Class: String Form: Namespace: Interactive diff --git a/src/doc/ja/tutorial/interfaces.rst b/src/doc/ja/tutorial/interfaces.rst index 1254d297be7..9c16b2eba08 100644 --- a/src/doc/ja/tutorial/interfaces.rst +++ b/src/doc/ja/tutorial/interfaces.rst @@ -55,7 +55,7 @@ GPは送られて来た文字列を評価し,結果を変数に格納する( sage: type(gp('znprimroot(10007)')) sage: type(pari('znprimroot(10007)')) - + では,どちらの方法を選ぶべきだろうか? 答は目的による、としか言えない. @@ -84,7 +84,7 @@ PARI Cライブラリ インターフェイスについて言うと,こちら sage: v [1, 2, 3, 4, 5] sage: type(v) - + PARIのオブジェクトは全て ``Gen`` 型になる. diff --git a/src/doc/ja/tutorial/programming.rst b/src/doc/ja/tutorial/programming.rst index 245dee89b3f..9edd5f80a6d 100644 --- a/src/doc/ja/tutorial/programming.rst +++ b/src/doc/ja/tutorial/programming.rst @@ -357,7 +357,7 @@ Sageで使われる第三のリスト類似データ型が,シーケンスで sage: type(v) sage: type(v[1]) - + sage: v.universe() Rational Field sage: v.is_immutable() diff --git a/src/doc/ja/tutorial/tour_assignment.rst b/src/doc/ja/tutorial/tour_assignment.rst index be04ba7f6f1..ea8673689cc 100644 --- a/src/doc/ja/tutorial/tour_assignment.rst +++ b/src/doc/ja/tutorial/tour_assignment.rst @@ -79,10 +79,10 @@ Pythonのデータはダイナミックに型付けされ,変数を通して sage: a = 5 # aは整数 sage: type(a) - + sage: a = 5/3 # aは有理数になった sage: type(a) - + sage: a = 'hello' # ここでaは文字列 sage: type(a) <... 'str'> diff --git a/src/doc/ja/tutorial/tour_coercion.rst b/src/doc/ja/tutorial/tour_coercion.rst index 15c3ce07c3d..fd125a81987 100644 --- a/src/doc/ja/tutorial/tour_coercion.rst +++ b/src/doc/ja/tutorial/tour_coercion.rst @@ -42,9 +42,9 @@ Pythonは(ダイナミックではあっても)強い型付けがなされる言 sage: Q. = PolynomialRing(ZZ, sparse=True) sage: R. = PolynomialRing(ZZ, implementation='NTL') sage: type(a); type(b); type(c) - + - + 以上から,解決すべき問題は二系統あることが分る. diff --git a/src/doc/ja/tutorial/tour_functions.rst b/src/doc/ja/tutorial/tour_functions.rst index 159ffca4c51..2c210a9da7d 100644 --- a/src/doc/ja/tutorial/tour_functions.rst +++ b/src/doc/ja/tutorial/tour_functions.rst @@ -59,7 +59,7 @@ Sageで「関数」と呼ばれるべきものを定義する方法は何通り sage: Dg(3) 6 sage: type(g) - + sage: plot(g, 0, 2) Graphics object consisting of 1 graphics primitive @@ -74,7 +74,7 @@ Sageで「関数」と呼ばれるべきものを定義する方法は何通り sage: g(x) x^2 sage: type(g(x)) - + sage: g(x).derivative() 2*x sage: plot(g(x), 0, 2) @@ -92,7 +92,7 @@ Sageで「関数」と呼ばれるべきものを定義する方法は何通り sage: plot(sin, 0, 2) Graphics object consisting of 1 graphics primitive sage: type(sin(x)) - + sage: plot(sin(x), 0, 2) Graphics object consisting of 1 graphics primitive @@ -142,7 +142,7 @@ Sageで「関数」と呼ばれるべきものを定義する方法は何通り :: sage: type(x<2) - + シンボリック式が評価される際, ``h`` の定義の場合と同じように,その式が明らかに真でないかぎり戻り値は偽になる. @@ -181,9 +181,9 @@ Sageで「関数」と呼ばれるべきものを定義する方法は何通り :: sage: type(f) - + sage: type(g) - + ``g`` は関数ではなく定数になっているので,変数を持たないから何も値を受けつけない. @@ -202,7 +202,7 @@ Sageで「関数」と呼ばれるべきものを定義する方法は何通り sage: g(3) 1 sage: type(g) - + - または ``f`` の定義は元のまま ``g`` をシンボリック表式として定義する. @@ -216,7 +216,7 @@ Sageで「関数」と呼ばれるべきものを定義する方法は何通り sage: g(3) 1 sage: type(g) - + - または ``f`` と ``g`` の定義は元のまま,代入すべき変数を特定する. diff --git a/src/doc/pt/tutorial/interactive_shell.rst b/src/doc/pt/tutorial/interactive_shell.rst index cba3f29cfcd..d2f9e24fc4a 100644 --- a/src/doc/pt/tutorial/interactive_shell.rst +++ b/src/doc/pt/tutorial/interactive_shell.rst @@ -475,7 +475,7 @@ cima e para baixo. Por exemplo, Automatic pdb calling has been turned ON sage: EllipticCurve([1,infinity]) --------------------------------------------------------------------------- - Traceback (most recent call last) + Traceback (most recent call last) ... ipdb> @@ -582,7 +582,7 @@ seguido de ? para ver informações sobre a função. sage: V = QQ^3 sage: V.coordinates? Type: instancemethod - Base Class: + Base Class: String Form: Namespace: Interactive diff --git a/src/doc/pt/tutorial/interfaces.rst b/src/doc/pt/tutorial/interfaces.rst index 8515f18a74c..3c080cc3cfc 100644 --- a/src/doc/pt/tutorial/interfaces.rst +++ b/src/doc/pt/tutorial/interfaces.rst @@ -63,7 +63,7 @@ diferentes: sage: type(gp('znprimroot(10007)')) sage: type(pari('znprimroot(10007)')) - + Então qual eu devo usar? Depende do que você está fazendo. A interface GP pode fazer absolutamente tudo o que você poderia fazer na linha de @@ -101,7 +101,7 @@ Primeiro criamos uma lista do PARI a partir de uma lista do Python. sage: v [1, 2, 3, 4, 5] sage: type(v) - + Cada objeto do PARI é do tipo ``Gen``. O tipo PARI do objeto subjacente pode ser obtido usando a função ``type``. diff --git a/src/doc/pt/tutorial/programming.rst b/src/doc/pt/tutorial/programming.rst index 7e65233dead..fd082952410 100644 --- a/src/doc/pt/tutorial/programming.rst +++ b/src/doc/pt/tutorial/programming.rst @@ -407,7 +407,7 @@ sequência possuem um parente comum, chamado o universo da sequência. sage: type(v) sage: type(v[1]) - + sage: v.universe() Rational Field sage: v.is_immutable() diff --git a/src/doc/pt/tutorial/tour_assignment.rst b/src/doc/pt/tutorial/tour_assignment.rst index 5ba8651dc07..001856d1349 100644 --- a/src/doc/pt/tutorial/tour_assignment.rst +++ b/src/doc/pt/tutorial/tour_assignment.rst @@ -89,10 +89,10 @@ variável pode possuir valores de qualquer tipo em determinado escopo: sage: a = 5 # a is an integer sage: type(a) - + sage: a = 5/3 # now a is a rational number sage: type(a) - + sage: a = 'hello' # now a is a string sage: type(a) <... 'str'> diff --git a/src/doc/pt/tutorial/tour_functions.rst b/src/doc/pt/tutorial/tour_functions.rst index dc3ebe3fa9c..2a7cac13969 100644 --- a/src/doc/pt/tutorial/tour_functions.rst +++ b/src/doc/pt/tutorial/tour_functions.rst @@ -61,7 +61,7 @@ integradas. sage: Dg(3) 6 sage: type(g) - + sage: plot(g, 0, 2) Graphics object consisting of 1 graphics primitive @@ -77,7 +77,7 @@ embora com algumas ressalvas: veja o item 5 abaixo. sage: g(x) x^2 sage: type(g(x)) - + sage: g(x).derivative() 2*x sage: plot(g(x), 0, 2) @@ -93,7 +93,7 @@ gráfico, e com uma pequena ajuda, diferenciadas e integradas. sage: plot(sin, 0, 2) Graphics object consisting of 1 graphics primitive sage: type(sin(x)) - + sage: plot(sin(x), 0, 2) Graphics object consisting of 1 graphics primitive @@ -140,7 +140,7 @@ na função ``h``, o que significa que ``x<2`` é calculado. :: sage: type(x<2) - + Quando uma equação simbólica é calculada, como na definição de ``h``, se ela não é obviamente verdadeira, então ela retorna False. Logo @@ -173,9 +173,9 @@ number of arguments must be less than or equal to 0." :: sage: type(f) - + sage: type(g) - + ``g`` não é uma função, é uma constante, logo não possui variáveis associadas, e você não pode substituir nenhum valor em ``g``. @@ -193,7 +193,7 @@ Solução: existem vária opções. sage: g(3) 1 sage: type(g) - + - Ou com ``f`` como definida originalmente, defina ``g`` como uma expressão simbólica. @@ -207,7 +207,7 @@ Solução: existem vária opções. sage: g(3) 1 sage: type(g) - + - Ou com ``f`` e ``g`` como definidas originalmente, especifique a variável para a qual você está substituindo. diff --git a/src/doc/ru/tutorial/interactive_shell.rst b/src/doc/ru/tutorial/interactive_shell.rst index 51dffa1c923..62e9b9f694f 100644 --- a/src/doc/ru/tutorial/interactive_shell.rst +++ b/src/doc/ru/tutorial/interactive_shell.rst @@ -392,7 +392,7 @@ Wall time. Однако, если существует существенная Automatic pdb calling has been turned ON sage: EllipticCurve([1,infinity]) --------------------------------------------------------------------------- - Traceback (most recent call last) + Traceback (most recent call last) ... ipdb> @@ -498,7 +498,7 @@ Sage обладает встроенной справочной системой sage: V = QQ^3 sage: V.coordinates? Type: instancemethod - Base Class: + Base Class: String Form: Namespace: Interactive diff --git a/src/doc/ru/tutorial/interfaces.rst b/src/doc/ru/tutorial/interfaces.rst index 2210f9c0a5b..ea84527f478 100644 --- a/src/doc/ru/tutorial/interfaces.rst +++ b/src/doc/ru/tutorial/interfaces.rst @@ -59,7 +59,7 @@ GP, и результат записывается в переменную в GP sage: type(gp('znprimroot(10007)')) sage: type(pari('znprimroot(10007)')) - + Так какой же способ использовать? Это зависит от того, что вы делаете. Интерфейс GP может делать все, что может делать программа GP/PARI, запускаемая @@ -92,7 +92,7 @@ Sage использует С-библиотеку PARI, чтобы поддер sage: v [1, 2, 3, 4, 5] sage: type(v) - + Каждый объект PARI является объектом типа ``Gen``. Тип PARI может быть получен с помощью функции-члена ``type``. diff --git a/src/doc/ru/tutorial/programming.rst b/src/doc/ru/tutorial/programming.rst index e0a58e26071..4550f32717a 100644 --- a/src/doc/ru/tutorial/programming.rst +++ b/src/doc/ru/tutorial/programming.rst @@ -367,7 +367,7 @@ Python, сработает нормально. sage: type(v) sage: type(v[1]) - + sage: v.universe() Rational Field sage: v.is_immutable() diff --git a/src/doc/ru/tutorial/tour_assignment.rst b/src/doc/ru/tutorial/tour_assignment.rst index 7f8612cac9b..9ad9b1d715d 100644 --- a/src/doc/ru/tutorial/tour_assignment.rst +++ b/src/doc/ru/tutorial/tour_assignment.rst @@ -87,10 +87,10 @@ Python имеет динамический контроль типов, так sage: a = 5 # a - целое число sage: type(a) - + sage: a = 5/3 # теперь a - рациональное число sage: type(a) - + sage: a = 'hello' # теперь a - строка sage: type(a) <... 'str'> diff --git a/src/doc/ru/tutorial/tour_functions.rst b/src/doc/ru/tutorial/tour_functions.rst index 6cc4d9c73c2..1f87c843415 100644 --- a/src/doc/ru/tutorial/tour_functions.rst +++ b/src/doc/ru/tutorial/tour_functions.rst @@ -58,7 +58,7 @@ sage: Dg(3) 6 sage: type(g) - + sage: plot(g, 0, 2) Graphics object consisting of 1 graphics primitive @@ -73,7 +73,7 @@ sage: g(x) x^2 sage: type(g(x)) - + sage: g(x).derivative() 2*x sage: plot(g(x), 0, 2) @@ -90,7 +90,7 @@ sage: plot(sin, 0, 2) Graphics object consisting of 1 graphics primitive sage: type(sin(x)) - + sage: plot(sin(x), 0, 2) Graphics object consisting of 1 graphics primitive @@ -135,7 +135,7 @@ :: sage: type(x<2) - + Решение: Не используйте ``plot(h(x), 0, 4)``; используйте: @@ -163,9 +163,9 @@ :: sage: type(f) - + sage: type(g) - + ``g`` не является функцией, это константа, поэтому она не имеет переменных, и вы можете вставлять что угодно в нее. @@ -183,7 +183,7 @@ sage: g(3) 1 sage: type(g) - + - Либо вместе с ``f``, определенной выше, определить ``g`` как символьное выражение. @@ -196,7 +196,7 @@ sage: g(3) 1 sage: type(g) - + - Либо с ``f`` и ``g``, заданными, как показано выше, создать переменную, под которую подставляются значения. From 617c1732ae45800226849ff70c69dacb360f44fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Mon, 11 Oct 2021 14:52:15 +0200 Subject: [PATCH 325/359] remove last trace of TransitiveIdeal --- src/sage/combinat/backtrack.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/combinat/backtrack.py b/src/sage/combinat/backtrack.py index 60df7b7eb05..2ec84286ea3 100644 --- a/src/sage/combinat/backtrack.py +++ b/src/sage/combinat/backtrack.py @@ -41,7 +41,7 @@ class GenericBacktracker(object): A generic backtrack tool for exploring a search space organized as a tree, with branch pruning, etc. - See also :class:`RecursivelyEnumeratedSet_forest` and :class:`TransitiveIdeal` for + See also :class:`RecursivelyEnumeratedSet_forest` for handling simple special cases. """ def __init__(self, initial_data, initial_state): From 95921411b2f06f9ff6477f4f3d5e77621cc8ac52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Mon, 11 Oct 2021 16:35:43 +0200 Subject: [PATCH 326/359] fix some doc in posets --- src/sage/combinat/posets/posets.py | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/sage/combinat/posets/posets.py b/src/sage/combinat/posets/posets.py index 3c5b56dedf2..9a1f7a536f4 100644 --- a/src/sage/combinat/posets/posets.py +++ b/src/sage/combinat/posets/posets.py @@ -6885,8 +6885,10 @@ def maximal_chains(self, partial=None): INPUT: - - ``partial`` -- list (optional); if present, find all maximal - chains starting with the elements in partial + - ``partial`` -- list (optional); if given, the list + ``partial`` is assumed to be the start of a maximal chain, + and the function will find all maximal chains starting with + the elements in ``partial`` This is used in constructing the order complex for the poset. @@ -6913,8 +6915,10 @@ def maximal_chains_iterator(self, partial=None): INPUT: - - ``partial`` -- list (optional); if present, yield all maximal - chains starting with the elements in partial + - ``partial`` -- list (optional); if given, the list + ``partial`` is assumed to be the start of a maximal chain, + and the function will yield all maximal chains starting with + the elements in ``partial`` EXAMPLES:: @@ -6923,6 +6927,13 @@ def maximal_chains_iterator(self, partial=None): sage: next(it) [0, 1, 3, 7] + TESTS:: + + sage: P = posets.BooleanLattice(3) + sage: it = P.maximal_chains_iterator([0, 4]) + sage: next(it) + [0, 4, 5, 7] + .. SEEALSO:: :meth:`antichains_iterator` From 2cd253c1b7d2b6cb6b8ca0254087565652b9d723 Mon Sep 17 00:00:00 2001 From: Jonathan Kliem Date: Mon, 11 Oct 2021 21:58:26 +0200 Subject: [PATCH 327/359] more specific import --- src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx b/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx index 9cff71d08b7..902a1551974 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx @@ -1265,7 +1265,7 @@ cdef class CombinatorialPolyhedron(SageObject): sage: polytopes.cube().vertex_adjacency_matrix().is_immutable() True """ - from sage.rings.all import ZZ + from sage.rings.integer_ring import ZZ from sage.matrix.constructor import matrix cdef Matrix_integer_dense adjacency_matrix = matrix( ZZ, self.n_Vrepresentation(), self.n_Vrepresentation(), 0) From 2101b8cccc8b0b2fc782dbeb8c476e6a52243498 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 11 Oct 2021 20:06:14 -0700 Subject: [PATCH 328/359] build/pkgs/python3/spkg-build.in: Make sure that python finds sqlite3 when determining which extension modules to build --- build/pkgs/python3/spkg-build.in | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/build/pkgs/python3/spkg-build.in b/build/pkgs/python3/spkg-build.in index c8c02917cbc..b75958ab0fd 100644 --- a/build/pkgs/python3/spkg-build.in +++ b/build/pkgs/python3/spkg-build.in @@ -84,8 +84,13 @@ sdh_configure --enable-shared $PYTHON_CONFIGURE # Make sure -L. is placed before -L$SAGE_LOCAL/lib so that python and extension # modules are linked with the right libpython; we pass this in at make time # only, since we don't want -L. to be saved as one of the default LDFLAGS -# used for building third-party extension modules -sdh_make LDFLAGS="-L. $LDFLAGS" +# used for building third-party extension modules. +# +# Trac #32442: As we now install python in SAGE_VENV, not SAGE_LOCAL, +# we need to provide paths into $SAGE_LOCAL, so that setup.py finds +# the libraries needed for the extension modules - in particular sqlite3. +# (The search code there does not know about CPATH and LIBRARY_PATH.) +sdh_make LDFLAGS="-L. -L$SAGE_LOCAL/lib $LDFLAGS" CPPFLAGS="-I$SAGE_LOCAL/include $CPPFLAGS" if [ "$UNAME" = "Darwin" ]; then export DYLD_LIBRARY_PATH="." From f3776fa32dc435a6e4c33ee3ce6cc221acf06703 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Tue, 12 Oct 2021 09:46:35 +0200 Subject: [PATCH 329/359] more details --- src/sage/functions/bessel.py | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/src/sage/functions/bessel.py b/src/sage/functions/bessel.py index 6de793a1545..3ba9ece2359 100644 --- a/src/sage/functions/bessel.py +++ b/src/sage/functions/bessel.py @@ -362,14 +362,14 @@ def _eval_(self, n, x): from sage.rings.infinity import unsigned_infinity if not isinstance(x, Expression) and x == 0: if n == 0: - return ZZ(1) + return ZZ.one() elif n.real() > 0 or n in ZZ: - return ZZ(0) + return ZZ.zero() elif n.real() < 0: return unsigned_infinity - if n == QQ(1) / 2: + if n == QQ((1, 2)): return sqrt(2 / pi / x) * sin(x) - elif n == QQ(-1) / 2: + elif n == QQ((-1, 2)): return sqrt(2 / pi / x) * cos(x) def _evalf_(self, n, x, parent=None, algorithm=None): @@ -584,7 +584,7 @@ def _eval_(self, n, x): return unsigned_infinity if n == QQ((1, 2)): return -sqrt(2 / pi / x) * cos(x) - elif n == QQ(-1) / 2: + elif n == QQ((-1, 2)): return sqrt(2 / pi / x) * sin(x) def _evalf_(self, n, x, parent=None, algorithm=None): @@ -788,14 +788,14 @@ def _eval_(self, n, x): from sage.rings.infinity import unsigned_infinity if not isinstance(x, Expression) and x == 0: if n == 0: - return ZZ(1) + return ZZ.one() elif n.real() > 0 or n in ZZ: - return ZZ(0) + return ZZ.zero() elif n.real() < 0: return unsigned_infinity - if n == QQ(1) / 2: + if n == QQ((1, 2)): return sqrt(2 / (pi * x)) * sinh(x) - elif n == -QQ(1) / 2: + elif n == QQ((-1, 2)): return sqrt(2 / (pi * x)) * cosh(x) def _evalf_(self, n, x, parent=None, algorithm=None): @@ -989,7 +989,7 @@ def _eval_(self, n, x): return infinity elif n.real() > 0 or n.real() < 0: return unsigned_infinity - if n == QQ(1) / 2 or n == -QQ(1) / 2 and x > 0: + if n == QQ((1, 2)) or n == QQ((-1, 2)) and x > 0: return sqrt(pi / 2) * exp(-x) * x ** (-Integer(1) / Integer(2)) def _evalf_(self, n, x, parent=None, algorithm=None): @@ -1274,13 +1274,11 @@ def _eval_(self, a, z): sage: struve_H(-3/2,x) -bessel_J(3/2, x) """ - from sage.symbolic.ring import SR if z.is_zero() \ and (SR(a).is_numeric() or SR(a).is_constant()) \ and a.real() >= -1: - return ZZ(0) - from sage.rings.rational_field import QQ - if a == -QQ((1, 2)): + return ZZ.zero() + if a == QQ((-1, 2)): from sage.functions.trig import sin return sqrt(2 / (pi * z)) * sin(z) if a == QQ((1, 2)): @@ -1288,7 +1286,7 @@ def _eval_(self, a, z): return sqrt(2 / (pi * z)) * (1 - cos(z)) if a < 0 and not SR(a).is_integer() and SR(2 * a).is_integer(): n = (a * (-2) - 1) / 2 - return Integer(-1)**n * bessel_J(n + QQ(1) / 2, z) + return Integer(-1)**n * bessel_J(n + QQ((1, 2)), z) def _evalf_(self, a, z, parent=None, algorithm=None): """ @@ -1392,11 +1390,10 @@ def _eval_(self, a, z): sage: struve_L(-3/2,x) -bessel_I(3/2, x) """ - from sage.symbolic.ring import SR if z.is_zero() \ and (SR(a).is_numeric() or SR(a).is_constant()) \ and a.real() >= -1: - return ZZ(0) + return ZZ.zero() if a == -Integer(1) / 2: from sage.functions.hyperbolic import sinh return sqrt(2 / (pi * z)) * sinh(z) @@ -1404,9 +1401,8 @@ def _eval_(self, a, z): from sage.functions.hyperbolic import cosh return sqrt(2 / (pi * z)) * (cosh(z) - 1) if a < 0 and not SR(a).is_integer() and SR(2 * a).is_integer(): - from sage.rings.rational_field import QQ n = (a * (-2) - 1) / 2 - return Integer(-1)**n * bessel_I(n + QQ(1) / 2, z) + return Integer(-1)**n * bessel_I(n + QQ((1, 2)), z) def _evalf_(self, a, z, parent=None, algorithm=None): """ From 17acb7bc892c9ca59408aa14740ff6304690e42a Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Tue, 12 Oct 2021 12:58:14 +0200 Subject: [PATCH 330/359] Do not need Cython for sdist or egg_info --- src/setup.py | 89 +++++++++++++++++++++++++++------------------------- 1 file changed, 46 insertions(+), 43 deletions(-) diff --git a/src/setup.py b/src/setup.py index 686f25aec36..7737465a96f 100755 --- a/src/setup.py +++ b/src/setup.py @@ -52,7 +52,7 @@ # ## Configuration # ######################################################## -if len(sys.argv) > 1 and sys.argv[1] == "sdist": +if len(sys.argv) > 1 and (sys.argv[1] == "sdist" or sys.argv[1] == "egg_info"): sdist = True else: sdist = False @@ -69,52 +69,55 @@ # ######################################################## # ## Discovering Sources # ######################################################## - -log.info("Discovering Python/Cython source code....") -t = time.time() - -# Exclude a few files if the corresponding distribution is not loaded -optional_packages = ['mcqd', 'bliss', 'tdlib', 'primecount', - 'coxeter3', 'fes', 'sirocco', 'meataxe'] -not_installed_packages = [package for package in optional_packages - if not is_package_installed_and_updated(package)] - -distributions_to_exclude = [f"sagemath-{pkg}" - for pkg in not_installed_packages] -files_to_exclude = filter_cython_sources(SAGE_SRC, distributions_to_exclude) - -log.debug(f"files_to_exclude = {files_to_exclude}") - -python_packages = find_namespace_packages(where=SAGE_SRC, include=['sage', 'sage.*']) -log.debug(f"python_packages = {python_packages}") - -log.info(f"Discovered Python/Cython sources, time: {(time.time() - t):.2f} seconds.") - -# from sage_build_cython: -import Cython.Compiler.Options -Cython.Compiler.Options.embed_pos_in_docstring = True -gdb_debug = os.environ.get('SAGE_DEBUG', None) != 'no' - -try: +if sdist: + extensions = [] + python_packages = [] +else: log.info("Generating auto-generated sources") from sage_setup.autogen import autogen_all autogen_all() - from Cython.Build import cythonize - from sage.env import cython_aliases, sage_include_directories - extensions = cythonize( - ["**/*.pyx"], - exclude=files_to_exclude, - include_path=sage_include_directories(use_sources=True) + ['.'], - compile_time_env=compile_time_env_variables(), - compiler_directives=compiler_directives(False), - aliases=cython_aliases(), - create_extension=create_extension, - gdb_debug=gdb_debug, - nthreads=4) -except Exception as exception: - log.warn(f"Exception while generating and cythonizing source files: {exception}") - raise + log.info("Discovering Python/Cython source code....") + t = time.time() + + # Exclude a few files if the corresponding distribution is not loaded + optional_packages = ['mcqd', 'bliss', 'tdlib', 'primecount', + 'coxeter3', 'fes', 'sirocco', 'meataxe'] + not_installed_packages = [package for package in optional_packages + if not is_package_installed_and_updated(package)] + + distributions_to_exclude = [f"sagemath-{pkg}" + for pkg in not_installed_packages] + files_to_exclude = filter_cython_sources(SAGE_SRC, distributions_to_exclude) + + log.debug(f"files_to_exclude = {files_to_exclude}") + + python_packages = find_namespace_packages(where=SAGE_SRC, include=['sage', 'sage.*']) + log.debug(f"python_packages = {python_packages}") + + log.info(f"Discovered Python/Cython sources, time: {(time.time() - t):.2f} seconds.") + + # from sage_build_cython: + import Cython.Compiler.Options + Cython.Compiler.Options.embed_pos_in_docstring = True + gdb_debug = os.environ.get('SAGE_DEBUG', None) != 'no' + + try: + from Cython.Build import cythonize + from sage.env import cython_aliases, sage_include_directories + extensions = cythonize( + ["**/*.pyx"], + exclude=files_to_exclude, + include_path=sage_include_directories(use_sources=True) + ['.'], + compile_time_env=compile_time_env_variables(), + compiler_directives=compiler_directives(False), + aliases=cython_aliases(), + create_extension=create_extension, + gdb_debug=gdb_debug, + nthreads=4) + except Exception as exception: + log.warn(f"Exception while cythonizing source files: {repr(exception)}") + raise # ######################################################## # ## Distutils From ff2a35241c54a1442a3d18ad60929f6efea0ef24 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 12 Oct 2021 09:39:55 -0700 Subject: [PATCH 331/359] src/setup.py: Restrict cythonize to sage/** --- src/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/setup.py b/src/setup.py index 7737465a96f..81ee8babd19 100755 --- a/src/setup.py +++ b/src/setup.py @@ -106,7 +106,7 @@ from Cython.Build import cythonize from sage.env import cython_aliases, sage_include_directories extensions = cythonize( - ["**/*.pyx"], + ["sage/**/*.pyx"], exclude=files_to_exclude, include_path=sage_include_directories(use_sources=True) + ['.'], compile_time_env=compile_time_env_variables(), From 46cf0677157aef4c208034b339797d39ca846b54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Tue, 12 Oct 2021 21:37:43 +0200 Subject: [PATCH 332/359] convert some + """ proj = self.projection() if self.ambient_dim() == 3: diff --git a/src/sage/geometry/polyhedron/constructor.py b/src/sage/geometry/polyhedron/constructor.py index 2df40ce6c59..e09a3d27d88 100644 --- a/src/sage/geometry/polyhedron/constructor.py +++ b/src/sage/geometry/polyhedron/constructor.py @@ -131,7 +131,7 @@ sage: type(v) sage: type( v() ) - + sage: v.polyhedron() A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 2 vertices and 2 rays sage: r = next(trunc_quadr.ray_generator()) diff --git a/src/sage/geometry/polyhedron/palp_database.py b/src/sage/geometry/polyhedron/palp_database.py index a9bd90eca8b..1ec027f9482 100644 --- a/src/sage/geometry/polyhedron/palp_database.py +++ b/src/sage/geometry/polyhedron/palp_database.py @@ -88,7 +88,7 @@ class PALPreader(SageObject): [-1, -1] in Ambient free module of rank 2 over the principal ideal domain Integer Ring sage: type(_) - + """ def __init__(self, dim, data_basename=None, output='Polyhedron'): diff --git a/src/sage/geometry/polyhedron/plot.py b/src/sage/geometry/polyhedron/plot.py index a7976de6d2e..9a6a759eb93 100644 --- a/src/sage/geometry/polyhedron/plot.py +++ b/src/sage/geometry/polyhedron/plot.py @@ -1009,7 +1009,7 @@ def render_solid_3d(self, **kwds): sage: p = polytopes.hypercube(3).projection() sage: p_solid = p.render_solid_3d(opacity = .7) sage: type(p_solid) - + """ polys = self.polygons N = max([-1] + [i for p in polys for i in p]) + 1 diff --git a/src/sage/geometry/polyhedron/representation.py b/src/sage/geometry/polyhedron/representation.py index 9b4cb1586d2..443bea9224a 100644 --- a/src/sage/geometry/polyhedron/representation.py +++ b/src/sage/geometry/polyhedron/representation.py @@ -231,7 +231,7 @@ def vector(self, base_ring=None): sage: v() (-1, -1, 0) sage: type(v()) - + Conversion to a different base ring can be forced with the optional argument:: diff --git a/src/sage/groups/abelian_gps/abelian_group.py b/src/sage/groups/abelian_gps/abelian_group.py index 00cf0f3c9d7..1c9ce29e858 100644 --- a/src/sage/groups/abelian_gps/abelian_group.py +++ b/src/sage/groups/abelian_gps/abelian_group.py @@ -974,9 +974,9 @@ def gens_orders(self): sage: F = AbelianGroup(3, [2], names='abc') sage: list(map(type, F.gens_orders())) - [, - , - ] + [, + , + ] """ return self._gens_orders @@ -1022,9 +1022,9 @@ def invariants(self): sage: F = AbelianGroup(3, [2], names='abc') sage: list(map(type, F.gens_orders())) - [, - , - ] + [, + , + ] """ # TODO: deprecate return self.gens_orders() diff --git a/src/sage/groups/conjugacy_classes.py b/src/sage/groups/conjugacy_classes.py index c3a3a8460c7..fd79d60ee5b 100644 --- a/src/sage/groups/conjugacy_classes.py +++ b/src/sage/groups/conjugacy_classes.py @@ -437,7 +437,7 @@ def cardinality(self): sage: cc.cardinality() 3840 sage: type(cc.cardinality()) - + """ return self._gap_().Size().sage() diff --git a/src/sage/groups/finitely_presented.py b/src/sage/groups/finitely_presented.py index ee364c289b0..10f52fc6d80 100644 --- a/src/sage/groups/finitely_presented.py +++ b/src/sage/groups/finitely_presented.py @@ -75,7 +75,7 @@ sage: a.gap().Order() 2 sage: type(_) # note that the above output is not a Sage integer - + You can use call syntax to replace the generators with a set of arbitrary ring elements. For example, take the free abelian group @@ -397,7 +397,7 @@ def wrap_FpGroup(libgap_fpgroup): sage: P = F / libgap([ a_cubed ]); P sage: type(P) - + Now wrap it:: @@ -775,7 +775,7 @@ class FinitelyPresentedGroup(GroupMixinLibGAP, UniqueRepresentation, sage: H.gap() sage: type(_) - + """ Element = FinitelyPresentedGroupElement diff --git a/src/sage/groups/free_group.py b/src/sage/groups/free_group.py index e3c3f785b7b..68c0f909bf0 100644 --- a/src/sage/groups/free_group.py +++ b/src/sage/groups/free_group.py @@ -322,7 +322,7 @@ def Tietze(self): sage: type(a.Tietze()) <... 'tuple'> sage: type(a.Tietze()[0]) - + """ tl = self.gap().TietzeWordAbstractWord() return tuple(tl.sage()) @@ -709,7 +709,7 @@ def wrap_FreeGroup(libgap_free_group): sage: F = libgap.FreeGroup(['a', 'b']) sage: type(F) - + Now wrap it:: diff --git a/src/sage/groups/libgap_morphism.py b/src/sage/groups/libgap_morphism.py index 86a16984e0c..75785e2e382 100644 --- a/src/sage/groups/libgap_morphism.py +++ b/src/sage/groups/libgap_morphism.py @@ -133,7 +133,7 @@ class GroupMorphism_libgap(Morphism): CompositionMapping( [ (6,7,8,10,9)(11,13,14,12,15)(16,19,20,18,17)(21,25,22,24,23) ] -> [ [ [ Z(5)^0, 0*Z(5) ], [ Z(5)^0, Z(5)^0 ] ] ], ) sage: type(_) - + sage: F = GF(7); MS = MatrixSpace(F,2,2) sage: F.multiplicative_generator() diff --git a/src/sage/groups/libgap_wrapper.pyx b/src/sage/groups/libgap_wrapper.pyx index 451cb5c65c2..01776f0df18 100644 --- a/src/sage/groups/libgap_wrapper.pyx +++ b/src/sage/groups/libgap_wrapper.pyx @@ -27,7 +27,7 @@ its output via LibGAP:: sage: FooGroup() sage: type(FooGroup().gap()) - + The element class is a subclass of :class:`~sage.structure.element.MultiplicativeGroupElement`. To use @@ -285,7 +285,7 @@ class ParentLibGAP(SageObject): sage: G.gap().parent() C library interface to GAP sage: type(G.gap()) - + This can be useful, for example, to call GAP functions that are not wrapped in Sage:: @@ -325,7 +325,7 @@ class ParentLibGAP(SageObject): TESTS:: sage: type(G.ngens()) - + """ return Integer(len(self.gens())) @@ -504,14 +504,14 @@ cdef class ElementLibGAP(MultiplicativeGroupElement): sage: xg a*b*a^-1*b^-1 sage: type(xg) - + TESTS:: sage: libgap(FreeGroup('a, b').an_element()) a*b sage: type(libgap(FreeGroup('a, b').an_element())) - + """ return self._libgap diff --git a/src/sage/groups/misc_gps/argument_groups.py b/src/sage/groups/misc_gps/argument_groups.py index 818185f783e..1cf801fad85 100644 --- a/src/sage/groups/misc_gps/argument_groups.py +++ b/src/sage/groups/misc_gps/argument_groups.py @@ -1534,7 +1534,7 @@ def _act_on_(self, other, is_left): sage: S(-1) * int(4) -4 sage: type(_) - + sage: S(-1) * QQ(4) -4 sage: _.parent() @@ -1641,7 +1641,7 @@ def __init__(self, category): sage: from sage.groups.misc_gps.argument_groups import SignGroup sage: S = SignGroup() sage: S.base() # indirect doctest - + """ return super(SignGroup, self).__init__(base=int, category=category) diff --git a/src/sage/groups/perm_gps/permgroup.py b/src/sage/groups/perm_gps/permgroup.py index 11b640c7c45..f91dcd8fcca 100644 --- a/src/sage/groups/perm_gps/permgroup.py +++ b/src/sage/groups/perm_gps/permgroup.py @@ -2852,7 +2852,7 @@ def _subgroup_constructor(self, libgap_group): sage: g = g1*g2 sage: Hgap = G.gap().Subgroup([g.gap()]) sage: type(Hgap) - + sage: H = G._subgroup_constructor(Hgap); H Subgroup generated by [(1,6,21,12,20,17)(2,10,15,9,11,5)(3,14,8)(4,18)(7,16)] of (The projective general unitary group of degree 3 over Finite Field of size 2) """ diff --git a/src/sage/groups/perm_gps/permgroup_element.pyx b/src/sage/groups/perm_gps/permgroup_element.pyx index 31e6ccce5ec..33057e459ef 100644 --- a/src/sage/groups/perm_gps/permgroup_element.pyx +++ b/src/sage/groups/perm_gps/permgroup_element.pyx @@ -1560,7 +1560,7 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): sage: t=PermutationGroupElement(L).multiplicative_order(); t 1492182350939279320058875736615841068547583863326864530410 sage: type(t) - + """ order = None cdef long long order_c = 1 diff --git a/src/sage/groups/perm_gps/permgroup_named.py b/src/sage/groups/perm_gps/permgroup_named.py index f1c8c715889..5010e958a3c 100644 --- a/src/sage/groups/perm_gps/permgroup_named.py +++ b/src/sage/groups/perm_gps/permgroup_named.py @@ -2127,9 +2127,9 @@ def cardinality(self): TESTS:: sage: type(TransitiveGroups(12).cardinality()) - + sage: type(TransitiveGroups(0).cardinality()) - + """ # gap.NrTransitiveGroups(0) fails, so Sage needs to handle this @@ -2519,9 +2519,9 @@ def cardinality(self): TESTS:: sage: type(PrimitiveGroups(12).cardinality()) - + sage: type(PrimitiveGroups(0).cardinality()) - + Check for :trac:`31774`:: diff --git a/src/sage/modular/abvar/finite_subgroup.py b/src/sage/modular/abvar/finite_subgroup.py index 3c2aefc0ab9..471386f3575 100644 --- a/src/sage/modular/abvar/finite_subgroup.py +++ b/src/sage/modular/abvar/finite_subgroup.py @@ -774,7 +774,7 @@ def invariants(self): ... ValueError: object is immutable; please change a copy instead. sage: type(v[0]) - + :: diff --git a/src/sage/modular/abvar/morphism.py b/src/sage/modular/abvar/morphism.py index 99bbd68af9d..670fff0fef8 100644 --- a/src/sage/modular/abvar/morphism.py +++ b/src/sage/modular/abvar/morphism.py @@ -796,7 +796,7 @@ def index(self): sage: t.index() 997 sage: type(t.index()) - + """ return self.__n diff --git a/src/sage/modular/abvar/torsion_point.py b/src/sage/modular/abvar/torsion_point.py index 56150c69943..a7cdd54ff3a 100644 --- a/src/sage/modular/abvar/torsion_point.py +++ b/src/sage/modular/abvar/torsion_point.py @@ -87,7 +87,7 @@ def element(self): sage: v = (G.0-G.1).element(); v (1/3, -1/5) sage: type(v) - + """ return self.__element diff --git a/src/sage/modular/arithgroup/arithgroup_element.pyx b/src/sage/modular/arithgroup/arithgroup_element.pyx index 1fff86aa7ab..b2e034bb5e7 100644 --- a/src/sage/modular/arithgroup/arithgroup_element.pyx +++ b/src/sage/modular/arithgroup/arithgroup_element.pyx @@ -254,7 +254,7 @@ cdef class ArithmeticSubgroupElement(MultiplicativeGroupElement): [4 5] [3 4] sage: type(x.matrix()) - + """ return self.__x diff --git a/src/sage/modular/arithgroup/congroup_gamma0.py b/src/sage/modular/arithgroup/congroup_gamma0.py index f1fc3f493d8..16390a280ab 100644 --- a/src/sage/modular/arithgroup/congroup_gamma0.py +++ b/src/sage/modular/arithgroup/congroup_gamma0.py @@ -75,7 +75,7 @@ class Gamma0_class(GammaH_class): sage: a = Gamma0(1).dimension_cusp_forms(2); a 0 sage: type(a) - + sage: Gamma0(5).dimension_cusp_forms(0) 0 sage: Gamma0(20).dimension_cusp_forms(1) diff --git a/src/sage/modular/dirichlet.py b/src/sage/modular/dirichlet.py index 1cb1a7dd803..b090be1f579 100644 --- a/src/sage/modular/dirichlet.py +++ b/src/sage/modular/dirichlet.py @@ -787,7 +787,7 @@ def conductor(self): sage: G. = DirichletGroup(20) sage: type(G(1).conductor()) - + """ if self.modulus() == 1 or self.is_trivial(): return rings.Integer(1) diff --git a/src/sage/modular/hecke/element.py b/src/sage/modular/hecke/element.py index 35053b87675..7f0ca936ccf 100644 --- a/src/sage/modular/hecke/element.py +++ b/src/sage/modular/hecke/element.py @@ -113,7 +113,7 @@ def element(self): sage: z = BrandtModule(37)([0,1,-1]).element(); z (0, 1, -1) sage: type(z) - + """ try: return self.__element @@ -130,11 +130,11 @@ def _vector_(self, R=None): sage: v = BrandtModule(37)([0,1,-1]); v (0, 1, -1) sage: type(v._vector_()) - + sage: type(vector(v)) - + sage: type(vector(v, GF(2))) - + """ if R is None: return self.__element diff --git a/src/sage/modular/local_comp/liftings.py b/src/sage/modular/local_comp/liftings.py index e862031f4b2..f3bf799ae88 100644 --- a/src/sage/modular/local_comp/liftings.py +++ b/src/sage/modular/local_comp/liftings.py @@ -53,7 +53,7 @@ def lift_to_gamma1(g, m, n): sage: assert matrix(Zmod(11), 2, n) == matrix(Zmod(11),2,m) sage: assert matrix(Zmod(17), 2, [n[0], 0, n[2], n[3]]) == 1 sage: type(lift_to_gamma1([10,11,3,11],19,5)[0]) - + Tests with `m = 1` and with `n = 1`:: @@ -95,7 +95,7 @@ def lift_matrix_to_sl2z(A, N): sage: lift_matrix_to_sl2z([10, 11, 3, 11], 19) [29, 106, 3, 11] sage: type(_[0]) - + sage: lift_matrix_to_sl2z([2,0,0,1], 5) Traceback (most recent call last): ... @@ -130,7 +130,7 @@ def lift_gen_to_gamma1(m, n): [1 6] [0 1] sage: type(lift_gen_to_gamma1(9, 8)[0]) - + """ return lift_to_gamma1([0,-1,1,0], m, n) @@ -150,7 +150,7 @@ def lift_uniformiser_odd(p, u, n): sage: lift_uniformiser_odd(3, 2, 11) [432, 377, 165, 144] sage: type(lift_uniformiser_odd(3, 2, 11)[0]) - + """ g = lift_gen_to_gamma1(p**u, n) return [p * g[0], g[1], p * g[2], g[3]] @@ -175,7 +175,7 @@ def lift_ramified(g, p, u, n): sage: lift_ramified([8,2,12,2], 3, 2, 23) [323, 110, -133584, -45493] sage: type(lift_ramified([8,2,12,2], 3, 2, 23)[0]) - + """ a, b, c, d = lift_to_gamma1(g, p**u, n) r = crt((c - g[2]) / p**u * inverse_mod(a, p), 0, p, n) diff --git a/src/sage/modular/modform/constructor.py b/src/sage/modular/modform/constructor.py index e330afb2361..2b9b59085f3 100644 --- a/src/sage/modular/modform/constructor.py +++ b/src/sage/modular/modform/constructor.py @@ -83,10 +83,10 @@ def canonical_parameters(group, level, weight, base_ring): sage: v = canonical_parameters(5, 5, int(7), ZZ); v (5, Congruence Subgroup Gamma0(5), 7, Integer Ring) sage: type(v[0]), type(v[1]), type(v[2]), type(v[3]) - (, + (, , - , - ) + , + ) sage: canonical_parameters( 5, 7, 7, ZZ ) Traceback (most recent call last): ... diff --git a/src/sage/modular/modform/space.py b/src/sage/modular/modform/space.py index afeb682bca2..497fb2e78bf 100644 --- a/src/sage/modular/modform/space.py +++ b/src/sage/modular/modform/space.py @@ -394,7 +394,7 @@ def __normalize_prec(self, prec): :: sage: type(N._ModularFormsSpace__normalize_prec(int(3))) - + """ if prec is None: prec = self.prec() diff --git a/src/sage/modular/modsym/boundary.py b/src/sage/modular/modsym/boundary.py index 89357424952..f8550d0f05f 100644 --- a/src/sage/modular/modsym/boundary.py +++ b/src/sage/modular/modsym/boundary.py @@ -541,7 +541,7 @@ def __call__(self, x): sage: B(7) Traceback (most recent call last): ... - TypeError: Coercion of 7 (of type ) into Space of Boundary Modular Symbols for Congruence Subgroup Gamma0(15) of weight 2 over Rational Field not (yet) defined. + TypeError: Coercion of 7 (of type ) into Space of Boundary Modular Symbols for Congruence Subgroup Gamma0(15) of weight 2 over Rational Field not (yet) defined. """ from .ambient import ModularSymbolsAmbient if isinstance(x, int) and x == 0: diff --git a/src/sage/modular/modsym/manin_symbol_list.py b/src/sage/modular/modsym/manin_symbol_list.py index 6dae77db4c7..dc4226b5db5 100644 --- a/src/sage/modular/modsym/manin_symbol_list.py +++ b/src/sage/modular/modsym/manin_symbol_list.py @@ -351,7 +351,7 @@ def manin_symbol(self, i): sage: s = m.manin_symbol(3); s [Y^2,(1,2)] sage: type(s) - + """ return self.element_class(self, self._symbol_list[i]) diff --git a/src/sage/modular/modsym/modsym.py b/src/sage/modular/modsym/modsym.py index 58a0d64b8b5..ee49b9c9abd 100644 --- a/src/sage/modular/modsym/modsym.py +++ b/src/sage/modular/modsym/modsym.py @@ -112,7 +112,7 @@ def canonical_parameters(group, weight, sign, base_ring): sage: p1 == p2 True sage: type(p1[1]) - + """ sign = rings.Integer(sign) if not (sign in [-1,0,1]): diff --git a/src/sage/modular/overconvergent/weightspace.py b/src/sage/modular/overconvergent/weightspace.py index 08aacc88588..14515dda101 100644 --- a/src/sage/modular/overconvergent/weightspace.py +++ b/src/sage/modular/overconvergent/weightspace.py @@ -447,7 +447,7 @@ def one_over_Lvalue(self): sage: pAdicWeightSpace(11)(0).one_over_Lvalue() 0 sage: type(_) - + """ if self.is_trivial(): return ZZ(0) diff --git a/src/sage/modular/pollack_stevens/sigma0.py b/src/sage/modular/pollack_stevens/sigma0.py index 687b3c0644e..fa2f4ac7d81 100644 --- a/src/sage/modular/pollack_stevens/sigma0.py +++ b/src/sage/modular/pollack_stevens/sigma0.py @@ -288,7 +288,7 @@ def matrix(self): sage: type(s) sage: type(sm) - + sage: s == sm True """ diff --git a/src/sage/modular/pollack_stevens/space.py b/src/sage/modular/pollack_stevens/space.py index e4cb161ce07..f52d609b6e7 100644 --- a/src/sage/modular/pollack_stevens/space.py +++ b/src/sage/modular/pollack_stevens/space.py @@ -823,7 +823,7 @@ def cusps_from_mat(g): You can also just give the matrix of ``g``:: sage: type(g) - + sage: cusps_from_mat(g.matrix()) (+Infinity, 0) diff --git a/src/sage/modular/quatalg/brandt.py b/src/sage/modular/quatalg/brandt.py index 81a775c99c4..6e170fe8c45 100644 --- a/src/sage/modular/quatalg/brandt.py +++ b/src/sage/modular/quatalg/brandt.py @@ -1023,7 +1023,7 @@ def hecke_matrix(self, n, algorithm='default', sparse=False, B=None): [ 6 6] [ 2 10] sage: type(t) - + sage: B.hecke_matrix(19, algorithm='direct', B=2) [ 8 12] [ 4 16] @@ -1079,9 +1079,9 @@ def _compute_hecke_matrix_prime(self, p, sparse=False, B=None): [1 0 2] [1 2 0] sage: type(t) - + sage: type(B._compute_hecke_matrix_prime(2,sparse=True)) - + """ return self._compute_hecke_matrix_directly(n=p, B=B, sparse=sparse) @@ -1106,9 +1106,9 @@ def _compute_hecke_matrix_directly(self, n, B=None, sparse=False): [1 0 2] [1 2 0] sage: type(t) - + sage: type(B._compute_hecke_matrix_directly(2,sparse=True)) - + You can't compute the Hecke operator for n not coprime to the level using this function:: diff --git a/src/sage/modules/fg_pid/fgp_element.py b/src/sage/modules/fg_pid/fgp_element.py index f6f03acd16c..3395225529b 100644 --- a/src/sage/modules/fg_pid/fgp_element.py +++ b/src/sage/modules/fg_pid/fgp_element.py @@ -440,7 +440,7 @@ def additive_order(self): sage: Q.0.additive_order() 12 sage: type(Q.0.additive_order()) - + sage: Q.1.additive_order() +Infinity """ diff --git a/src/sage/modules/filtered_vector_space.py b/src/sage/modules/filtered_vector_space.py index 4d0e451806e..dd6608c6161 100644 --- a/src/sage/modules/filtered_vector_space.py +++ b/src/sage/modules/filtered_vector_space.py @@ -218,7 +218,7 @@ def normalize_degree(deg): sage: from sage.modules.filtered_vector_space import normalize_degree sage: type(normalize_degree(int(1))) - + sage: normalize_degree(oo) +Infinity """ diff --git a/src/sage/modules/free_module_element.pyx b/src/sage/modules/free_module_element.pyx index 2075d07c0ae..fb1937e4da6 100644 --- a/src/sage/modules/free_module_element.pyx +++ b/src/sage/modules/free_module_element.pyx @@ -914,7 +914,7 @@ cdef class FreeModuleElement(Vector): # abstract base class sage: v = sage.modules.free_module_element.FreeModuleElement(QQ^3) sage: type(v) - + """ self._parent = parent self._degree = parent.degree() @@ -1735,7 +1735,7 @@ cdef class FreeModuleElement(Vector): # abstract base class sage: F. = PolynomialRing(QQ, 'y') sage: type(vector(F, [0]*4, sparse=True)) - + sage: vector(F, [0,0,0,y]) == vector(F, [0,0,0,y]) True sage: vector(F, [0,0,0,0]) == vector(F, [0,2,0,y]) @@ -1928,7 +1928,7 @@ cdef class FreeModuleElement(Vector): # abstract base class sage: P. = QQ[] sage: v = vector([x,y,z], sparse=True) sage: type(v) - + sage: a = v.list(); a [x, y, z] sage: a[0] = x*y; v @@ -4012,7 +4012,7 @@ cdef class FreeModuleElement(Vector): # abstract base class sage: vec (0.5, 0.3333333333333334, 0.4596976941318602) sage: type(vec) - + sage: answers [(0.5, 5.55111512312578...e-15, 21, 0), (0.3333333333333..., 3.70074341541719...e-15, 21, 0), (0.45969769413186..., 5.10366964392284...e-15, 21, 0)] @@ -4169,7 +4169,7 @@ cdef class FreeModuleElement_generic_dense(FreeModuleElement): EXAMPLES:: sage: type(vector(RR, [-1,0,2/3,pi,oo])) - + We can initialize with lists, tuples and derived types:: @@ -4418,7 +4418,7 @@ cdef class FreeModuleElement_generic_dense(FreeModuleElement): sage: P. = QQ[] sage: v = vector([x,y,z]) sage: type(v) - + sage: a = v.list(); a [x, y, z] sage: a[0] = x*y; v @@ -5114,7 +5114,7 @@ cdef class FreeModuleElement_generic_sparse(FreeModuleElement): sage: M = FreeModule(R, 3, sparse=True) * (1/x) sage: v = M([-x^2, 3/x, 0]) sage: type(v) - + sage: a = v.list() sage: a [-x^2, 3/x, 0] diff --git a/src/sage/modules/module.pyx b/src/sage/modules/module.pyx index 5f3b4e0d467..62c6636fe0b 100644 --- a/src/sage/modules/module.pyx +++ b/src/sage/modules/module.pyx @@ -120,7 +120,7 @@ cdef class Module(Parent): sage: from sage.modules.module import Module sage: M = Module(ZZ) sage: type(M) - + """ from sage.categories.modules import Modules diff --git a/src/sage/modules/tensor_operations.py b/src/sage/modules/tensor_operations.py index 3550946581b..ce3bd555434 100644 --- a/src/sage/modules/tensor_operations.py +++ b/src/sage/modules/tensor_operations.py @@ -171,7 +171,7 @@ class VectorCollection(FreeModule_ambient_field): ((1, 0), (0, 1), (1, 2)) sage: r = R._vectors[0] sage: type(r) - + sage: r.parent() is R True sage: r.is_immutable() diff --git a/src/sage/modules/vector_complex_double_dense.pyx b/src/sage/modules/vector_complex_double_dense.pyx index 74c9dd75b11..c823e685abd 100644 --- a/src/sage/modules/vector_complex_double_dense.pyx +++ b/src/sage/modules/vector_complex_double_dense.pyx @@ -7,7 +7,7 @@ EXAMPLES:: sage: v (1.0 - 1.0*I, 2.0 + 3.141592653589793*I, 3.0 + 5.0*I) sage: type(v) - + sage: parent(v) Vector space of dimension 3 over Complex Double Field sage: v[0] = 5 diff --git a/src/sage/modules/vector_double_dense.pyx b/src/sage/modules/vector_double_dense.pyx index 83334163bea..d5559a07fb0 100644 --- a/src/sage/modules/vector_double_dense.pyx +++ b/src/sage/modules/vector_double_dense.pyx @@ -10,7 +10,7 @@ EXAMPLES:: sage: v (1.0 - 1.0*I, 2.0 + 3.141592653589793*I, 3.0 + 5.0*I) sage: type(v) - + sage: parent(v) Vector space of dimension 3 over Complex Double Field sage: v[0] = 5 diff --git a/src/sage/modules/vector_mod2_dense.pyx b/src/sage/modules/vector_mod2_dense.pyx index 3c08d14f2d7..47f41853f98 100644 --- a/src/sage/modules/vector_mod2_dense.pyx +++ b/src/sage/modules/vector_mod2_dense.pyx @@ -59,7 +59,7 @@ cdef class Vector_mod2_dense(free_module_element.FreeModuleElement): sage: VS([0,0,1]) (0, 0, 1) sage: type(_) - + """ cdef Vector_mod2_dense y y = Vector_mod2_dense.__new__(Vector_mod2_dense) @@ -114,7 +114,7 @@ cdef class Vector_mod2_dense(free_module_element.FreeModuleElement): sage: VS([0,0,1]) (0, 0, 1) sage: type(_) - + """ self._degree = degree self._parent = parent @@ -131,7 +131,7 @@ cdef class Vector_mod2_dense(free_module_element.FreeModuleElement): sage: VS((0,0,1/3)) (0, 0, 1) sage: type(_) - + """ self._entries = NULL self._is_immutable = 0 @@ -146,7 +146,7 @@ cdef class Vector_mod2_dense(free_module_element.FreeModuleElement): sage: VS((0,0,1/3)) (0, 0, 1) sage: type(_) - + sage: VS((0,0,int(3))) (0, 0, 1) sage: VS((0,0,3)) diff --git a/src/sage/modules/vector_modn_dense.pyx b/src/sage/modules/vector_modn_dense.pyx index d04604c5be3..9efa2d09753 100644 --- a/src/sage/modules/vector_modn_dense.pyx +++ b/src/sage/modules/vector_modn_dense.pyx @@ -5,7 +5,7 @@ EXAMPLES:: sage: v = vector(Integers(8),[1,2,3,4,5]) sage: type(v) - + sage: v (1, 2, 3, 4, 5) sage: 3*v @@ -64,13 +64,13 @@ TESTS:: sage: K = GF(previous_prime(2^31)) sage: v = vector(K, [42]); type(v[0]) - + sage: ~v[0] 2096353084 sage: K = GF(next_prime(2^31)) sage: v = vector(K, [42]); type(v[0]) - + sage: ~v[0] 1482786336 diff --git a/src/sage/modules/vector_real_double_dense.pyx b/src/sage/modules/vector_real_double_dense.pyx index 883a6195ca3..59bb8f4e23a 100644 --- a/src/sage/modules/vector_real_double_dense.pyx +++ b/src/sage/modules/vector_real_double_dense.pyx @@ -7,7 +7,7 @@ EXAMPLES:: sage: v (1.0, 3.141592653589793, 1.414213562373095) sage: type(v) - + sage: parent(v) Vector space of dimension 3 over Real Double Field sage: v[0] = 5 diff --git a/src/sage/stats/time_series.pyx b/src/sage/stats/time_series.pyx index 1f267685b69..234925fb478 100644 --- a/src/sage/stats/time_series.pyx +++ b/src/sage/stats/time_series.pyx @@ -2579,7 +2579,7 @@ def unpickle_time_series_v1(bytes v, Py_ssize_t n): sage: v = stats.TimeSeries([1,2,3]) sage: s = v.__reduce__()[1][0] sage: type(s) - + sage: sage.stats.time_series.unpickle_time_series_v1(s,3) [1.0000, 2.0000, 3.0000] sage: sage.stats.time_series.unpickle_time_series_v1(s+s,6) diff --git a/src/sage/structure/coerce_actions.pyx b/src/sage/structure/coerce_actions.pyx index 4f1c4cdf45b..82a5eaf356c 100644 --- a/src/sage/structure/coerce_actions.pyx +++ b/src/sage/structure/coerce_actions.pyx @@ -63,7 +63,7 @@ cdef class GenericAction(Action): sage: sage.structure.coerce_actions.GenericAction(QQ, Z6, True) Traceback (most recent call last): ... - NotImplementedError: action for not implemented + NotImplementedError: action for not implemented This will break if we tried to use it:: diff --git a/src/sage/structure/dynamic_class.py b/src/sage/structure/dynamic_class.py index 6ff4bc7990c..434c2968f8d 100644 --- a/src/sage/structure/dynamic_class.py +++ b/src/sage/structure/dynamic_class.py @@ -201,11 +201,11 @@ def dynamic_class(name, bases, cls=None, reduction=None, doccls=None, '__main__' sage: Foo.__bases__ - (,) + (,) sage: FooBar.__bases__ (,) sage: Foo.mro() - [, ] + [, ] sage: FooBar.mro() [, , ] @@ -238,7 +238,7 @@ class also has a zero ``__dictoffset__``. This means that the sage: BarFoo = dynamic_class("BarFoo", (Foo,), Bar, reduction = (str, (3,))) sage: type(BarFoo).__reduce__(BarFoo) - (, (3,)) + (, (3,)) sage: loads(dumps(BarFoo)) '3' @@ -280,7 +280,7 @@ class also has a zero ``__dictoffset__``. This means that the first class:: sage: dynamic_class("BarFoo", (Foo,), Bar, reduction = (str, (2,)), cache="ignore_reduction")._reduction - (, (3,)) + (, (3,)) .. WARNING:: @@ -502,7 +502,7 @@ def __reduce__(self): sage: C = sage.structure.dynamic_class.dynamic_class_internal("bla", (object,), Foo, doccls = DocClass) sage: type(C).__reduce__(C) (, - ('bla', (,), , None, )) + ('bla', (,), , None, )) sage: C = sage.structure.dynamic_class.dynamic_class_internal("bla", (object,), Foo, doccls = DocClass, reduction = "blah") sage: type(C).__reduce__(C) 'blah' diff --git a/src/sage/structure/element.pyx b/src/sage/structure/element.pyx index 7cdddb22644..9561ae9a899 100644 --- a/src/sage/structure/element.pyx +++ b/src/sage/structure/element.pyx @@ -2453,7 +2453,7 @@ cdef class ModuleElementWithMutability(ModuleElement): sage: v = sage.modules.free_module_element.FreeModuleElement(QQ^3) sage: type(v) - + """ self._parent = parent self._is_immutable = is_immutable diff --git a/src/sage/structure/sequence.py b/src/sage/structure/sequence.py index 0c8440da8e0..4925e24ce8a 100644 --- a/src/sage/structure/sequence.py +++ b/src/sage/structure/sequence.py @@ -116,7 +116,7 @@ def Sequence(x, universe=None, check=True, immutable=False, cr=False, cr_str=Non sage: v = Sequence(range(10)) sage: v.universe() - + sage: v [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] @@ -298,7 +298,7 @@ class Sequence_generic(sage.structure.sage_object.SageObject, list): sage: v = Sequence(range(10)) sage: v.universe() - + sage: v [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] @@ -485,7 +485,7 @@ def __setitem__(self, n, value): sage: v [1, 5, 3, 4] sage: type(v[2]) - + """ self._require_mutable() if isinstance(n, slice): @@ -539,7 +539,7 @@ def append(self, x): sage: v = Sequence([1/3,2,3,4]) sage: v.append(4) sage: type(v[4]) - + """ self._require_mutable() y = self.__universe(x) @@ -776,7 +776,7 @@ def is_mutable(self): True sage: a[0] = 100 sage: type(a[0]) - + sage: a.set_immutable() sage: a[0] = 50 Traceback (most recent call last): diff --git a/src/sage/symbolic/constants.py b/src/sage/symbolic/constants.py index a4b43b2a9f3..29c43eb64c5 100644 --- a/src/sage/symbolic/constants.py +++ b/src/sage/symbolic/constants.py @@ -717,7 +717,7 @@ def _mpfr_(self,R): sage: NaN._mpfr_(RealField(53)) NaN sage: type(_) - + """ return R('NaN') #??? nan in mpfr: void mpfr_set_nan (mpfr_t x) diff --git a/src/sage/symbolic/expression.pyx b/src/sage/symbolic/expression.pyx index 34145c0fad4..1c084ee9dc2 100644 --- a/src/sage/symbolic/expression.pyx +++ b/src/sage/symbolic/expression.pyx @@ -1476,7 +1476,7 @@ cdef class Expression(CommutativeRingElement): sage: ZZ(f.coefficient(x,0)) -3 sage: type(ZZ(f.coefficient(x,0))) - + Coercion is done if necessary:: @@ -1484,7 +1484,7 @@ cdef class Expression(CommutativeRingElement): sage: ZZ(f.coefficient(x)) 17 sage: type(ZZ(f.coefficient(x))) - + If the symbolic expression is just a wrapper around an integer, that very same integer is not preserved, but a new one returned:: @@ -1549,7 +1549,7 @@ cdef class Expression(CommutativeRingElement): sage: a = QQ(f.coefficient(x)); a 17 sage: type(a) - + sage: QQ(f.coefficient(x,0)) -3/8 @@ -1679,7 +1679,7 @@ cdef class Expression(CommutativeRingElement): sage: SR(CBF(1+I))._convert({'parent':RDF}) 1.0 + 1.0*I sage: type(_.pyobject()) - + sage: SR(CBF(1+I))._convert({'parent':CDF}) 1.0 + 1.0*I sage: SR(RBF(1))._convert({'parent':RDF}) @@ -1687,7 +1687,7 @@ cdef class Expression(CommutativeRingElement): sage: SR(CBF(1))._convert({'parent':RDF}) 1.0 sage: type(_.pyobject()) - + """ cdef GEx res = self._gobj.evalf(0, kwds) return new_Expression_from_GEx(self._parent, res) @@ -6270,7 +6270,7 @@ cdef class Expression(CommutativeRingElement): sage: type(t._unpack_operands()) <... 'tuple'> sage: list(map(type, t._unpack_operands())) - [, , , , ] + [, , , , ] sage: u = SR._force_pyobject((t, x^2)) sage: u._unpack_operands() ((1, 2, x, x + 1, x + 2), x^2) @@ -8264,7 +8264,7 @@ cdef class Expression(CommutativeRingElement): sage: abs(SR(-5)) 5 sage: type(abs(SR(-5))) - + Because this overrides a Python builtin function, we do not currently support a ``hold`` parameter to prevent automatic @@ -10361,7 +10361,7 @@ cdef class Expression(CommutativeRingElement): sage: res = t.maxima_methods().logcontract(); res log((sqrt(2) + 1)*(sqrt(2) - 1)) sage: type(res) - + """ from sage.symbolic.maxima_wrapper import MaximaWrapper return MaximaWrapper(self) @@ -13538,7 +13538,7 @@ cdef Expression new_Expression_from_GEx(parent, GEx juice): if is_exactly_a_function(juice): # if the function defines any dynamic methods these are made # available through a dynamic class - cls = get_dynamic_class_for_function(ex_to_function(juice).get_serial()) + cls = get_dynamic_class_for_function(ex_to_function(juice).get_serial()) else: cls = Expression @@ -13559,7 +13559,7 @@ cpdef new_Expression(parent, x): sage: a = SR(-3/4); a -3/4 sage: type(a) - + sage: a.parent() Symbolic Ring sage: K. = QuadraticField(-3) @@ -13654,7 +13654,7 @@ cpdef new_Expression_from_pyobject(parent, x, bint force=True, bint recursive=Tr sage: t = SR._force_pyobject(QQ); t # indirect doctest Rational Field sage: type(t) - + sage: from sage.symbolic.expression import new_Expression_from_pyobject sage: t = new_Expression_from_pyobject(SR, 17); t diff --git a/src/sage/symbolic/function.pyx b/src/sage/symbolic/function.pyx index d2c7d8e468f..faac362f426 100644 --- a/src/sage/symbolic/function.pyx +++ b/src/sage/symbolic/function.pyx @@ -446,7 +446,7 @@ cdef class Function(SageObject): sage: arctan(float(1)) 0.7853981633974483 sage: type(lambert_w(SR(0))) - + Precision of the result depends on the precision of the input:: @@ -955,7 +955,7 @@ cdef class BuiltinFunction(Function): sage: sin(numpy.int32(0)) 0.0 sage: type(_) - + TESTS:: diff --git a/src/sage/symbolic/pynac_impl.pxi b/src/sage/symbolic/pynac_impl.pxi index 01a51af2997..880a07faf17 100644 --- a/src/sage/symbolic/pynac_impl.pxi +++ b/src/sage/symbolic/pynac_impl.pxi @@ -101,9 +101,9 @@ cdef exprseq_to_PyTuple(GEx seq): sage: tfunc = TFunc() sage: u = SR._force_pyobject((1, x+1, 2)) sage: tfunc(u, x, SR._force_pyobject((3.0, 2^x))) - len(args): 3, types: [<... 'tuple'>, , <... 'tuple'>] - argument 0 is a tuple, with types [, , ] - argument 2 is a tuple, with types [, ] + len(args): 3, types: [<... 'tuple'>, , <... 'tuple'>] + argument 0 is a tuple, with types [, , ] + argument 2 is a tuple, with types [, ] tfunc((1, x + 1, 2), x, (3.00000000000000, 2^x)) """ from sage.symbolic.ring import SR @@ -128,7 +128,7 @@ def unpack_operands(Expression ex): sage: type(unpack_operands(t)) <... 'tuple'> sage: list(map(type, unpack_operands(t))) - [, , , , ] + [, , , , ] sage: u = SR._force_pyobject((t, x^2)) sage: unpack_operands(u) ((1, 2, x, x + 1, x + 2), x^2) @@ -159,7 +159,7 @@ cdef exvector_to_PyTuple(GExVector seq): sage: tfunc = TFunc() sage: u = SR._force_pyobject((1, x+1, 2)) sage: tfunc(u, x, 3.0, 5.0r) - len(args): 4, types: [<... 'tuple'>, , , <... 'float'>] + len(args): 4, types: [<... 'tuple'>, , , <... 'float'>] tfunc((1, x + 1, 2), x, 3.00000000000000, 5.0) TESTS: @@ -167,8 +167,8 @@ cdef exvector_to_PyTuple(GExVector seq): Check if symbolic functions in the arguments are preserved:: sage: tfunc(sin(x), tfunc(1, x^2)) - len(args): 2, types: [, ] - len(args): 2, types: [, ] + len(args): 2, types: [, ] + len(args): 2, types: [, ] tfunc(sin(x), tfunc(1, x^2)) """ @@ -1343,11 +1343,11 @@ cdef py_float(n, PyObject* kwds): sage: py_float(10, {'parent':CDF}) 10.0 sage: type(py_float(10, {'parent':CDF})) - + sage: py_float(1/2, {'parent':CC}) 0.500000000000000 sage: type(py_float(1/2, {'parent':CC})) - + """ if kwds is not NULL: p = (kwds)['parent'] @@ -2420,9 +2420,9 @@ def init_pynac_I(): sage: sage.symbolic.expression.init_pynac_I() sage: type(sage.symbolic.expression.I) - + sage: type(sage.symbolic.expression.I.pyobject()) - + Check that :trac:`10064` is fixed:: diff --git a/src/sage/symbolic/ring.pyx b/src/sage/symbolic/ring.pyx index a07d43d2aec..7789e1c4095 100644 --- a/src/sage/symbolic/ring.pyx +++ b/src/sage/symbolic/ring.pyx @@ -248,7 +248,7 @@ cdef class SymbolicRing(CommutativeRing): sage: a = SR(-3/4); a -3/4 sage: type(a) - + sage: a.parent() Symbolic Ring sage: K. = QuadraticField(-3) @@ -402,7 +402,7 @@ cdef class SymbolicRing(CommutativeRing): sage: t = SR._force_pyobject(QQ); t Rational Field sage: type(t) - + Testing tuples:: @@ -525,7 +525,7 @@ cdef class SymbolicRing(CommutativeRing): sage: c = SR.characteristic(); c 0 sage: type(c) - + """ return Integer(0) @@ -795,7 +795,7 @@ cdef class SymbolicRing(CommutativeRing): The return type is a symbolic expression:: sage: type(zz) - + We can specify the domain as well:: @@ -1177,7 +1177,7 @@ cdef class NumpyToSRMorphism(Morphism): sage: a = f(numpy.int8('2')).pyobject() sage: type(a) - + This behavior also applies to standard functions:: From 2bd108b56aec4bea04d1143f4e0710abf235679c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Tue, 12 Oct 2021 21:50:49 +0200 Subject: [PATCH 333/359] removing src/sage/combinat/integer_list_old.py --- src/sage/combinat/integer_list_old.py | 1214 ------------------------- 1 file changed, 1214 deletions(-) delete mode 100644 src/sage/combinat/integer_list_old.py diff --git a/src/sage/combinat/integer_list_old.py b/src/sage/combinat/integer_list_old.py deleted file mode 100644 index cdd420bb79e..00000000000 --- a/src/sage/combinat/integer_list_old.py +++ /dev/null @@ -1,1214 +0,0 @@ -r""" -Tools for generating lists of integers in lexicographic order - -IMPORTANT NOTE (2009/02): -The internal functions in this file will be deprecated soon. -Please only use them through :class:`IntegerListsLex`. - -AUTHORS: - -- Mike Hansen - -- Travis Scrimshaw (2012-05-12): Fixed errors when returning ``None`` from - first. Added checks to make sure ``max_slope`` is satisfied. - -- Travis Scrimshaw (2012-10-29): Made ``IntegerListsLex`` into a parent with - the element class ``IntegerListsLexElement``. -""" -# **************************************************************************** -# Copyright (C) 2007 Mike Hansen , -# Copyright (C) 2012 Travis Scrimshaw -# -# Distributed under the terms of the GNU General Public License (GPL) -# -# This code is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# The full text of the GPL is available at: -# -# https://www.gnu.org/licenses/ -# **************************************************************************** - -from sage.arith.all import binomial -from sage.rings.integer_ring import ZZ -from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets -from sage.structure.parent import Parent -from sage.structure.list_clone import ClonableArray -from sage.misc.stopgap import stopgap - - -def first(n, min_length, max_length, floor, ceiling, min_slope, max_slope): - """ - Return the lexicographically smallest valid composition of ``n`` - satisfying the conditions. - - .. warning:: - - INTERNAL FUNCTION! DO NOT USE DIRECTLY! - - .. TODO:: - - Move this into Cython. - - Preconditions: - - - ``floor`` and ``ceiling`` need to satisfy the slope constraints, - e.g. be obtained ``fromcomp2floor`` or ``comp2ceil`` - - - ``floor`` must be below ``ceiling`` to ensure - the existence a valid composition - - TESTS:: - - sage: import sage.combinat.integer_list_old as integer_list - sage: f = lambda l: lambda i: l[i-1] - sage: f([0,1,2,3,4,5])(1) - 0 - sage: integer_list.first(12, 4, 4, f([0,0,0,0]), f([4,4,4,4]), -1, 1) - [4, 3, 3, 2] - sage: integer_list.first(36, 9, 9, f([3,3,3,2,1,1,0,0,0]), f([7,6,5,5,5,5,5,4,4]), -1, 1) - [7, 6, 5, 5, 4, 3, 3, 2, 1] - sage: integer_list.first(25, 9, 9, f([3,3,3,2,1,1,0,0,0]), f([7,6,5,5,5,5,5,4,4]), -2, 1) - [7, 6, 5, 4, 2, 1, 0, 0, 0] - sage: integer_list.first(36, 9, 9, f([3,3,3,2,1,4,2,0,0]), f([7,6,5,5,5,5,5,4,4]), -2, 1) - [7, 6, 5, 5, 5, 4, 3, 1, 0] - - :: - - sage: I = integer_list.IntegerListsLex(6, max_slope=2, min_slope=2) - sage: list(I) - [[6], [2, 4], [0, 2, 4]] - """ - stopgap("First uses the old implementation of IntegerListsLex, which does not allow for arbitrary input;" - " non-allowed input can return wrong results," - " please see the documentation for IntegerListsLex for details.", - 17548) - # Check trivial cases, and standardize min_length to be at least 1 - if n < 0: - return None - if max_length <= 0: - if n == 0: - return [] - return None - if min_length <= 0: - if n == 0: - return [] - min_length = 1 - - # Increase min_length until n <= sum([ceiling(i) for i in range(min_length)]) - # This may run forever! - # Find the actual length the list needs to be - N = 0 - for i in range(1, min_length + 1): - ceil = ceiling(i) - if ceil < floor(i): - return None - N += ceil - while N < n: - min_length += 1 - if min_length > max_length: - return None - - ceil = ceiling(min_length) - if ceil == 0 and max_slope <= 0 or ceil < floor(min_length): - return None - - N += ceil - - # Trivial case - if min_length == 1: - if n < floor(1): - return None - return [n] - - if max_slope < min_slope: - return None - - # Compute the minimum values - # We are constrained below by the max slope - result = [floor(min_length)] - n -= floor(min_length) - for i in reversed(range(1, min_length)): - result.insert(0, max(floor(i), result[0] - max_slope)) - n -= result[0] - if n < 0: - return None - - if n == 0: # There is nothing more to do - return result - - if min_slope == float('-inf'): - for i in range(1, min_length+1): - if n <= ceiling(i) - result[i-1]: # -1 for indexing - result[i-1] += n - break - else: - n -= ceiling(i) - result[i-1] - result[i-1] = ceiling(i) - else: - low_x = 1 - low_y = result[0] - high_x = 1 - high_y = result[0] - - while n > 0: - # invariant after each iteration of the loop: - # [low_x, low_y] is the coordinate of the rightmost point of the - # current diagonal s.t. result[low_x] < low_y - low_y += 1 - while low_x < min_length and low_y + min_slope > result[low_x]: - low_x += 1 - low_y += min_slope - - high_y += 1 - while high_y > ceiling(high_x): - high_x += 1 - high_y += min_slope - - n -= low_x - high_x + 1 - - for j in range(1, high_x): - result[j-1] = ceiling(j) - for i in range(0, -n): - result[high_x+i-1] = high_y + min_slope * i - 1 - for i in range(-n, low_x-high_x+1): - result[high_x+i-1] = high_y + min_slope * i - - # Special check for equal slopes - if min_slope == max_slope and any(val + min_slope != result[i + 1] - for i, val in enumerate(result[:-1])): - return None - - return result - - -def lower_regular(comp, min_slope, max_slope): - """ - Return the uppest regular composition below ``comp`` - - TESTS:: - - sage: import sage.combinat.integer_list_old as integer_list - sage: integer_list.lower_regular([4,2,6], -1, 1) - [3, 2, 3] - sage: integer_list.lower_regular([4,2,6], -1, infinity) - [3, 2, 6] - sage: integer_list.lower_regular([1,4,2], -1, 1) - [1, 2, 2] - sage: integer_list.lower_regular([4,2,6,3,7], -2, 1) - [4, 2, 3, 3, 4] - sage: integer_list.lower_regular([4,2,infinity,3,7], -2, 1) - [4, 2, 3, 3, 4] - sage: integer_list.lower_regular([1, infinity, 2], -1, 1) - [1, 2, 2] - sage: integer_list.lower_regular([infinity, 4, 2], -1, 1) - [4, 3, 2] - """ - new_comp = comp[:] - for i in range(1, len(new_comp)): - new_comp[i] = min(new_comp[i], new_comp[i-1] + max_slope) - - for i in reversed(range(len(new_comp)-1)): - new_comp[i] = min(new_comp[i], new_comp[i+1] - min_slope) - - return new_comp - - -def rightmost_pivot(comp, min_length, max_length, floor, ceiling, min_slope, max_slope): - """ - TESTS:: - - sage: import sage.combinat.integer_list_old as integer_list - sage: f = lambda l: lambda i: l[i-1] - sage: integer_list.rightmost_pivot([7,6,5,5,4,3,3,2,1], 9, 9, f([3,3,3,2,1,1,0,0,0]), f([7,6,5,5,5,5,5,4,4]), -1, 0) - [7, 2] - sage: integer_list.rightmost_pivot([7,6,5,5,4,3,3,2,1], 9, 9,f([3,3,3,2,1,1,0,0,0]), f([7,6,5,5,5,5,5,4,4]), -2, 0) - [7, 1] - sage: integer_list.rightmost_pivot([7,6,5,5,4,3,3,2,1], 9, 9,f([3,3,3,2,1,1,0,0,0]), f([7,6,5,5,5,5,5,4,4]), -2, 4) - [8, 1] - sage: integer_list.rightmost_pivot([7,6,5,5,4,3,3,2,1], 9, 9,f([3,3,3,2,1,1,0,0,0]), f([7,6,5,5,5,5,5,4,4]), -2, 1) - [8, 1] - sage: integer_list.rightmost_pivot([7,6,5,5,5,5,5,4,4], 9, 9,f([3,3,3,2,1,1,0,0,0]), f([7,6,5,5,5,5,5,4,4]), -2, 1) - sage: integer_list.rightmost_pivot([3,3,3,2,1,1,0,0,0], 9, 9,f([3,3,3,2,1,1,0,0,0]), f([7,6,5,5,5,5,5,4,4]), -2, 1) - sage: g = lambda x: lambda i: x - sage: integer_list.rightmost_pivot([1],1,1,g(0),g(2),-10, 10) - sage: integer_list.rightmost_pivot([1,2],2,2,g(0),g(2),-10, 10) - sage: integer_list.rightmost_pivot([1,2],2,2,g(1),g(2), -10, 10) - sage: integer_list.rightmost_pivot([1,2],2,3,g(1),g(2), -10, 10) - [2, 1] - sage: integer_list.rightmost_pivot([2,2],2,3,g(2),g(2),-10, 10) - sage: integer_list.rightmost_pivot([2,3],2,3,g(2),g(2),-10,+10) - sage: integer_list.rightmost_pivot([3,2],2,3,g(2),g(2),-10,+10) - sage: integer_list.rightmost_pivot([3,3],2,3,g(2),g(2),-10,+10) - [1, 2] - sage: integer_list.rightmost_pivot([6],1,3,g(0),g(6),-1,0) - [1, 0] - sage: integer_list.rightmost_pivot([6],1,3,g(0),g(6),-2,0) - [1, 0] - sage: integer_list.rightmost_pivot([7,9,8,7],1,5,g(0),g(10),-1,10) - [2, 6] - sage: integer_list.rightmost_pivot([7,9,8,7],1,5,g(5),g(10),-10,10) - [3, 5] - sage: integer_list.rightmost_pivot([7,9,8,7],1,5,g(5),g(10),-1,10) - [2, 6] - sage: integer_list.rightmost_pivot([7,9,8,7],1,5,g(4),g(10),-2,10) - [3, 7] - sage: integer_list.rightmost_pivot([9,8,7],1,4,g(4),g(10),-2,0) - [1, 4] - sage: integer_list.rightmost_pivot([1,3],1,5,lambda i: i,g(10),-10,10) - sage: integer_list.rightmost_pivot([1,4],1,5,lambda i: i,g(10),-10,10) - sage: integer_list.rightmost_pivot([2,4],1,5,lambda i: i,g(10),-10,10) - [1, 1] - """ - if max_slope < min_slope: - return None - - x = len(comp) - if x == 0: - return None - - y = len(comp) + 1 - while y <= max_length: - if ceiling(y) > 0: - break - if max_slope <= 0: - y = max_length + 1 - break - y += 1 - - ceilingx_x = comp[x - 1]-1 - floorx_x = floor(x) - if x > 1: - floorx_x = max(floorx_x, comp[x - 2] + min_slope) - - F = comp[x - 1] - floorx_x - G = ceilingx_x - comp[x - 1] # this is -1 - - highX = x - lowX = x - - while not (ceilingx_x >= floorx_x and - (G >= 0 or - (y < max_length + 1 and - F - max(floor(y), floorx_x + (y - x) * min_slope) >= 0 and - G + min(ceiling(y), ceilingx_x + (y - x) * max_slope) >= 0))): - - if x == 1: - return None - - x -= 1 - - oldfloorx_x = floorx_x - ceilingx_x = comp[x-1] - 1 - floorx_x = floor(x) - if x > 1: - floorx_x = max(floorx_x, comp[x-2] + min_slope) - - min_slope_lowX = min_slope * (lowX - x) - max_slope_highX = max_slope * (highX - x) - - # Update G - if max_slope == float('+inf'): - # In this case, we have - # -- ceiling_x(i) = ceiling(i) for i > x - # --G >= 0 or G = -1 - G += ceiling(x + 1) - comp[x] - else: - G += (highX - x) * ((comp[x-1] + max_slope) - comp[x]) - 1 - temp = (ceilingx_x + max_slope_highX) - ceiling(highX) - while highX > x and temp >= 0: - G -= temp - highX -= 1 - max_slope_highX = max_slope * (highX-x) - temp = (ceilingx_x + max_slope_highX) - ceiling(highX) - - if G >= 0 and comp[x-1] > floorx_x: - # By case 1, x is at the rightmost pivot position - break - - # Update F - if y < max_length+1: - F += comp[x-1] - floorx_x - if min_slope != float('-inf'): - F += (lowX - x) * (oldfloorx_x - (floorx_x + min_slope)) - temp = floor(lowX) - (floorx_x + min_slope_lowX) - while lowX > x and temp >= 0: - F -= temp - lowX -= 1 - min_slope_lowX = min_slope * (lowX-x) - temp = floor(lowX) - (floorx_x + min_slope_lowX) - - return [x, floorx_x] - - -def next(comp, min_length, max_length, floor, ceiling, min_slope, max_slope): - """ - Return the next integer list after ``comp`` that satisfies the - constraints. - - .. WARNING:: - - INTERNAL FUNCTION! DO NOT USE DIRECTLY! - - EXAMPLES:: - - sage: from sage.combinat.integer_list_old import next - sage: IV = sage.combinat.integer_list_old.IntegerListsLex(n=2,length=3,min_slope=0) - sage: next([0,1,1], 3, 3, lambda i: 0, lambda i: 5, 0, 10) - [0, 0, 2] - """ - stopgap("Next uses the old implementation of IntegerListsLex, which does not allow for arbitrary input;" - " non-allowed input can return wrong results," - " please see the documentation for IntegerListsLex for details.", - 17548) - x = rightmost_pivot(comp, min_length, max_length, floor, ceiling, min_slope, max_slope) - if x is None: - return None - [x, low] = x - high = comp[x-1] - 1 - -# // Build wrappers around floor and ceiling to take into -# // account the new constraints on the value of compo[x]. -# // -# // Efficiency note: they are not wrapped more than once, since -# // the method Next calls first, but not the converse. - - if min_slope == float('-inf'): - new_floor = lambda i: floor(x+(i-1)) - else: - new_floor = lambda i: max(floor(x+(i-1)), low+(i-1)*min_slope) - - if max_slope == float('+inf'): - new_ceiling = lambda i: comp[x-1] - 1 if i == 1 else ceiling(x+(i-1)) - else: - new_ceiling = lambda i: min(ceiling(x+(i-1)), high+(i-1)*max_slope) - - res = [] - res += comp[:x-1] - f = first(sum(comp[x-1:]), max(min_length-x+1, 0), max_length-x+1, - new_floor, new_ceiling, min_slope, max_slope) - if f is None: # Check to make sure it is valid - return None - res += f - return res - - -def iterator(n, min_length, max_length, floor, ceiling, min_slope, max_slope): - """ - .. WARNING:: - - INTERNAL FUNCTION! DO NOT USE DIRECTLY! - - EXAMPLES:: - - sage: from sage.combinat.integer_list_old import iterator - sage: IV = sage.combinat.integer_list_old.IntegerListsLex(n=2,length=3,min_slope=0) - sage: list(iterator(2, 3, 3, lambda i: 0, lambda i: 5, 0, 10)) - [[0, 1, 1], [0, 0, 2]] - """ - stopgap("Iterator uses the old implementation of IntegerListsLex, which does not allow for arbitrary input;" - " non-allowed input can return wrong results," - " please see the documentation for IntegerListsLex for details.", - 17548) - succ = lambda x: next(x, min_length, max_length, floor, ceiling, min_slope, max_slope) - - # Handle the case where n is a list of integers - if isinstance(n, list): - for i in range(n[0], min(n[1]+1, upper_bound(min_length, max_length, floor, ceiling, min_slope, max_slope))): - for el in iterator(i, min_length, max_length, floor, ceiling, min_slope, max_slope): - yield el - else: - f = first(n, min_length, max_length, floor, ceiling, min_slope, max_slope) - while f is not None: - yield f - f = succ(f) - - -def upper_regular(comp, min_slope, max_slope): - """ - Return the uppest regular composition above ``comp``. - - TESTS:: - - sage: import sage.combinat.integer_list_old as integer_list - sage: integer_list.upper_regular([4,2,6],-1,1) - [4, 5, 6] - sage: integer_list.upper_regular([4,2,6],-2, 1) - [4, 5, 6] - sage: integer_list.upper_regular([4,2,6,3,7],-2, 1) - [4, 5, 6, 6, 7] - sage: integer_list.upper_regular([4,2,6,1], -2, 1) - [4, 5, 6, 4] - """ - - new_comp = comp[:] - for i in range(1, len(new_comp)): - new_comp[i] = max(new_comp[i], new_comp[i-1] + min_slope) - - for i in reversed(range(len(new_comp)-1)): - new_comp[i] = max(new_comp[i], new_comp[i+1] - max_slope) - - return new_comp - - -def comp2floor(f, min_slope, max_slope): - """ - Given a composition, returns the lowest regular function N->N above - it. - - EXAMPLES:: - - sage: from sage.combinat.integer_list_old import comp2floor - sage: f = comp2floor([2, 1, 1],-1,0) - sage: [f(i) for i in range(10)] - [2, 1, 1, 1, 2, 3, 4, 5, 6, 7] - """ - if not f: - return lambda i: 0 - floor = upper_regular(f, min_slope, max_slope) - return lambda i: floor[i] if i < len(floor) else max(0, floor[-1]-(i-len(floor))*min_slope) - - -def comp2ceil(c, min_slope, max_slope): - """ - Given a composition, return the lowest regular function N->N below it. - - EXAMPLES:: - - sage: from sage.combinat.integer_list_old import comp2ceil - sage: f = comp2ceil([2, 1, 1],-1,0) - sage: [f(i) for i in range(10)] - [2, 1, 1, 1, 2, 3, 4, 5, 6, 7] - """ - if not c: - return lambda i: 0 - ceil = lower_regular(c, min_slope, max_slope) - return lambda i: ceil[i] if i < len(ceil) else max(0, ceil[-1]-(i-len(ceil))*min_slope) - - -def upper_bound(min_length, max_length, floor, ceiling, min_slope, max_slope): - """ - Compute a coarse upper bound on the size of a vector satisfying the - constraints. - - TESTS:: - - sage: import sage.combinat.integer_list_old as integer_list - sage: f = lambda x: lambda i: x - sage: integer_list.upper_bound(0,4,f(0), f(1),-infinity,infinity) - 4 - sage: integer_list.upper_bound(0, infinity, f(0), f(1), -infinity, infinity) - inf - sage: integer_list.upper_bound(0, infinity, f(0), f(1), -infinity, -1) - 1 - sage: integer_list.upper_bound(0, infinity, f(0), f(5), -infinity, -1) - 15 - sage: integer_list.upper_bound(0, infinity, f(0), f(5), -infinity, -2) - 9 - """ - from sage.functions.all import floor as flr - if max_length < float('inf'): - return sum([ceiling(j) for j in range(max_length)]) - elif max_slope < 0 and ceiling(1) < float('inf'): - maxl = flr(-ceiling(1) / max_slope) - return ceiling(1) * (maxl + 1) + binomial(maxl + 1, 2) * max_slope - # FIXME: only checking the first 10000 values, but that should generally - # be enough - elif [ceiling(j) for j in range(10000)] == [0] * 10000: - return 0 - else: - return float('inf') - - -def is_a(comp, min_length, max_length, floor, ceiling, min_slope, max_slope): - """ - Return ``True`` if ``comp`` meets the constraints imposed by the - arguments. - - .. WARNING:: - - INTERNAL FUNCTION! DO NOT USE DIRECTLY! - - EXAMPLES:: - - sage: from sage.combinat.integer_list_old import is_a - sage: IV = sage.combinat.integer_list_old.IntegerListsLex(n=2,length=3,min_slope=0) - sage: all(is_a(iv, 3, 3, lambda i: 0, lambda i: 5, 0, 10) for iv in IV) - True - """ - if not(min_length <= len(comp) <= max_length): - return False - for i in range(len(comp)): - if not(floor(i + 1) <= comp[i] <= ceiling(i + 1)): - return False - for i in range(len(comp) - 1): - slope = comp[i + 1] - comp[i] - if not(min_slope <= slope <= max_slope): - return False - return True - - -class IntegerListsLexElement(ClonableArray): - """ - Element class for :class:`IntegerListsLex`. - """ - def check(self): - """ - Check to make sure this is a valid element in its - :class:`IntegerListsLex` parent. - - .. TODO:: Placeholder. Implement a proper check. - - EXAMPLES:: - - sage: C = IntegerListsLex(4) - sage: C([4]).check() - True - """ - return True - - -class IntegerListsLex(Parent): - r""" - A combinatorial class `C` for integer lists satisfying certain - sum, length, upper/lower bound and regularity constraints. The - purpose of this tool is mostly to provide a Constant Amortized - Time iterator through those lists, in lexicographic order. - - INPUT: - - - ``n`` -- a non negative integer - - ``min_length`` -- a non negative integer - - ``max_length`` -- an integer or `\infty` - - ``length`` -- an integer; overrides min_length and max_length if - specified - - ``min_part`` -- the minimum value of each part; defaults to ``0`` - - ``max_part`` -- the maximum value of each part; defaults to `+\infty` - - ``floor`` -- a function `f` (or list); defaults to - ``lambda i: min_part`` - - ``ceiling`` -- a function `f` (or list); defaults to - ``lambda i: max_part`` - - ``min_slope`` -- an integer or `-\infty`; defaults to `-\infty` - - ``max_slope`` -- an integer or `+\infty`; defaults to `+\infty` - - An *integer list* is a list `l` of nonnegative integers, its - *parts*. The *length* of `l` is the number of its parts; - the *sum* of `l` is the sum of its parts. - - .. NOTE:: - - Two valid integer lists are considered equivalent if they only - differ by trailing zeroes. In this case, only the list with the - least number of trailing zeroes will be produced. - - The constraints on the lists are as follow: - - - Sum: `sum(l) == n` - - - Length: ``min_length <= len(l) <= max_length`` - - - Lower and upper bounds: ``floor(i) <= l[i] <= ceiling(i)``, for - ``i`` from 0 to ``len(l)`` - - - Regularity condition: ``minSlope <= l[i+1]-l[i] <= maxSlope``, - for ``i`` from 0 to ``len(l)-1`` - - This is a generic low level tool. The interface has been designed - with efficiency in mind. It is subject to incompatible changes in - the future. More user friendly interfaces are provided by high - level tools like :class:`Partitions` or :class:`Compositions`. - - EXAMPLES: - - We create the combinatorial class of lists of length 3 and sum 2:: - - sage: import sage.combinat.integer_list_old as integer_list - sage: C = integer_list.IntegerListsLex(2, length=3) - sage: C - Integer lists of sum 2 satisfying certain constraints - sage: C.cardinality() - 6 - sage: [p for p in C] - [[2, 0, 0], [1, 1, 0], [1, 0, 1], [0, 2, 0], [0, 1, 1], [0, 0, 2]] - - sage: [2, 0, 0] in C - True - sage: [2, 0, 1] in C - False - sage: "a" in C - False - sage: ["a"] in C - False - - sage: C.first() - [2, 0, 0] - - One can specify lower and upper bound on each part:: - - sage: list(integer_list.IntegerListsLex(5, length = 3, floor = [1,2,0], ceiling = [3,2,3])) - [[3, 2, 0], [2, 2, 1], [1, 2, 2]] - - Using the slope condition, one can generate integer partitions - (but see :mod:`sage.combinat.partition.Partitions`):: - - sage: list(integer_list.IntegerListsLex(4, max_slope=0)) - [[4], [3, 1], [2, 2], [2, 1, 1], [1, 1, 1, 1]] - - This is the list of all partitions of `7` with parts at least `2`:: - - sage: list(integer_list.IntegerListsLex(7, max_slope = 0, min_part = 2)) - [[7], [5, 2], [4, 3], [3, 2, 2]] - - This is the list of all partitions of `5` and length at most 3 - which are bounded below by [2,1,1]:: - - sage: list(integer_list.IntegerListsLex(5, max_slope = 0, max_length = 3, floor = [2,1,1])) - [[5], [4, 1], [3, 2], [3, 1, 1], [2, 2, 1]] - - Note that ``[5]`` is considered valid, because the lower bound - constraint only apply to existing positions in the list. To - obtain instead the partitions containing ``[2,1,1]``, one need to - use ``min_length``:: - - sage: list(integer_list.IntegerListsLex(5, max_slope = 0, min_length = 3, max_length = 3, floor = [2,1,1])) - [[3, 1, 1], [2, 2, 1]] - - This is the list of all partitions of `5` which are contained in - ``[3,2,2]``:: - - sage: list(integer_list.IntegerListsLex(5, max_slope = 0, max_length = 3, ceiling = [3,2,2])) - [[3, 2], [3, 1, 1], [2, 2, 1]] - - This is the list of all compositions of `4` (but see Compositions):: - - sage: list(integer_list.IntegerListsLex(4, min_part = 1)) - [[4], [3, 1], [2, 2], [2, 1, 1], [1, 3], [1, 2, 1], [1, 1, 2], [1, 1, 1, 1]] - - This is the list of all integer vectors of sum `4` and length `3`:: - - sage: list(integer_list.IntegerListsLex(4, length = 3)) - [[4, 0, 0], [3, 1, 0], [3, 0, 1], [2, 2, 0], [2, 1, 1], - [2, 0, 2], [1, 3, 0], [1, 2, 1], [1, 1, 2], [1, 0, 3], - [0, 4, 0], [0, 3, 1], [0, 2, 2], [0, 1, 3], [0, 0, 4]] - - There are all the lists of sum 4 and length 4 such that l[i] <= i:: - - sage: list(integer_list.IntegerListsLex(4, length=4, ceiling=lambda i: i)) - [[0, 1, 2, 1], [0, 1, 1, 2], [0, 1, 0, 3], [0, 0, 2, 2], [0, 0, 1, 3]] - - This is the list of all monomials of degree `4` which divide the - monomial `x^3y^1z^2` (a monomial being identified with its - exponent vector):: - - sage: R. = QQ[] - sage: m = [3,1,2] - sage: def term(exponents): - ....: return x^exponents[0] * y^exponents[1] * z^exponents[2] - sage: list( integer_list.IntegerListsLex(4, length = len(m), ceiling = m, element_constructor = term) ) - [x^3*y, x^3*z, x^2*y*z, x^2*z^2, x*y*z^2] - - Note the use of the element_constructor feature. - - In general, the complexity of the iteration algorithm is constant - time amortized for each integer list produced. There is one - degenerate case though where the algorithm may run forever without - producing anything. If max_length is `+\infty` and max_slope `>0`, - testing whether there exists a valid integer list of sum `n` may - be only semi-decidable. In the following example, the algorithm - will enter an infinite loop, because it needs to decide whether - `ceiling(i)` is nonzero for some `i`:: - - sage: list( integer_list.IntegerListsLex(1, ceiling = lambda i: 0) ) # todo: not implemented - - .. NOTE:: - - Caveat: counting is done by brute force generation. In some - special cases, it would be possible to do better by counting - techniques for integral point in polytopes. - - .. NOTE:: - - Caveat: with the current implementation, the constraints should - satisfy the following conditions: - - - The upper and lower bounds themselves should satisfy the - slope constraints. - - - The maximal and minimal part values should not be equal. - - Those conditions are not always checked by the algorithm, and the - result may be completely incorrect if they are not satisfied: - - In the following example, the floor conditions do not satisfy the - slope conditions since the floor for the third part is also 3:: - - sage: I = integer_list.IntegerListsLex(16, min_length=2, min_part=3, max_slope=-1, floor=[5,3]) - Traceback (most recent call last): - ... - ValueError: floor does not satisfy the max slope condition - - Compare this with the following input, which is equivalent - but it bypasses the checks because the floor is a function:: - - sage: f = lambda x: 5 if x == 0 else 3 - sage: I = integer_list.IntegerListsLex(16, min_length=2, max_slope=-1, floor=f) - sage: list(I) - [[13, 3], [12, 4], [11, 5], [10, 6]] - - With some work, this could be fixed without affecting the overall - complexity and efficiency. Also, the generation algorithm could be - extended to deal with non-constant slope constraints and with - negative parts, as well as to accept a range parameter instead of - a single integer for the sum `n` of the lists (the later was - readily implemented in MuPAD-Combinat). Encouragements, - suggestions, and help are welcome. - - .. TODO:: - - Integrate all remaining tests from - http://mupad-combinat.svn.sourceforge.net/viewvc/mupad-combinat/trunk/MuPAD-Combinat/lib/COMBINAT/TEST/MachineIntegerListsLex.tst - - TESTS:: - - sage: g = lambda x: lambda i: x - sage: list(integer_list.IntegerListsLex(0, floor = g(1), min_slope = 0)) - [[]] - sage: list(integer_list.IntegerListsLex(0, floor = g(1), min_slope = 0, max_slope = 0)) - [[]] - sage: list(integer_list.IntegerListsLex(0, max_length=0, floor = g(1), min_slope = 0, max_slope = 0)) - [[]] - sage: list(integer_list.IntegerListsLex(0, max_length=0, floor = g(0), min_slope = 0, max_slope = 0)) - [[]] - sage: list(integer_list.IntegerListsLex(0, min_part = 1, min_slope = 0)) - [[]] - sage: list(integer_list.IntegerListsLex(1, min_part = 1, min_slope = 0)) - [[1]] - sage: list(integer_list.IntegerListsLex(0, min_length = 1, min_part = 1, min_slope = 0)) - [] - sage: list(integer_list.IntegerListsLex(0, min_length = 1, min_slope = 0)) - [[0]] - sage: list(integer_list.IntegerListsLex(3, max_length=2, )) - [[3], [2, 1], [1, 2], [0, 3]] - sage: partitions = {"min_part": 1, "max_slope": 0} - sage: partitions_min_2 = {"floor": g(2), "max_slope": 0} - sage: compositions = {"min_part": 1} - sage: integer_vectors = lambda l: {"length": l} - sage: lower_monomials = lambda c: {"length": c, "floor": lambda i: c[i]} - sage: upper_monomials = lambda c: {"length": c, "ceiling": lambda i: c[i]} - sage: constraints = { "min_part":1, "min_slope": -1, "max_slope": 0} - sage: list(integer_list.IntegerListsLex(6, **partitions)) - [[6], - [5, 1], - [4, 2], - [4, 1, 1], - [3, 3], - [3, 2, 1], - [3, 1, 1, 1], - [2, 2, 2], - [2, 2, 1, 1], - [2, 1, 1, 1, 1], - [1, 1, 1, 1, 1, 1]] - sage: list(integer_list.IntegerListsLex(6, **constraints)) - [[6], - [3, 3], - [3, 2, 1], - [2, 2, 2], - [2, 2, 1, 1], - [2, 1, 1, 1, 1], - [1, 1, 1, 1, 1, 1]] - sage: list(integer_list.IntegerListsLex(1, **partitions_min_2)) - [] - sage: list(integer_list.IntegerListsLex(2, **partitions_min_2)) - [[2]] - sage: list(integer_list.IntegerListsLex(3, **partitions_min_2)) - [[3]] - sage: list(integer_list.IntegerListsLex(4, **partitions_min_2)) - [[4], [2, 2]] - sage: list(integer_list.IntegerListsLex(5, **partitions_min_2)) - [[5], [3, 2]] - sage: list(integer_list.IntegerListsLex(6, **partitions_min_2)) - [[6], [4, 2], [3, 3], [2, 2, 2]] - sage: list(integer_list.IntegerListsLex(7, **partitions_min_2)) - [[7], [5, 2], [4, 3], [3, 2, 2]] - sage: list(integer_list.IntegerListsLex(9, **partitions_min_2)) - [[9], [7, 2], [6, 3], [5, 4], [5, 2, 2], [4, 3, 2], [3, 3, 3], [3, 2, 2, 2]] - sage: list(integer_list.IntegerListsLex(10, **partitions_min_2)) - [[10], - [8, 2], - [7, 3], - [6, 4], - [6, 2, 2], - [5, 5], - [5, 3, 2], - [4, 4, 2], - [4, 3, 3], - [4, 2, 2, 2], - [3, 3, 2, 2], - [2, 2, 2, 2, 2]] - sage: list(integer_list.IntegerListsLex(4, **compositions)) - [[4], [3, 1], [2, 2], [2, 1, 1], [1, 3], [1, 2, 1], [1, 1, 2], [1, 1, 1, 1]] - sage: list(integer_list.IntegerListsLex(6, min_length=1, floor=[7])) - [] - - Noted on :trac:`17898`:: - - sage: list(integer_list.IntegerListsLex(4, min_part=1, length=3, min_slope=1)) - [] - sage: integer_list.IntegerListsLex(6, ceiling=[4,2], floor=[3,3]).list() - [] - sage: integer_list.IntegerListsLex(6, min_part=1, max_part=3, max_slope=-4).list() - [] - """ - def __init__(self, - n, - length = None, min_length=0, max_length=float('+inf'), - floor=None, ceiling = None, - min_part = 0, max_part = float('+inf'), - min_slope=float('-inf'), max_slope=float('+inf'), - name = None, - element_constructor = None, - element_class = None, - global_options = None): - """ - Initialize ``self``. - - TESTS:: - - sage: import sage.combinat.integer_list_old as integer_list - sage: C = integer_list.IntegerListsLex(2, length=3) - sage: C == loads(dumps(C)) - True - sage: C == loads(dumps(C)) # this did fail at some point, really! - True - sage: C is loads(dumps(C)) # todo: not implemented - True - sage: C.cardinality().parent() is ZZ - True - sage: TestSuite(C).run() - """ - stopgap("The old implementation of IntegerListsLex does not allow for arbitrary input;" - " non-allowed input can return wrong results," - " please see the documentation for IntegerListsLex for details.", - 17548) - # Convert to float infinity - from sage.rings.infinity import infinity - if max_slope == infinity: - max_slope = float('+inf') - if min_slope == -infinity: - min_slope = float('-inf') - if max_length == infinity: - max_length = float('inf') - if max_part == infinity: - max_part = float('+inf') - - if floor is None: - self.floor_list = [] - else: - try: - # Is ``floor`` an iterable? - # Not ``floor[:]`` because we want ``self.floor_list`` - # mutable, and applying [:] to a tuple gives a tuple. - self.floor_list = list(floor) - # Make sure the floor list will make the list satisfy the constraints - if min_slope != float('-inf'): - for i in range(1, len(self.floor_list)): - self.floor_list[i] = max(self.floor_list[i], self.floor_list[i-1] + min_slope) - - # Some input checking - for i in range(1, len(self.floor_list)): - if self.floor_list[i] - self.floor_list[i-1] > max_slope: - raise ValueError("floor does not satisfy the max slope condition") - if self.floor_list and min_part - self.floor_list[-1] > max_slope: - raise ValueError("floor does not satisfy the max slope condition") - except TypeError: - self.floor = floor - if ceiling is None: - self.ceiling_list = [] - else: - try: - # Is ``ceiling`` an iterable? - self.ceiling_list = list(ceiling) - # Make sure the ceiling list will make the list satisfy the constraints - if max_slope != float('+inf'): - for i in range(1, len(self.ceiling_list)): - self.ceiling_list[i] = min(self.ceiling_list[i], self.ceiling_list[i-1] + max_slope) - - # Some input checking - for i in range(1, len(self.ceiling_list)): - if self.ceiling_list[i] - self.ceiling_list[i-1] < min_slope: - raise ValueError("ceiling does not satisfy the min slope condition") - if self.ceiling_list and max_part - self.ceiling_list[-1] < min_slope: - raise ValueError("ceiling does not satisfy the min slope condition") - except TypeError: - # ``ceiling`` is not an iterable. - self.ceiling = ceiling - if name is not None: - self.rename(name) - if n in ZZ: - self.n = n - self.n_range = [n] - else: - self.n_range = n - if length is not None: - min_length = length - max_length = length - self.min_length = min_length - self.max_length = max_length - self.min_part = min_part - self.max_part = max_part - # FIXME: the internal functions currently assume that floor and ceiling start at 1 - # this is a workaround - self.max_slope = max_slope - self.min_slope = min_slope - if element_constructor is not None: - self._element_constructor_ = element_constructor - if element_class is not None: - self.Element = element_class - if global_options is not None: - self.global_options = global_options - Parent.__init__(self, category=FiniteEnumeratedSets()) - - Element = IntegerListsLexElement - - def _element_constructor_(self, lst): - """ - Construct an element with ``self`` as parent. - - EXAMPLES:: - - sage: import sage.combinat.integer_list_old as integer_list - sage: C = integer_list.IntegerListsLex(4) - sage: C([4]) - [4] - """ - return self.element_class(self, lst) - - def __eq__(self, x): - """ - Compare two different :class:`IntegerListsLex`. - - For now, the comparison is done just on their repr's which is - not robust! - - EXAMPLES:: - - sage: import sage.combinat.integer_list_old as integer_list - sage: C = integer_list.IntegerListsLex(2, length=3) - sage: D = integer_list.IntegerListsLex(4, length=3) - sage: repr(C) == repr(D) - False - sage: C == D - False - """ - return repr(self) == repr(x) - - def __ne__(self, other): - """ - Compare two different :class:`IntegerListsLex`. - - For now, the comparison is done just on their repr's which is - not robust! - - EXAMPLES:: - - sage: import sage.combinat.integer_list_old as integer_list - sage: C = integer_list.IntegerListsLex(2, length=3) - sage: D = integer_list.IntegerListsLex(4, length=3) - sage: C != D - True - """ - return not self.__eq__(other) - - def __hash__(self): - """ - Compute a hash for ``self``. - - EXAMPLES:: - - sage: import sage.combinat.integer_list_old as integer_list - sage: C = integer_list.IntegerListsLex(2, length=3) - sage: h = hash(C) - """ - return hash(repr(self)) ^ 53397379531 - - def _repr_(self): - """ - Return the name of this combinatorial class. - - EXAMPLES:: - - sage: import sage.combinat.integer_list_old as integer_list - sage: C = integer_list.IntegerListsLex(2, length=3) - sage: C # indirect doctest - Integer lists of sum 2 satisfying certain constraints - - sage: C = integer_list.IntegerListsLex([1,2,4], length=3) - sage: C # indirect doctest - Integer lists of sum in [1, 2, 4] satisfying certain constraints - - sage: C = integer_list.IntegerListsLex([1,2,4], length=3, name="A given name") - sage: C - A given name - """ - if hasattr(self, "n"): - return "Integer lists of sum %s satisfying certain constraints" % self.n - - return "Integer lists of sum in %s satisfying certain constraints" % self.n_range - - def floor(self, i): - """ - Return the minimum part that can appear at the `i^{th}` position of - any list produced. - - EXAMPLES:: - - sage: import sage.combinat.integer_list_old as integer_list - sage: C = integer_list.IntegerListsLex(4, length=2, min_part=1) - sage: C.floor(0) - 1 - sage: C = integer_list.IntegerListsLex(4, length=2, floor=[1,2]) - sage: C.floor(0) - 1 - sage: C.floor(1) - 2 - """ - if i < len(self.floor_list): - return max(self.min_part, self.floor_list[i]) - if self.min_slope != float('-inf') and self.min_slope > 0: - return self.min_part + (i - len(self.floor_list)) * self.min_slope - return self.min_part - - def ceiling(self, i): - """ - Return the maximum part that can appear in the `i^{th}` - position in any list produced. - - EXAMPLES:: - - sage: import sage.combinat.integer_list_old as integer_list - sage: C = integer_list.IntegerListsLex(4, length=2, max_part=3) - sage: C.ceiling(0) - 3 - sage: C = integer_list.IntegerListsLex(4, length=2, ceiling=[3,2]) - sage: C.ceiling(0) - 3 - sage: C.ceiling(1) - 2 - """ - if i < len(self.ceiling_list): - return min(self.max_part, self.ceiling_list[i]) - if self.max_slope != float('inf') and self.max_slope < 0: - return self.max_part + (i - len(self.ceiling_list)) * self.max_slope - return self.max_part - - # Temporary adapter to use the preexisting list/iterator/is_a function above. - # FIXME: fix their specs so that floor and ceiling start from 0 instead of 1... - # FIXME: integrate them as methods of this class - def build_args(self): - """ - Return a list of arguments that can be passed into the pre-existing - ``first``, ``next``, ``is_a``, ... functions in this module. - - ``n`` is currently not included in this list. - - EXAMPLES:: - - sage: import sage.combinat.integer_list_old as integer_list - sage: C = integer_list.IntegerListsLex(2, length=3) - sage: C.build_args() - [3, - 3, - at 0x...>, - at 0x...>, - -inf, - inf] - """ - return [self.min_length, self.max_length, - lambda i: self.floor(i - 1), lambda i: self.ceiling(i - 1), - self.min_slope, self.max_slope] - - def first(self): - """ - Return the lexicographically maximal element in ``self``. - - EXAMPLES:: - - sage: import sage.combinat.integer_list_old as integer_list - sage: C = integer_list.IntegerListsLex(2, length=3) - sage: C.first() - [2, 0, 0] - """ - # Make sure we have a valid return - f = first(self.n_range[0], *(self.build_args())) - if f is None: - return None - return self._element_constructor_(f) - - def __iter__(self): - """ - Return an iterator for the elements of ``self``. - - EXAMPLES:: - - sage: import sage.combinat.integer_list_old as integer_list - sage: C = integer_list.IntegerListsLex(2, length=3) - sage: list(C) #indirect doctest - [[2, 0, 0], [1, 1, 0], [1, 0, 1], [0, 2, 0], [0, 1, 1], [0, 0, 2]] - """ - args = self.build_args() - for n in self.n_range: - l = first(n, *args) - while l is not None: - yield self._element_constructor_(l) - l = next(l, *args) - - def count(self): - """ - Default brute force implementation of count by iteration - through all the objects. - - Note that this skips the call to ``_element_constructor_``, - unlike the default implementation. - - .. TODO:: - - Do the iteration in place to save on copying time - - EXAMPLES:: - - sage: import sage.combinat.integer_list_old as integer_list - sage: C = integer_list.IntegerListsLex(2, length=3) - sage: C.cardinality() == C.count() - True - """ - args = self.build_args() - c = ZZ(0) - for n in self.n_range: - l = first(n, *args) - while l is not None: - c += 1 - l = next(l, *args) - return c - - def __contains__(self, v): - """ - Return ``True`` if and only if ``v`` is in ``self``. - - EXAMPLES:: - - sage: import sage.combinat.integer_list_old as integer_list - sage: C = integer_list.IntegerListsLex(2, length=3) - sage: [2, 0, 0] in C - True - sage: [2, 0] in C - False - sage: [3, 0, 0] in C - False - sage: all(v in C for v in C) - True - """ - if isinstance(v, (self.element_class, list)): - return is_a(v, *(self.build_args())) and sum(v) in self.n_range - return False From fee15659e1d8b0de44b03564bb347d743c333f19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Mon, 11 Oct 2021 20:56:07 +0200 Subject: [PATCH 334/359] using itertools.chain in abstact_tree + remove long doctest in ncsf --- src/sage/combinat/abstract_tree.py | 56 +++++++++++++---------------- src/sage/combinat/ncsf_qsym/ncsf.py | 2 -- 2 files changed, 24 insertions(+), 34 deletions(-) diff --git a/src/sage/combinat/abstract_tree.py b/src/sage/combinat/abstract_tree.py index 90b278a05ef..65fec9cacdd 100644 --- a/src/sage/combinat/abstract_tree.py +++ b/src/sage/combinat/abstract_tree.py @@ -62,6 +62,7 @@ - Florent Hivert (2010-2011): initial revision - Frédéric Chapoton (2011): contributed some methods """ +import itertools from sage.structure.list_clone import ClonableArray from sage.rings.integer import Integer @@ -195,15 +196,8 @@ def pre_order_traversal_iter(self): if self.is_empty(): return yield self - # TODO:: PYTHON 3 - # import itertools - # yield from itertools.chain(map( - # lambda c: c.pre_order_traversal_iter(), - # self - # )) - for children in self: - for node in children.pre_order_traversal_iter(): - yield node + yield from itertools.chain(*[c.pre_order_traversal_iter() + for c in self]) def iterative_pre_order_traversal(self, action=None): r""" @@ -275,7 +269,8 @@ def iterative_pre_order_traversal(self, action=None): if self.is_empty(): return if action is None: - action = lambda x: None + def action(x): + return None stack = [] stack.append(self) while stack: @@ -390,7 +385,8 @@ def pre_order_traversal(self, action=None): 7 """ if action is None: - action = lambda x: None + def action(x): + return None for node in self.pre_order_traversal_iter(): action(node) @@ -484,15 +480,8 @@ def post_order_traversal_iter(self): """ if self.is_empty(): return - # TODO:: PYTHON 3 - # import itertools - # yield from itertools.chain(map( - # lambda c: c.post_order_traversal_iter(), - # self - # )) - for children in self: - for node in children.post_order_traversal_iter(): - yield node + yield from itertools.chain(*[c.post_order_traversal_iter() + for c in self]) yield self def post_order_traversal(self, action=None): @@ -563,7 +552,8 @@ def post_order_traversal(self, action=None): 7 """ if action is None: - action = lambda x: None + def action(x): + return None for node in self.post_order_traversal_iter(): action(node) @@ -638,7 +628,8 @@ def iterative_post_order_traversal(self, action=None): if self.is_empty(): return if action is None: - action = lambda x: None + def action(x): + return None stack = [self] while stack: node = stack[-1] @@ -725,7 +716,8 @@ def breadth_first_order_traversal(self, action=None): if self.is_empty(): return if action is None: - action = lambda x: None + def action(x): + return None queue = [] queue.append(self) while queue: @@ -1179,10 +1171,10 @@ def node_to_str(t): return t_repr if len(self) == 1: repr_child = self[0]._ascii_art_() - sep = AsciiArt([" "*(repr_child._root-1)]) + sep = AsciiArt([" " * (repr_child._root - 1)]) t_repr = AsciiArt([node_to_str(self)]) t_repr._root = 1 - repr_root = (sep + t_repr)*(sep + AsciiArt(["|"])) + repr_root = (sep + t_repr) * (sep + AsciiArt(["|"])) t_repr = repr_root * repr_child t_repr._root = repr_child._root t_repr._baseline = t_repr._h - 1 @@ -1190,9 +1182,9 @@ def node_to_str(t): # General case l_repr = [subtree._ascii_art_() for subtree in self] acc = l_repr.pop(0) - whitesep = acc._root+1 - lf_sep = " "*(acc._root+1) + "_"*(acc._l-acc._root) - ls_sep = " "*(acc._root) + "/" + " "*(acc._l-acc._root) + whitesep = acc._root + 1 + lf_sep = " " * (acc._root + 1) + "_" * (acc._l - acc._root) + ls_sep = " " * (acc._root) + "/" + " " * (acc._l - acc._root) while l_repr: t_repr = l_repr.pop(0) acc += AsciiArt([" "]) + t_repr @@ -1200,10 +1192,10 @@ def node_to_str(t): lf_sep += "_" * (t_repr._root + 1) else: lf_sep += "_" * (t_repr._l + 1) - ls_sep += " "*(t_repr._root) + "/" + " "*(t_repr._l-t_repr._root) + ls_sep += " " * (t_repr._root) + "/" + " " * (t_repr._l - t_repr._root) mid = whitesep + (len(lf_sep) - whitesep) // 2 node = node_to_str(self) - t_repr = AsciiArt([lf_sep[:mid-1] + node + lf_sep[mid+len(node)-1:], ls_sep]) * acc + t_repr = AsciiArt([lf_sep[:mid - 1] + node + lf_sep[mid + len(node) - 1:], ls_sep]) * acc t_repr._root = mid t_repr._baseline = t_repr._h - 1 return t_repr @@ -1485,7 +1477,7 @@ def _latex_(self): new_cmd4 = "$}\n;}" # some variables to simplify code sep = "\\&" - space = " "*9 + space = " " * 9 sepspace = sep + space spacesep = space + sep @@ -1952,7 +1944,7 @@ def __setitem_rec__(self, idx, i, value): self._setitem(idx[-1], value) else: with self[idx[i]].clone() as child: - child.__setitem_rec__(idx, i+1, value) + child.__setitem_rec__(idx, i + 1, value) self[idx[i]] = child def __getitem__(self, idx): diff --git a/src/sage/combinat/ncsf_qsym/ncsf.py b/src/sage/combinat/ncsf_qsym/ncsf.py index f145ecde76d..a746239b155 100644 --- a/src/sage/combinat/ncsf_qsym/ncsf.py +++ b/src/sage/combinat/ncsf_qsym/ncsf.py @@ -3795,8 +3795,6 @@ def internal_product_on_basis_by_bracketing(self, I, J): True sage: psi_int_test(4) # long time True - sage: psi_int_test(5) # long time - True """ # The algorithm used here is described in # :meth:`generic_basis_code.GradedModulesWithInternalProduct.ElementMethods.internal_product`. From 471b52f8221e93d19ceafaf922742dcc6ba5f86f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Wed, 13 Oct 2021 11:43:42 +0200 Subject: [PATCH 335/359] fix wrong change --- src/sage/symbolic/expression.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/symbolic/expression.pyx b/src/sage/symbolic/expression.pyx index 1c084ee9dc2..3bb7e6a6fe3 100644 --- a/src/sage/symbolic/expression.pyx +++ b/src/sage/symbolic/expression.pyx @@ -13538,7 +13538,7 @@ cdef Expression new_Expression_from_GEx(parent, GEx juice): if is_exactly_a_function(juice): # if the function defines any dynamic methods these are made # available through a dynamic class - cls = get_dynamic_class_for_function(ex_to_function(juice).get_serial()) + cls = get_dynamic_class_for_function(ex_to_function(juice).get_serial()) else: cls = Expression From 8eb9c501163ce25d614203114112c693c6c750f8 Mon Sep 17 00:00:00 2001 From: Jonathan Kliem Date: Wed, 13 Oct 2021 14:19:17 +0200 Subject: [PATCH 336/359] typo it's -> its --- src/sage/graphs/generic_graph.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sage/graphs/generic_graph.py b/src/sage/graphs/generic_graph.py index 8efe2ee7f77..81908f634ae 100644 --- a/src/sage/graphs/generic_graph.py +++ b/src/sage/graphs/generic_graph.py @@ -3492,7 +3492,7 @@ def antisymmetric(self): True """ if not self._directed: - # An undirected graph is antisymmetric only if all it's edges are + # An undirected graph is antisymmetric only if all its edges are # loops return self.size() == len(self.loop_edges()) if self.has_loops(): @@ -23481,7 +23481,7 @@ def edge_polytope(self, backend=None): True The EP of a graph is isomorphic to the subdirect sum of - it's connected components EPs:: + its connected components EPs:: sage: n = randint(3, 6) sage: G1 = graphs.RandomGNP(n, 0.2) @@ -23583,7 +23583,7 @@ def symmetric_edge_polytope(self, backend=None): True The SEP of a graph is isomorphic to the subdirect sum of - it's connected components SEP's:: + its connected components SEP's:: sage: n = randint(3, 6) sage: G1 = graphs.RandomGNP(n, 0.2) From 3cfe23594c0962cd8ff76147462711a57087d79d Mon Sep 17 00:00:00 2001 From: Jonathan Kliem Date: Thu, 16 Sep 2021 10:47:01 +0200 Subject: [PATCH 337/359] implicitly fuzz RNG-dependent doctests --- src/bin/sage | 2 +- src/bin/sage-runtests | 4 +-- src/doc/en/developer/doctesting.rst | 28 ++++++++++++++++++- src/sage/arith/misc.py | 25 +++++++++++++---- src/sage/crypto/util.py | 2 ++ src/sage/doctest/control.py | 4 ++- src/sage/functions/exp_integral.py | 2 +- src/sage/functions/orthogonal_polys.py | 2 ++ src/sage/misc/misc.py | 2 ++ src/sage/modular/modform/numerical.py | 4 +-- src/sage/stats/hmm/chmm.pyx | 2 +- src/sage/symbolic/random_tests.py | 2 +- .../linalg_doctest.py | 2 ++ 13 files changed, 65 insertions(+), 16 deletions(-) diff --git a/src/bin/sage b/src/bin/sage index 8a5bfafd8e2..fcd263029d0 100755 --- a/src/bin/sage +++ b/src/bin/sage @@ -466,7 +466,7 @@ usage_advanced() { echo " labeled \"# optional\" or labeled" echo " \"# optional tag\" for any of the tags given." echo " --randorder[=seed] -- randomize order of tests" - echo " --random-seed[=seed] -- random seed for fuzzing doctests" + echo " --random-seed[=seed] -- random seed (integer) for fuzzing doctests" echo " --new -- only test files modified since last commit" echo " --initial -- only show the first failure per block" echo " --debug -- drop into PDB after an unexpected error" diff --git a/src/bin/sage-runtests b/src/bin/sage-runtests index 16d3295b922..d1fe6567e74 100755 --- a/src/bin/sage-runtests +++ b/src/bin/sage-runtests @@ -65,7 +65,7 @@ if __name__ == "__main__": 'if "build" is listed, will also run tests specific to Sage\'s build/packaging system; ' 'if set to "all", then all tests will be run') parser.add_option("--randorder", type=int, metavar="SEED", help="randomize order of tests") - parser.add_option("--random-seed", dest="random_seed", type=int, metavar="SEED", help="random seed for fuzzing doctests") + parser.add_option("--random-seed", dest="random_seed", type=int, metavar="SEED", help="random seed (integer) for fuzzing doctests") parser.add_option("--global-iterations", "--global_iterations", type=int, default=0, help="repeat the whole testing process this many times") parser.add_option("--file-iterations", "--file_iterations", type=int, default=0, help="repeat each file this many times, stopping on the first failure") parser.add_option("--environment", type=str, default="sage.repl.ipython_kernel.all_jupyter", help="name of a module that provides the global environment for tests") @@ -132,7 +132,7 @@ if __name__ == "__main__": # Limit the number of threads to 2 to save system resources. # See Trac #23713, #23892, #30351 - if sys.platform == 'darwin': + if sys.platform == 'darwin': os.environ["OMP_NUM_THREADS"] = "1" else: os.environ["OMP_NUM_THREADS"] = "2" diff --git a/src/doc/en/developer/doctesting.rst b/src/doc/en/developer/doctesting.rst index f5fec4590f3..e26d7329095 100644 --- a/src/doc/en/developer/doctesting.rst +++ b/src/doc/en/developer/doctesting.rst @@ -803,7 +803,33 @@ You can also pass in an explicit amount of time:: Finally, you can disable any warnings about long tests with ``--warn-long 0``. -Doctests may start from a random seed:: +Doctests start from a random seed:: + + [kliem@sage sage-9.2]$ sage -t src/sage/doctest/tests/random_seed.rst + Running doctests with ID 2020-06-23-23-22-59-49f37a55. + ... + Doctesting 1 file. + sage -t --warn-long 89.5 --random-seed=112986622569797306072457879734474628454 src/sage/doctest/tests/random_seed.rst + ********************************************************************** + File "src/sage/doctest/tests/random_seed.rst", line 3, in sage.doctest.tests.random_seed + Failed example: + randint(5, 10) + Expected: + 9 + Got: + 8 + ********************************************************************** + 1 item had failures: + 1 of 2 in sage.doctest.tests.random_seed + [1 test, 1 failure, 0.00 s] + ---------------------------------------------------------------------- + sage -t --warn-long 89.5 --random-seed=112986622569797306072457879734474628454 src/sage/doctest/tests/random_seed.rst # 1 doctest failed + ---------------------------------------------------------------------- + Total time for all tests: 0.0 seconds + cpu time: 0.0 seconds + cumulative wall time: 0.0 seconds + +This seed can be set explicitly to reproduce possible failures:: [kliem@sage sage-9.2]$ sage -t --warn-long 89.5 --random-seed=112986622569797306072457879734474628454 src/sage/doctest/tests/random_seed.rst Running doctests with ID 2020-06-23-23-24-28-14a52269. diff --git a/src/sage/arith/misc.py b/src/sage/arith/misc.py index 039e786aff7..ccf442967f3 100644 --- a/src/sage/arith/misc.py +++ b/src/sage/arith/misc.py @@ -5660,12 +5660,25 @@ def sort_complex_numbers_for_display(nums): ....: RDF.random_element())) sage: shuffle(nums) sage: nums = sort_c(nums) - sage: nums[:3] - [0.0, 1.0, 2.0] - sage: for i in range(3, len(nums)-1): - ....: assert nums[i].real() <= nums[i+1].real() + 1e-10 - ....: if abs(nums[i].real() - nums[i+1].real()) < 1e-10: - ....: assert nums[i].imag() <= nums[i+1].imag() + 1e-10 + sage: for i in range(len(nums)): + ....: if nums[i].imag(): + ....: first_non_real = i + ....: break + ....: else: + ....: first_non_real = len(nums) + sage: assert first_non_real >= 3 + sage: for i in range(first_non_real - 1): + ....: assert nums[i].real() <= nums[i + 1].real() + + sage: def truncate(n): + ....: if n.real() < 1e-10: + ....: return 0 + ....: else: + ....: return n.real().n(digits=9) + sage: for i in range(first_non_real, len(nums)-1): + ....: assert truncate(nums[i]) <= truncate(nums[i + 1]) + ....: if truncate(nums[i]) == truncate(nums[i + 1]): + ....: assert nums[i].imag() <= nums[i+1].imag() """ if not nums: return nums diff --git a/src/sage/crypto/util.py b/src/sage/crypto/util.py index 1d1e375e6cc..cb7b6a12138 100644 --- a/src/sage/crypto/util.py +++ b/src/sage/crypto/util.py @@ -334,6 +334,8 @@ def carmichael_lambda(n): ....: L = coprime(n) ....: return list(map(power_mod, L, [k]*len(L), [n]*len(L))) sage: def my_carmichael(n): + ....: if n == 1: + ....: return 1 ....: for k in range(1, n): ....: L = znpower(n, k) ....: ones = [1] * len(L) diff --git a/src/sage/doctest/control.py b/src/sage/doctest/control.py index afb0d6cbcf1..8c8c91f2c00 100644 --- a/src/sage/doctest/control.py +++ b/src/sage/doctest/control.py @@ -28,6 +28,7 @@ import re import types import sage.misc.flatten +import sage.misc.randstate as randstate from sage.structure.sage_object import SageObject from sage.env import DOT_SAGE, SAGE_LIB, SAGE_SRC, SAGE_VENV, SAGE_EXTCODE from sage.misc.temporary_file import tmp_dir @@ -417,7 +418,8 @@ def __init__(self, options, args): self._init_warn_long() if self.options.random_seed is None: - self.options.random_seed = 0 + randstate.set_random_seed() + self.options.random_seed = randstate.initial_seed() def __del__(self): if getattr(self, 'logfile', None) is not None: diff --git a/src/sage/functions/exp_integral.py b/src/sage/functions/exp_integral.py index b20f7779f1a..21dcfa9f471 100644 --- a/src/sage/functions/exp_integral.py +++ b/src/sage/functions/exp_integral.py @@ -1497,7 +1497,7 @@ def exponential_integral_1(x, n=0): ....: n = 2^ZZ.random_element(14) ....: x = exponential_integral_1(a, n) ....: y = exponential_integral_1(S(a), n) - ....: c = RDF(2 * max(1.0, y[0])) + ....: c = RDF(4 * max(1.0, y[0])) ....: for i in range(n): ....: e = float(abs(S(x[i]) - y[i]) << prec) ....: if e >= c: diff --git a/src/sage/functions/orthogonal_polys.py b/src/sage/functions/orthogonal_polys.py index 9b5636f3fdc..2a5ed971550 100644 --- a/src/sage/functions/orthogonal_polys.py +++ b/src/sage/functions/orthogonal_polys.py @@ -2084,6 +2084,8 @@ class Func_ultraspherical(GinacFunction): sage: _ = var('x') sage: for N in range(100): ....: n = ZZ.random_element().abs() + 5 + ....: if n > 5000: # avoid timeouts + ....: continue ....: a = QQ.random_element().abs() + 5 ....: assert ((n+1)*ultraspherical(n+1,a,x) - 2*x*(n+a)*ultraspherical(n,a,x) + (n+2*a-1)*ultraspherical(n-1,a,x)).expand().is_zero() sage: ultraspherical(5,9/10,3.1416) diff --git a/src/sage/misc/misc.py b/src/sage/misc/misc.py index efaa182f0d9..fbebd99b3a3 100644 --- a/src/sage/misc/misc.py +++ b/src/sage/misc/misc.py @@ -803,6 +803,8 @@ def __rmul__(self, left): EXAMPLES:: sage: A = random_matrix(ZZ, 4) + sage: while A.rank() != 4: + ....: A = random_matrix(ZZ, 4) sage: B = random_matrix(ZZ, 4) sage: temp = A * BackslashOperator() sage: temp.left is A diff --git a/src/sage/modular/modform/numerical.py b/src/sage/modular/modform/numerical.py index 0d467ef2c0b..f09aca90239 100644 --- a/src/sage/modular/modform/numerical.py +++ b/src/sage/modular/modform/numerical.py @@ -444,7 +444,7 @@ def systems_of_eigenvalues(self, bound): EXAMPLES:: - sage: numerical_eigenforms(61).systems_of_eigenvalues(10) # rel tol 1e-12 + sage: numerical_eigenforms(61).systems_of_eigenvalues(10) # rel tol 1e-11 [ [-1.4811943040920152, 0.8060634335253695, 3.1563251746586642, 0.6751308705666477], [-1.0, -2.0000000000000027, -3.000000000000003, 1.0000000000000044], @@ -471,7 +471,7 @@ def systems_of_abs(self, bound): EXAMPLES:: - sage: numerical_eigenforms(61).systems_of_abs(10) # rel tol 1e-12 + sage: numerical_eigenforms(61).systems_of_abs(10) # rel tol 1e-11 [ [0.3111078174659775, 2.903211925911551, 2.525427560843529, 3.214319743377552], [1.0, 2.0000000000000027, 3.000000000000003, 1.0000000000000044], diff --git a/src/sage/stats/hmm/chmm.pyx b/src/sage/stats/hmm/chmm.pyx index 0f9837745ad..6cc2d42adb3 100644 --- a/src/sage/stats/hmm/chmm.pyx +++ b/src/sage/stats/hmm/chmm.pyx @@ -903,7 +903,7 @@ cdef class GaussianHiddenMarkovModel(HiddenMarkovModel): sage: m = hmm.GaussianHiddenMarkovModel([[.1,.9],[.5,.5]], [(1,.5), (-1,3)], [.1,.9]) sage: v = m.sample(10) sage: l = stats.TimeSeries([m.baum_welch(v,max_iter=1)[0] for _ in range(len(v))]) - sage: all(l[i] <= l[i+1] for i in range(9)) + sage: all(l[i] <= l[i+1] + 0.0001 for i in range(9)) True sage: l # random [-20.1167, -17.7611, -16.9814, -16.9364, -16.9314, -16.9309, -16.9309, -16.9309, -16.9309, -16.9309] diff --git a/src/sage/symbolic/random_tests.py b/src/sage/symbolic/random_tests.py index 9e50acd181b..35e6edcbb4b 100644 --- a/src/sage/symbolic/random_tests.py +++ b/src/sage/symbolic/random_tests.py @@ -426,7 +426,7 @@ def test_symbolic_expression_order(repetitions=100): sage: from sage.symbolic.random_tests import test_symbolic_expression_order sage: test_symbolic_expression_order(200) - sage: test_symbolic_expression_order(10000) # long time + sage: test_symbolic_expression_order(10000) # long time, # not tested, known bug (see :trac:`32185`) """ rnd_length = 50 nvars = 10 diff --git a/src/sage/tests/books/computational-mathematics-with-sagemath/linalg_doctest.py b/src/sage/tests/books/computational-mathematics-with-sagemath/linalg_doctest.py index e3c78e66202..902b3c1aec2 100644 --- a/src/sage/tests/books/computational-mathematics-with-sagemath/linalg_doctest.py +++ b/src/sage/tests/books/computational-mathematics-with-sagemath/linalg_doctest.py @@ -269,6 +269,8 @@ sage: A = random_matrix(R,2,3); A # random [ 3*x^2 + x x^2 + 2*x 2*x^2 + 2] [ x^2 + x + 2 2*x^2 + 4*x + 3 x^2 + 4*x + 3] + sage: while A.rank() < 2: + ....: A = random_matrix(R,2,3) Sage example in ./linalg.tex, line 1830:: From 1980561fa6749e0ed70d944a6e9784422fd777f9 Mon Sep 17 00:00:00 2001 From: Jonathan Kliem Date: Thu, 16 Sep 2021 10:54:31 +0200 Subject: [PATCH 338/359] reduce vertices for edge disjoint spanning trees --- src/sage/graphs/generic_graph.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/sage/graphs/generic_graph.py b/src/sage/graphs/generic_graph.py index 81908f634ae..a44d1aac6e6 100644 --- a/src/sage/graphs/generic_graph.py +++ b/src/sage/graphs/generic_graph.py @@ -6262,8 +6262,11 @@ def edge_disjoint_spanning_trees(self, k, root=None, solver=None, verbose=0): By Edmond's theorem, a graph which is `k`-connected always has `k` edge-disjoint arborescences, regardless of the root we pick:: - sage: g = digraphs.RandomDirectedGNP(28, .3) # reduced from 30 to 28, cf. #9584 + sage: g = digraphs.RandomDirectedGNP(11, .3) # reduced from 30 to 11, cf. #32169 sage: k = Integer(g.edge_connectivity()) + sage: while not k: + ....: g = digraphs.RandomDirectedGNP(28, .3) # + ....: k = Integer(g.edge_connectivity()) sage: arborescences = g.edge_disjoint_spanning_trees(k) # long time (up to 15s on sage.math, 2011) sage: all(a.is_directed_acyclic() for a in arborescences) # long time True From e6dd0270513299c1c6ff813093510b88471c5695 Mon Sep 17 00:00:00 2001 From: Jonathan Kliem Date: Thu, 16 Sep 2021 16:53:13 +0200 Subject: [PATCH 339/359] do not remove fixed doctest --- src/sage/symbolic/random_tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/symbolic/random_tests.py b/src/sage/symbolic/random_tests.py index 35e6edcbb4b..9e50acd181b 100644 --- a/src/sage/symbolic/random_tests.py +++ b/src/sage/symbolic/random_tests.py @@ -426,7 +426,7 @@ def test_symbolic_expression_order(repetitions=100): sage: from sage.symbolic.random_tests import test_symbolic_expression_order sage: test_symbolic_expression_order(200) - sage: test_symbolic_expression_order(10000) # long time, # not tested, known bug (see :trac:`32185`) + sage: test_symbolic_expression_order(10000) # long time """ rnd_length = 50 nvars = 10 From 22c2b66adc903abae40e517d44a117dca2d41756 Mon Sep 17 00:00:00 2001 From: Jonathan Kliem Date: Thu, 16 Sep 2021 16:53:21 +0200 Subject: [PATCH 340/359] simplify doctest --- src/sage/functions/orthogonal_polys.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/sage/functions/orthogonal_polys.py b/src/sage/functions/orthogonal_polys.py index 2a5ed971550..9a1078049b4 100644 --- a/src/sage/functions/orthogonal_polys.py +++ b/src/sage/functions/orthogonal_polys.py @@ -2083,9 +2083,7 @@ class Func_ultraspherical(GinacFunction): 32*t^3 - 12*t sage: _ = var('x') sage: for N in range(100): - ....: n = ZZ.random_element().abs() + 5 - ....: if n > 5000: # avoid timeouts - ....: continue + ....: n = ZZ.random_element(5, 5001) ....: a = QQ.random_element().abs() + 5 ....: assert ((n+1)*ultraspherical(n+1,a,x) - 2*x*(n+a)*ultraspherical(n,a,x) + (n+2*a-1)*ultraspherical(n-1,a,x)).expand().is_zero() sage: ultraspherical(5,9/10,3.1416) From e32986c1d5a0bede049a9023c8c651270e0dc43c Mon Sep 17 00:00:00 2001 From: Jonathan Kliem Date: Thu, 16 Sep 2021 17:20:17 +0200 Subject: [PATCH 341/359] fix unstable doctests --- src/sage/graphs/tutte_polynomial.py | 4 +++- src/sage/groups/perm_gps/permgroup_morphism.py | 9 ++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/sage/graphs/tutte_polynomial.py b/src/sage/graphs/tutte_polynomial.py index f01a21437f9..297b1347481 100644 --- a/src/sage/graphs/tutte_polynomial.py +++ b/src/sage/graphs/tutte_polynomial.py @@ -544,10 +544,12 @@ def tutte_polynomial(G, edge_selector=None, cache=None): + 105*x^2*y^2 + 65*x*y^3 + 35*y^4 + 180*x^3 + 240*x^2*y + 171*x*y^2 + 75*y^3 + 120*x^2 + 168*x*y + 84*y^2 + 36*x + 36*y - The Tutte polynomial of `G` evaluated at (1,1) is the number of + The Tutte polynomial of a connected graph `G` evaluated at (1,1) is the number of spanning trees of `G`:: sage: G = graphs.RandomGNP(10,0.6) + sage: while not G.is_connected(): + ....: G = graphs.RandomGNP(10,0.6) sage: G.tutte_polynomial()(1,1) == G.spanning_trees_count() True diff --git a/src/sage/groups/perm_gps/permgroup_morphism.py b/src/sage/groups/perm_gps/permgroup_morphism.py index 29521593601..55ceb218817 100644 --- a/src/sage/groups/perm_gps/permgroup_morphism.py +++ b/src/sage/groups/perm_gps/permgroup_morphism.py @@ -117,11 +117,10 @@ def image(self, J): sage: G = L.galois_group() sage: D4 = DihedralGroup(4) sage: h = D4.isomorphism_to(G) - sage: h.image(D4) - Subgroup generated by [(1,2)(3,4)(5,7)(6,8), (1,6,4,7)(2,5,3,8)] of (Galois group 8T4 ([4]2) with order 8 of x^8 + 4*x^7 + 12*x^6 + 22*x^5 + 23*x^4 + 14*x^3 + 28*x^2 + 24*x + 16) - sage: r, s = D4.gens() - sage: h.image(r) - (1,6,4,7)(2,5,3,8) + sage: h.image(D4).is_isomorphic(G) + True + sage: all(h.image(g) in G for g in D4.gens()) + True """ H = self.codomain() if J in self.domain(): From 7b1bd36084abebcab724b9a0157b43e0394b5e85 Mon Sep 17 00:00:00 2001 From: Jonathan Kliem Date: Fri, 17 Sep 2021 11:00:44 +0200 Subject: [PATCH 342/359] fixed some doctests for disjoint spanning trees --- src/sage/graphs/generic_graph.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/sage/graphs/generic_graph.py b/src/sage/graphs/generic_graph.py index a44d1aac6e6..983f9c9bdc9 100644 --- a/src/sage/graphs/generic_graph.py +++ b/src/sage/graphs/generic_graph.py @@ -6265,7 +6265,7 @@ def edge_disjoint_spanning_trees(self, k, root=None, solver=None, verbose=0): sage: g = digraphs.RandomDirectedGNP(11, .3) # reduced from 30 to 11, cf. #32169 sage: k = Integer(g.edge_connectivity()) sage: while not k: - ....: g = digraphs.RandomDirectedGNP(28, .3) # + ....: g = digraphs.RandomDirectedGNP(11, .3) ....: k = Integer(g.edge_connectivity()) sage: arborescences = g.edge_disjoint_spanning_trees(k) # long time (up to 15s on sage.math, 2011) sage: all(a.is_directed_acyclic() for a in arborescences) # long time @@ -6276,6 +6276,8 @@ def edge_disjoint_spanning_trees(self, k, root=None, solver=None, verbose=0): In the undirected case, we can only ensure half of it:: sage: g = graphs.RandomGNP(30, .3) + sage: while not g.is_connected(): + ....: g = graphs.RandomGNP(30, .3) sage: k = Integer(g.edge_connectivity()) // 2 sage: trees = g.edge_disjoint_spanning_trees(k) sage: all(t.is_tree() for t in trees) From 812b5559b06b4fb9ade7b325a83c1385ea24a58e Mon Sep 17 00:00:00 2001 From: Jonathan Kliem Date: Mon, 20 Sep 2021 09:11:51 +0200 Subject: [PATCH 343/359] fix unstable doctest in book_stein_ent --- src/sage/tests/book_stein_ent.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/sage/tests/book_stein_ent.py b/src/sage/tests/book_stein_ent.py index cd6d4f7f179..5041f7ea4cf 100644 --- a/src/sage/tests/book_stein_ent.py +++ b/src/sage/tests/book_stein_ent.py @@ -267,8 +267,9 @@ ....: if g != 1 and g != n: ....: return g sage: n=32295194023343; e=29468811804857; d=11127763319273 -sage: crack_given_decrypt(n, e*d - 1) -737531 +sage: p = crack_given_decrypt(n, e*d - 1) +sage: p in (737531, n/737531) # could be other prime divisor +True sage: factor(n) 737531 * 43788253 sage: e = 22601762315966221465875845336488389513 From 74e505b8b769247b91482298aeebfa19fc64995b Mon Sep 17 00:00:00 2001 From: Jonathan Kliem Date: Mon, 4 Oct 2021 11:59:22 +0200 Subject: [PATCH 344/359] edge disjoint spanning tree not as fast as claimed, see #32169 --- src/sage/graphs/generic_graph.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sage/graphs/generic_graph.py b/src/sage/graphs/generic_graph.py index 983f9c9bdc9..be2e927f40e 100644 --- a/src/sage/graphs/generic_graph.py +++ b/src/sage/graphs/generic_graph.py @@ -6262,7 +6262,7 @@ def edge_disjoint_spanning_trees(self, k, root=None, solver=None, verbose=0): By Edmond's theorem, a graph which is `k`-connected always has `k` edge-disjoint arborescences, regardless of the root we pick:: - sage: g = digraphs.RandomDirectedGNP(11, .3) # reduced from 30 to 11, cf. #32169 + sage: g = digraphs.RandomDirectedGNP(11, .3) # reduced from 30 to 11, cf. #32169 sage: k = Integer(g.edge_connectivity()) sage: while not k: ....: g = digraphs.RandomDirectedGNP(11, .3) @@ -6275,9 +6275,9 @@ def edge_disjoint_spanning_trees(self, k, root=None, solver=None, verbose=0): In the undirected case, we can only ensure half of it:: - sage: g = graphs.RandomGNP(30, .3) - sage: while not g.is_connected(): - ....: g = graphs.RandomGNP(30, .3) + sage: g = graphs.RandomGNP(14, .3) # reduced from 30 to 14, see #32169 + sage: while not g.is_biconnected(): + ....: g = graphs.RandomGNP(14, .3) sage: k = Integer(g.edge_connectivity()) // 2 sage: trees = g.edge_disjoint_spanning_trees(k) sage: all(t.is_tree() for t in trees) From 44cd7ae08c998e19b0e8d31c88c657a2993ff1ce Mon Sep 17 00:00:00 2001 From: Jonathan Kliem Date: Fri, 8 Oct 2021 09:49:35 +0200 Subject: [PATCH 345/359] fix doctest failure for random matrix --- src/sage/matrix/matrix0.pyx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/sage/matrix/matrix0.pyx b/src/sage/matrix/matrix0.pyx index 41b8da5f415..763a9c3d0c4 100644 --- a/src/sage/matrix/matrix0.pyx +++ b/src/sage/matrix/matrix0.pyx @@ -4830,7 +4830,10 @@ cdef class Matrix(sage.structure.element.Matrix): sage: B.multiplicative_order() 1 - sage: E = MatrixSpace(GF(11^2,'e'),5).random_element() + sage: M = MatrixSpace(GF(11^2,'e'),5) + sage: E = M.random_element() + sage: while E.det() == 0: + ....: E = M.random_element() sage: (E^E.multiplicative_order()).is_one() True From 2c478d1c375f10f4e6f7e95fcb71feff74d13653 Mon Sep 17 00:00:00 2001 From: Jonathan Kliem Date: Fri, 8 Oct 2021 16:22:00 +0200 Subject: [PATCH 346/359] one more unstable doctest --- .../sol/graphique_doctest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/tests/books/computational-mathematics-with-sagemath/sol/graphique_doctest.py b/src/sage/tests/books/computational-mathematics-with-sagemath/sol/graphique_doctest.py index 95e7f328255..549f48e1b77 100644 --- a/src/sage/tests/books/computational-mathematics-with-sagemath/sol/graphique_doctest.py +++ b/src/sage/tests/books/computational-mathematics-with-sagemath/sol/graphique_doctest.py @@ -42,7 +42,7 @@ sage: g = plot([c*e^(-1/x) for c in srange(-8, 8, 0.4)], (x, -3, 3)) sage: y = var('y') sage: g += plot_vector_field((x^2, y), (x,-3,3), (y,-5,5)) - sage: g.show() + sage: g.show() # not tested, known bug, see :trac:`32657` Sage example in ./sol/graphique.tex, line 124:: From a6c9428a04d5acb20e601cc367539816bcb24dab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Wed, 13 Oct 2021 14:42:58 +0200 Subject: [PATCH 347/359] change : Ctrl-c pressed while running Axiom + : Ctrl-c pressed while running Axiom :: diff --git a/src/sage/interfaces/fricas.py b/src/sage/interfaces/fricas.py index 98e452513cf..514f02fccd4 100644 --- a/src/sage/interfaces/fricas.py +++ b/src/sage/interfaces/fricas.py @@ -1308,7 +1308,7 @@ def _parse_and_eval(s, start=0): sage: FriCASElement._parse_and_eval('(a "(b c)")') Traceback (most recent call last): ... - TypeError: cannot coerce arguments: no canonical coercion from to Symbolic Ring + TypeError: cannot coerce arguments: no canonical coercion from to Symbolic Ring """ a = start diff --git a/src/sage/interfaces/giac.py b/src/sage/interfaces/giac.py index 0a2fc56812a..8e0ff6843fb 100644 --- a/src/sage/interfaces/giac.py +++ b/src/sage/interfaces/giac.py @@ -856,7 +856,7 @@ def __float__(self): sage: float(giac(1/2)) 0.5 sage: type(_) - + """ return float(giac.eval('evalf(%s)' % self.name())) diff --git a/src/sage/interfaces/gp.py b/src/sage/interfaces/gp.py index 7a4c1b90603..48fe1a16158 100644 --- a/src/sage/interfaces/gp.py +++ b/src/sage/interfaces/gp.py @@ -913,7 +913,7 @@ def _sage_(self): sage: s.sage() 'foo' sage: type(s.sage()) - + """ if self.is_string(): return str(self) diff --git a/src/sage/interfaces/lie.py b/src/sage/interfaces/lie.py index deb16fdfe27..43c3ec3fdd2 100644 --- a/src/sage/interfaces/lie.py +++ b/src/sage/interfaces/lie.py @@ -209,7 +209,7 @@ sage: b = a.sage(); b # optional - lie 1234 sage: type(b) # optional - lie - + Vectors:: @@ -226,7 +226,7 @@ [1 2] [3 4] sage: type(b) # optional - lie - + Polynomials:: @@ -234,7 +234,7 @@ sage: b = a.sage(); b # optional - lie -2*x0^2*x1 + x0*x1^2 sage: type(b) # optional - lie - + Text:: diff --git a/src/sage/interfaces/maxima_abstract.py b/src/sage/interfaces/maxima_abstract.py index 3fe2dd7bbab..917059de0ab 100644 --- a/src/sage/interfaces/maxima_abstract.py +++ b/src/sage/interfaces/maxima_abstract.py @@ -1216,18 +1216,18 @@ def _sage_(self): sage: b = a._sage_(); b sqrt(2) + 2.5 sage: type(b) - + We illustrate an automatic coercion:: sage: c = b + sqrt(3); c sqrt(3) + sqrt(2) + 2.5 sage: type(c) - + sage: d = sqrt(3) + b; d sqrt(3) + sqrt(2) + 2.5 sage: type(d) - + sage: a = sage.calculus.calculus.maxima('x^(sqrt(y)+%pi) + sin(%e + %pi)') sage: a._sage_() diff --git a/src/sage/interfaces/singular.py b/src/sage/interfaces/singular.py index d9c0a90fb08..3a0fafaf4fa 100644 --- a/src/sage/interfaces/singular.py +++ b/src/sage/interfaces/singular.py @@ -1994,7 +1994,7 @@ def _sage_(self, R=None): sage: singular(5).sage() 5 sage: type(singular(int(5)).sage()) - + """ typ = self.type() diff --git a/src/sage/libs/coxeter3/coxeter_group.py b/src/sage/libs/coxeter3/coxeter_group.py index b4118ca9592..a9127b88da1 100644 --- a/src/sage/libs/coxeter3/coxeter_group.py +++ b/src/sage/libs/coxeter3/coxeter_group.py @@ -393,7 +393,7 @@ def parabolic_kazhdan_lusztig_polynomial(self, u, v, J, constant_term_one=True): sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3 sage: type(W.parabolic_kazhdan_lusztig_polynomial([2],[],[1])) # optional - coxeter3 - + """ u = self(u) v = self(v) diff --git a/src/sage/libs/ecl.pyx b/src/sage/libs/ecl.pyx index a0237505d91..85dc3d1e564 100644 --- a/src/sage/libs/ecl.pyx +++ b/src/sage/libs/ecl.pyx @@ -1296,7 +1296,7 @@ cdef class EclListIterator: sage: from sage.libs.ecl import * sage: I=EclListIterator(EclObject("(1 2 3)")) sage: type(I) - + sage: [i for i in I] [, , ] sage: [i for i in EclObject("(1 2 3)")] @@ -1318,7 +1318,7 @@ cdef class EclListIterator: sage: from sage.libs.ecl import * sage: I=EclListIterator(EclObject("(1 2 3)")) sage: type(I) - + """ if not o.listp(): diff --git a/src/sage/libs/eclib/homspace.pyx b/src/sage/libs/eclib/homspace.pyx index 900aa7834a9..d12f35dc82f 100644 --- a/src/sage/libs/eclib/homspace.pyx +++ b/src/sage/libs/eclib/homspace.pyx @@ -23,7 +23,7 @@ cdef class ModularSymbols: sage: M = CremonaModularSymbols(225) sage: type(M) - + """ def __init__(self, long level, int sign=0, bint cuspidal=False, int verbose=0): """ @@ -242,7 +242,7 @@ cdef class ModularSymbols: sage: M = CremonaModularSymbols(37) sage: t = M.sparse_hecke_matrix(2); type(t) - + sage: print(t) [ 3 0 0 0 0] [-1 -1 1 1 0] diff --git a/src/sage/libs/eclib/mat.pyx b/src/sage/libs/eclib/mat.pyx index d740a695654..2ad3474b221 100644 --- a/src/sage/libs/eclib/mat.pyx +++ b/src/sage/libs/eclib/mat.pyx @@ -21,7 +21,7 @@ cdef class Matrix: sage: M = CremonaModularSymbols(225) sage: t = M.hecke_matrix(2) sage: type(t) - + sage: t 61 x 61 Cremona matrix over Rational Field @@ -30,7 +30,7 @@ cdef class Matrix: sage: t = CremonaModularSymbols(11).hecke_matrix(2); t 3 x 3 Cremona matrix over Rational Field sage: type(t) - + """ def __repr__(self): """ @@ -204,12 +204,12 @@ cdef class Matrix: [ 0 1] [ 1 -1] sage: type(s) - + sage: s = t.sage_matrix_over_ZZ(sparse=False); s [ 0 1] [ 1 -1] sage: type(s) - + """ cdef long n = self.nrows() cdef long i, j, k diff --git a/src/sage/libs/eclib/mwrank.pyx b/src/sage/libs/eclib/mwrank.pyx index 2d10fd76180..0c20771d558 100644 --- a/src/sage/libs/eclib/mwrank.pyx +++ b/src/sage/libs/eclib/mwrank.pyx @@ -202,7 +202,7 @@ cdef class _bigint: sage: _bigint('123') 123 sage: type(_bigint(123)) - + """ s = str(x) if s.isdigit() or s[0] == "-" and s[1:].isdigit(): @@ -357,7 +357,7 @@ cdef class _Curvedata: # cython class wrapping eclib's Curvedata class sage: E.silverman_bound() 6.52226179519101... sage: type(E.silverman_bound()) - + """ return Curvedata_silverman_bound(self.x) @@ -570,7 +570,7 @@ cdef class _mw: sage: EQ [] sage: type(EQ) - + sage: E = _Curvedata(0,0,1,-7,6) sage: EQ = _mw(E) diff --git a/src/sage/libs/gap/libgap.pyx b/src/sage/libs/gap/libgap.pyx index 9f9f62be13a..6a9d4b2ceee 100644 --- a/src/sage/libs/gap/libgap.pyx +++ b/src/sage/libs/gap/libgap.pyx @@ -12,7 +12,7 @@ EXAMPLES:: sage: a 10 sage: type(a) - + sage: a*a 100 sage: timeit('a*a') # random output @@ -35,7 +35,7 @@ objects to GAP objects, for example strings to strings:: sage: libgap('List([1..10], i->i^2)') "List([1..10], i->i^2)" sage: type(_) - + You can usually use the :meth:`~sage.libs.gap.element.GapElement.sage` method to convert the resulting GAP element back to its Sage @@ -44,7 +44,7 @@ equivalent:: sage: a.sage() 10 sage: type(_) - + sage: libgap.eval('5/3 + 7*E(3)').sage() 7*zeta3 + 5/3 @@ -93,7 +93,7 @@ can be used as follows:: sage: lst = libgap([1,5,7]); lst [ 1, 5, 7 ] sage: type(lst) - + sage: len(lst) 3 sage: lst[0] @@ -101,7 +101,7 @@ can be used as follows:: sage: [ x^2 for x in lst ] [1, 25, 49] sage: type(_[0]) - + Note that you can access the elements of GAP ``List`` objects as you would expect from Python (with indexing starting at 0), but the @@ -637,7 +637,7 @@ class Gap(Parent): EXAMPLES:: sage: type(libgap) - + sage: type(libgap._get_object()) """ diff --git a/src/sage/libs/giac/giac.pyx b/src/sage/libs/giac/giac.pyx index abd6438744e..916b66f3bd1 100644 --- a/src/sage/libs/giac/giac.pyx +++ b/src/sage/libs/giac/giac.pyx @@ -1457,7 +1457,7 @@ cdef class Pygen(GiacMethods_base): sage: a=libgiac('10'); b=libgiac('2**300') sage: a;type(ZZ(a)) 10 - + sage: next_prime(b) 2037035976334486086268445688409378161051468393665936250636140449354381299763336706183397533 sage: c=libgiac('2 % nextprime(2**40)') diff --git a/src/sage/libs/lcalc/lcalc_Lfunction.pyx b/src/sage/libs/lcalc/lcalc_Lfunction.pyx index 7e54d7e78d5..58deb827aa9 100644 --- a/src/sage/libs/lcalc/lcalc_Lfunction.pyx +++ b/src/sage/libs/lcalc/lcalc_Lfunction.pyx @@ -455,7 +455,7 @@ cdef class Lfunction_I(Lfunction): sage: chi = DirichletGroup(5)[2] #This is a quadratic character sage: L=Lfunction_from_character(chi, type="int") sage: type(L) - + """ Lfunction.__init__(self, name, what_type_L, dirichlet_coefficient, period, Q, OMEGA, gamma,lambd, pole,residue) self._repr += " with integer Dirichlet coefficients" @@ -591,7 +591,7 @@ cdef class Lfunction_D(Lfunction): sage: chi = DirichletGroup(5)[2] #This is a quadratic character sage: L=Lfunction_from_character(chi, type="double") sage: type(L) - + """ Lfunction.__init__(self, name, what_type_L, dirichlet_coefficient, period, Q, OMEGA, gamma,lambd, pole,residue) self._repr += " with real Dirichlet coefficients" @@ -731,7 +731,7 @@ cdef class Lfunction_C: sage: chi = DirichletGroup(5)[1] sage: L=Lfunction_from_character(chi, type="complex") sage: type(L) - + """ Lfunction.__init__(self, name, what_type_L, dirichlet_coefficient, period, Q, OMEGA, gamma,lambd, pole,residue) self._repr += " with complex Dirichlet coefficients" diff --git a/src/sage/libs/lrcalc/lrcalc.pyx b/src/sage/libs/lrcalc/lrcalc.pyx index 1cf67dc15ab..b591081ec4c 100644 --- a/src/sage/libs/lrcalc/lrcalc.pyx +++ b/src/sage/libs/lrcalc/lrcalc.pyx @@ -297,7 +297,7 @@ def test_skewtab_to_SkewTableau(outer, inner): cdef dict sf_hashtab_to_dict(hashtab *ht): """ Return a dictionary representing a Schur function. The keys are - partitions and the values are integers . + partitions and the values are integers . EXAMPLES:: @@ -320,7 +320,7 @@ cdef dict sf_hashtab_to_dict(hashtab *ht): cdef dict schubert_hashtab_to_dict(hashtab *ht): """ Return a dictionary corresponding to a Schubert polynomial whose keys - are permutations and whose values are integers . + are permutations and whose values are integers . EXAMPLES:: @@ -341,7 +341,7 @@ cdef dict schubert_hashtab_to_dict(hashtab *ht): cdef dict vp_hashtab_to_dict(hashtab *ht): """ Return a dictionary corresponding to the coproduct of a Schur function whose keys are - pairs of partitions and whose values are integers . + pairs of partitions and whose values are integers . EXAMPLES:: diff --git a/src/sage/libs/mpmath/ext_main.pyx b/src/sage/libs/mpmath/ext_main.pyx index 5821be79073..379971de1a3 100644 --- a/src/sage/libs/mpmath/ext_main.pyx +++ b/src/sage/libs/mpmath/ext_main.pyx @@ -1965,7 +1965,7 @@ cdef class mpf(mpf_base): sage: mpf(-500.5).man 1001 sage: type(_) - + """ return self._mpf_[1] diff --git a/src/sage/libs/mpmath/utils.pyx b/src/sage/libs/mpmath/utils.pyx index d6c9eeea75d..ea5aa54bfc8 100644 --- a/src/sage/libs/mpmath/utils.pyx +++ b/src/sage/libs/mpmath/utils.pyx @@ -402,11 +402,11 @@ def call(func, *args, **kwargs): sage: a.call(a.polylog, 2, 1/2, parent=CC) 0.582240526465012 sage: type(_) - + sage: a.call(a.polylog, 2, 1/2, parent=RDF) 0.5822405264650125 sage: type(_) - + Check that :trac:`11885` is fixed:: diff --git a/src/sage/libs/ntl/ntl_GF2.pyx b/src/sage/libs/ntl/ntl_GF2.pyx index 2a03e7723b4..b899f21548f 100644 --- a/src/sage/libs/ntl/ntl_GF2.pyx +++ b/src/sage/libs/ntl/ntl_GF2.pyx @@ -250,7 +250,7 @@ def unpickle_class_value(cls, x): sage: sage.libs.ntl.ntl_GF2.unpickle_class_value(ntl.GF2,1) 1 sage: type(sage.libs.ntl.ntl_GF2.unpickle_class_value(ntl.GF2,1)) - + """ return cls(x) @@ -263,7 +263,7 @@ def unpickle_class_args(cls, x): sage: sage.libs.ntl.ntl_GF2.unpickle_class_args(ntl.GF2,[1]) 1 sage: type(sage.libs.ntl.ntl_GF2.unpickle_class_args(ntl.GF2,[1])) - + """ return cls(*x) diff --git a/src/sage/libs/ntl/ntl_GF2E.pyx b/src/sage/libs/ntl/ntl_GF2E.pyx index 748449f9c25..252851d40ed 100644 --- a/src/sage/libs/ntl/ntl_GF2E.pyx +++ b/src/sage/libs/ntl/ntl_GF2E.pyx @@ -403,7 +403,7 @@ cdef class ntl_GF2E(object): sage: a.rep() [1 0 0 0 0 0 1 1] sage: type(a.rep()) - + """ cdef ntl_GF2X x = ntl_GF2X.__new__(ntl_GF2X) x.x = GF2E_rep(self.x) diff --git a/src/sage/libs/ntl/ntl_ZZ.pyx b/src/sage/libs/ntl/ntl_ZZ.pyx index 16d04663efa..e132e997e01 100644 --- a/src/sage/libs/ntl/ntl_ZZ.pyx +++ b/src/sage/libs/ntl/ntl_ZZ.pyx @@ -293,7 +293,7 @@ cdef class ntl_ZZ(object): sage: n=ntl.ZZ(2983) sage: type(n._integer_()) - + AUTHOR: Joel B. Mohler """ @@ -403,7 +403,7 @@ def unpickle_class_value(cls, x): sage: sage.libs.ntl.ntl_ZZ.unpickle_class_value(ntl.ZZ, 3) 3 sage: type(sage.libs.ntl.ntl_ZZ.unpickle_class_value(ntl.ZZ, 3)) - + """ return cls(x) @@ -416,7 +416,7 @@ def unpickle_class_args(cls, x): sage: sage.libs.ntl.ntl_ZZ.unpickle_class_args(ntl.ZZ, [3]) 3 sage: type(sage.libs.ntl.ntl_ZZ.unpickle_class_args(ntl.ZZ, [3])) - + """ return cls(*x) diff --git a/src/sage/libs/ntl/ntl_ZZX.pyx b/src/sage/libs/ntl/ntl_ZZX.pyx index 3aea4aca9fc..cee8c5422e6 100644 --- a/src/sage/libs/ntl/ntl_ZZX.pyx +++ b/src/sage/libs/ntl/ntl_ZZX.pyx @@ -226,7 +226,7 @@ cdef class ntl_ZZX(object): sage: x[0] 129381729371289371237128318293718237 sage: type(x[0]) - + sage: x[1] 2 sage: x[2] @@ -278,7 +278,7 @@ cdef class ntl_ZZX(object): sage: L = x.list(); L [129381729371289371237128318293718237, 2, -3, 0, 4] sage: type(L[0]) - + sage: x = ntl.ZZX() sage: L = x.list(); L [] diff --git a/src/sage/libs/ntl/ntl_ZZ_p.pyx b/src/sage/libs/ntl/ntl_ZZ_p.pyx index 4fab1d1a7cb..114963b1882 100644 --- a/src/sage/libs/ntl/ntl_ZZ_p.pyx +++ b/src/sage/libs/ntl/ntl_ZZ_p.pyx @@ -414,7 +414,7 @@ cdef class ntl_ZZ_p(object): sage: x.lift() 8 sage: type(x.lift()) - + """ cdef ntl_ZZ r = ntl_ZZ() self.c.restore_c() @@ -452,12 +452,12 @@ cdef class ntl_ZZ_p(object): sage: x.lift_centered() 8 sage: type(x.lift_centered()) - + sage: x = ntl.ZZ_p(12, 18) sage: x.lift_centered() -6 sage: type(x.lift_centered()) - + """ cdef ntl_ZZ r = self.lift() cdef ntl_ZZ m = self.modulus() @@ -476,7 +476,7 @@ cdef class ntl_ZZ_p(object): 8 sage: type(x._integer_()) - + """ self.c.restore_c() cdef ZZ_c rep = ZZ_p_rep(self.x) @@ -493,7 +493,7 @@ cdef class ntl_ZZ_p(object): sage: c = ntl.ZZ_pContext(20) sage: n = ntl.ZZ_p(2983, c) sage: type(n._sage_()) - + sage: n 3 diff --git a/src/sage/libs/ntl/ntl_ZZ_pContext.pyx b/src/sage/libs/ntl/ntl_ZZ_pContext.pyx index 0c8995608fd..008e6abd8eb 100644 --- a/src/sage/libs/ntl/ntl_ZZ_pContext.pyx +++ b/src/sage/libs/ntl/ntl_ZZ_pContext.pyx @@ -95,7 +95,7 @@ cdef class ntl_ZZ_pContext_class(object): sage: c = ntl.ZZ_pContext(10^30) sage: type(c.modulus()) - + sage: c.modulus() == 10^30 True """ diff --git a/src/sage/libs/ntl/ntl_ZZ_pE.pyx b/src/sage/libs/ntl/ntl_ZZ_pE.pyx index f46b28f95b5..c2802a3391b 100644 --- a/src/sage/libs/ntl/ntl_ZZ_pE.pyx +++ b/src/sage/libs/ntl/ntl_ZZ_pE.pyx @@ -296,7 +296,7 @@ cdef class ntl_ZZ_pE(object): sage: i [9 1] sage: type(i) - + """ return self.get_as_ZZ_pX() @@ -350,6 +350,6 @@ def make_ZZ_pE(x, c): sage: sage.libs.ntl.ntl_ZZ_pE.make_ZZ_pE([4,3], c) [4 3] sage: type(sage.libs.ntl.ntl_ZZ_pE.make_ZZ_pE([4,3], c)) - + """ return ntl_ZZ_pE(x, c) diff --git a/src/sage/libs/ntl/ntl_ZZ_pEX.pyx b/src/sage/libs/ntl/ntl_ZZ_pEX.pyx index 983bbbe826a..4d48f32025b 100644 --- a/src/sage/libs/ntl/ntl_ZZ_pEX.pyx +++ b/src/sage/libs/ntl/ntl_ZZ_pEX.pyx @@ -1251,6 +1251,6 @@ def make_ZZ_pEX(v, modulus): sage: sage.libs.ntl.ntl_ZZ_pEX.make_ZZ_pEX([a,b,b], c) [[3 2] [1 2] [1 2]] sage: type(sage.libs.ntl.ntl_ZZ_pEX.make_ZZ_pEX([a,b,b], c)) - + """ return ntl_ZZ_pEX(v, modulus) diff --git a/src/sage/libs/ntl/ntl_ZZ_pX.pyx b/src/sage/libs/ntl/ntl_ZZ_pX.pyx index d7fb124c62a..bd34a79c85c 100644 --- a/src/sage/libs/ntl/ntl_ZZ_pX.pyx +++ b/src/sage/libs/ntl/ntl_ZZ_pX.pyx @@ -312,7 +312,7 @@ cdef class ntl_ZZ_pX(object): sage: x.list() [1, 3, 5] sage: type(x.list()[0]) - + """ # could be sped up. self.c.restore_c() diff --git a/src/sage/libs/ntl/ntl_mat_ZZ.pyx b/src/sage/libs/ntl/ntl_mat_ZZ.pyx index db14f86b71d..c9f054602e8 100644 --- a/src/sage/libs/ntl/ntl_mat_ZZ.pyx +++ b/src/sage/libs/ntl/ntl_mat_ZZ.pyx @@ -453,7 +453,7 @@ cdef class ntl_mat_ZZ(object): sage: M.charpoly() [-2 -5 1] sage: type(_) - + sage: M.determinant() -2 """ diff --git a/src/sage/libs/pari/convert_sage.pyx b/src/sage/libs/pari/convert_sage.pyx index c8918beb653..62fe5185cfb 100644 --- a/src/sage/libs/pari/convert_sage.pyx +++ b/src/sage/libs/pari/convert_sage.pyx @@ -251,7 +251,7 @@ cpdef gen_to_sage(Gen z, locals=None): sage: s = pari('"foo"').sage(); s 'foo' sage: type(s) - + """ cdef GEN g = z.g cdef long t = typ(g) diff --git a/src/sage/libs/singular/ring.pyx b/src/sage/libs/singular/ring.pyx index 63b63070cd2..0ed2ff8e04a 100644 --- a/src/sage/libs/singular/ring.pyx +++ b/src/sage/libs/singular/ring.pyx @@ -422,7 +422,7 @@ cdef class ring_wrapper_Py(object): sage: from sage.libs.singular.ring import ring_wrapper_Py sage: ring_wrapper_Py - + """ cdef ring* _ring diff --git a/src/sage/libs/singular/singular.pyx b/src/sage/libs/singular/singular.pyx index c736d56b0c0..cba2147c0ab 100644 --- a/src/sage/libs/singular/singular.pyx +++ b/src/sage/libs/singular/singular.pyx @@ -58,7 +58,7 @@ cdef Rational si2sa_QQ(number *n, number **nn, ring *_ring): sage: P(-1/3).lc() -1/3 sage: type(P(3).lc()) - + """ cdef number *nom cdef number *denom @@ -115,7 +115,7 @@ cdef Integer si2sa_ZZ(number *n, ring *_ring): sage: P(-1234567890).lc() -1234567890 sage: type(P(3).lc()) - + """ cdef Integer z z = Integer() @@ -172,7 +172,7 @@ cdef FFgf2eE si2sa_GFqNTLGF2E(number *n, ring *_ring, Cache_ntl_gf2e cache): sage: f.lc() a^11 + a^10 + a^8 + a^7 + a^6 + a^5 + a^2 + a sage: type(f.lc()) - + """ cdef poly *z cdef long c @@ -207,7 +207,7 @@ cdef object si2sa_GFq_generic(number *n, ring *_ring, object base): sage: f.lc() a^12 + a^11 + a^9 + a^8 + a^7 + 2*a^6 + a^5 sage: type(f.lc()) - + Try the largest characteristic which Singular supports:: diff --git a/src/sage/manifolds/calculus_method.py b/src/sage/manifolds/calculus_method.py index e4d3919e67c..f5830c0bc45 100644 --- a/src/sage/manifolds/calculus_method.py +++ b/src/sage/manifolds/calculus_method.py @@ -52,7 +52,7 @@ def _SR_to_Sympy(expression): sage: a = x^2 + sin(x)^2; a x^2 + sin(x)^2 sage: type(a) - + sage: b = _SR_to_Sympy(a); b x**2 + sin(x)**2 sage: type(b) @@ -89,7 +89,7 @@ def _Sympy_to_SR(expression): sage: from sage.manifolds.calculus_method import _Sympy_to_SR, _SR_to_Sympy sage: a = x^2 + sin(x)^2 sage: type(a) - + sage: b = _SR_to_Sympy(a); b x**2 + sin(x)**2 sage: type(b) diff --git a/src/sage/manifolds/chart.py b/src/sage/manifolds/chart.py index e0630722d3e..8c4e2028aa6 100644 --- a/src/sage/manifolds/chart.py +++ b/src/sage/manifolds/chart.py @@ -206,7 +206,7 @@ class Chart(UniqueRepresentation, SageObject): :mod:`sage.symbolic.expression`):: sage: type(z1) - + In addition to the Python variable name provided in the operator ``<.,.>``, the coordinates are accessible by their indices:: @@ -1502,7 +1502,7 @@ def calculus_method(self): sage: f.expr() x^2 + cos(y)*sin(x) sage: type(f.expr()) - + sage: parent(f.expr()) Symbolic Ring sage: f.display() @@ -1733,7 +1733,7 @@ class RealChart(Chart): :mod:`sage.symbolic.expression`):: sage: type(th) - + sage: latex(th) {\theta} sage: assumptions(th) diff --git a/src/sage/manifolds/chart_func.py b/src/sage/manifolds/chart_func.py index 1c4bf0080c1..6ffc287ca09 100644 --- a/src/sage/manifolds/chart_func.py +++ b/src/sage/manifolds/chart_func.py @@ -134,7 +134,7 @@ class ChartFunction(AlgebraElement, ModuleElementWithMutability): expression:: sage: type(f.expr()) - + A SymPy expression can also be asked for:: @@ -207,7 +207,7 @@ class ChartFunction(AlgebraElement, ModuleElementWithMutability): sage: f0(x,y) = x^2 + 3*y + 1 sage: type(f0) - + sage: f0 (x, y) |--> x^2 + 3*y + 1 sage: f0(x,y) @@ -495,7 +495,7 @@ def expr(self, method=None): sage: f.expr() x^2 + y sage: type(f.expr()) - + Asking for the SymPy expression:: @@ -3057,7 +3057,7 @@ def expr(self, method=None): sage: f.expr() (x - y, x*y, cos(x)*e^y) sage: type(f.expr()[0]) - + A SymPy output:: diff --git a/src/sage/manifolds/continuous_map.py b/src/sage/manifolds/continuous_map.py index 6f060ca13b9..a6356e77f11 100644 --- a/src/sage/manifolds/continuous_map.py +++ b/src/sage/manifolds/continuous_map.py @@ -1503,7 +1503,7 @@ def expr(self, chart1=None, chart2=None): sage: Phi.expr() # equivalent to above since 'uv' and 'xyz' are default charts (u*v, u/v, u + v) sage: type(Phi.expr()[0]) - + Expressions in other charts:: diff --git a/src/sage/manifolds/differentiable/chart.py b/src/sage/manifolds/differentiable/chart.py index 47dd4efd2ec..86a39667cd8 100644 --- a/src/sage/manifolds/differentiable/chart.py +++ b/src/sage/manifolds/differentiable/chart.py @@ -198,7 +198,7 @@ class DiffChart(Chart): :mod:`sage.symbolic.expression`):: sage: type(z1) - + In addition to the Python variable name provided in the operator ``<.,.>``, the coordinates are accessible by their indices:: @@ -829,7 +829,7 @@ class RealDiffChart(DiffChart, RealChart): :mod:`sage.symbolic.expression`):: sage: type(th) - + sage: latex(th) {\theta} sage: assumptions(th) diff --git a/src/sage/manifolds/differentiable/diff_map.py b/src/sage/manifolds/differentiable/diff_map.py index fce91145ed5..7f0c09a6b7c 100644 --- a/src/sage/manifolds/differentiable/diff_map.py +++ b/src/sage/manifolds/differentiable/diff_map.py @@ -760,7 +760,7 @@ def differential_functions(self, chart1=None, chart2=None): sage: JJ[2,0] 2*x sage: type(JJ[2,0]) - + sage: bool( JJ[2,0] == J[2][0].expr() ) True diff --git a/src/sage/manifolds/differentiable/examples/euclidean.py b/src/sage/manifolds/differentiable/examples/euclidean.py index bedc6ece275..b0659787b0e 100644 --- a/src/sage/manifolds/differentiable/examples/euclidean.py +++ b/src/sage/manifolds/differentiable/examples/euclidean.py @@ -57,7 +57,7 @@ sage: y y sage: type(y) - + sage: assumptions() [x is real, y is real] diff --git a/src/sage/manifolds/differentiable/examples/real_line.py b/src/sage/manifolds/differentiable/examples/real_line.py index 09c38be8f8d..15b11a84dc1 100644 --- a/src/sage/manifolds/differentiable/examples/real_line.py +++ b/src/sage/manifolds/differentiable/examples/real_line.py @@ -123,7 +123,7 @@ class OpenInterval(DifferentiableManifold): t sage: t = I.canonical_coordinate() sage: type(t) - + However, it can be obtained in the same step as the interval construction by means of the shortcut ``I.``:: @@ -132,7 +132,7 @@ class OpenInterval(DifferentiableManifold): sage: t t sage: type(t) - + The trick is performed by the Sage preparser:: @@ -577,7 +577,7 @@ def canonical_coordinate(self): sage: I.canonical_coordinate() t sage: type(I.canonical_coordinate()) - + sage: I.canonical_coordinate().is_real() True @@ -777,7 +777,7 @@ class RealLine(OpenInterval): t sage: t = R.canonical_coordinate() sage: type(t) - + However, it can be obtained in the same step as the real line construction by means of the shortcut ``R.``:: @@ -786,7 +786,7 @@ class RealLine(OpenInterval): sage: t t sage: type(t) - + The trick is performed by Sage preparser:: diff --git a/src/sage/manifolds/differentiable/manifold.py b/src/sage/manifolds/differentiable/manifold.py index 7766ebb6543..659c84b2d0c 100644 --- a/src/sage/manifolds/differentiable/manifold.py +++ b/src/sage/manifolds/differentiable/manifold.py @@ -70,7 +70,7 @@ sage: y y sage: type(y) - + The South pole is the point of coordinates `(x,y)=(0,0)` in the above chart:: diff --git a/src/sage/manifolds/differentiable/scalarfield.py b/src/sage/manifolds/differentiable/scalarfield.py index 5885f1fb624..ba66d50ad20 100644 --- a/src/sage/manifolds/differentiable/scalarfield.py +++ b/src/sage/manifolds/differentiable/scalarfield.py @@ -209,7 +209,7 @@ class DiffScalarField(ScalarField): sage: f.expr(c_uv) (u^2 + v^2)/(u^2 + v^2 + 1) sage: type(f.expr(c_uv)) - + The method :meth:`~sage.manifolds.scalarfield.ScalarField.coord_function` returns instead a function of the chart coordinates, i.e. an instance of diff --git a/src/sage/manifolds/manifold.py b/src/sage/manifolds/manifold.py index 2645de657c9..1b62341fc84 100644 --- a/src/sage/manifolds/manifold.py +++ b/src/sage/manifolds/manifold.py @@ -60,7 +60,7 @@ sage: y y sage: type(y) - + The South pole is the point of coordinates `(x, y) = (0, 0)` in the above chart:: @@ -1550,7 +1550,7 @@ def chart(self, coordinates='', names=None, calc_method=None, sage: y y sage: type(y) - + But a shorter way to proceed is to use the operator ``<,>`` in the left-hand side of the chart declaration (there is then no need to @@ -2511,7 +2511,7 @@ def set_calculus_method(self, method): sage: f.expr() x^2 + cos(y)*sin(x) sage: type(f.expr()) - + sage: parent(f.expr()) Symbolic Ring sage: f.display() diff --git a/src/sage/manifolds/scalarfield.py b/src/sage/manifolds/scalarfield.py index 29378d6a872..8409ed656b3 100644 --- a/src/sage/manifolds/scalarfield.py +++ b/src/sage/manifolds/scalarfield.py @@ -211,7 +211,7 @@ class ScalarField(CommutativeAlgebraElement, ModuleElementWithMutability): sage: f.expr(c_uv) (u^2 + v^2)/(u^2 + v^2 + 1) sage: type(f.expr(c_uv)) - + The method :meth:`coord_function` returns instead a function of the chart coordinates, i.e. an instance of @@ -1844,7 +1844,7 @@ def expr(self, chart=None, from_chart=None): backend used for coordinate computations:: sage: type(f.expr()) - + sage: M.set_calculus_method('sympy') sage: type(f.expr()) diff --git a/src/sage/matrix/matrix0.pyx b/src/sage/matrix/matrix0.pyx index 41b8da5f415..8a3ea5918c4 100644 --- a/src/sage/matrix/matrix0.pyx +++ b/src/sage/matrix/matrix0.pyx @@ -78,7 +78,7 @@ cdef class Matrix(sage.structure.element.Matrix): [1.0 2.0 3.0] [4.0 5.0 6.0] sage: type(a) - + sage: parent(a) Full MatrixSpace of 2 by 3 dense matrices over Complex Double Field @@ -112,7 +112,7 @@ cdef class Matrix(sage.structure.element.Matrix): sage: import sage.matrix.matrix0 sage: A = sage.matrix.matrix0.Matrix(MatrixSpace(QQ,2)) sage: type(A) - + """ P = parent self._parent = P @@ -885,11 +885,11 @@ cdef class Matrix(sage.structure.element.Matrix): sage: M = MatrixSpace(GF(2), 3, 3, implementation='generic') sage: m = M(range(9)) sage: type(m) - + sage: parent(m) Full MatrixSpace of 3 by 3 dense matrices over Finite Field of size 2 (using Matrix_generic_dense) sage: type(m[:2,:2]) - + sage: parent(m[:2,:2]) Full MatrixSpace of 2 by 2 dense matrices over Finite Field of size 2 (using Matrix_generic_dense) """ @@ -5563,13 +5563,13 @@ cdef class Matrix(sage.structure.element.Matrix): sage: m = matrix(Zmod(49),2,[2,1,3,3]) sage: type(m) - + sage: ~m [ 1 16] [48 17] sage: m = matrix(Zmod(2^100),2,[2,1,3,3]) sage: type(m) - + sage: (~m)*m [1 0] [0 1] diff --git a/src/sage/matrix/matrix2.pyx b/src/sage/matrix/matrix2.pyx index d4a8ec9d3a1..b951e962342 100644 --- a/src/sage/matrix/matrix2.pyx +++ b/src/sage/matrix/matrix2.pyx @@ -2851,7 +2851,7 @@ cdef class Matrix(Matrix1): sage: M = MatrixSpace(RR, 2) sage: A = M(range(2^2)) sage: type(A) - + sage: A.charpoly('x') x^2 - 3.00000000000000*x - 2.00000000000000 sage: A.charpoly('y') @@ -15150,7 +15150,7 @@ cdef class Matrix(Matrix1): [ 1/11*(sqrt(33)*e^sqrt(33) - sqrt(33))*e^(-1/2*sqrt(33) + 5/2) 1/22*((sqrt(33) + 11)*e^sqrt(33) - sqrt(33) + 11)*e^(-1/2*sqrt(33) + 5/2)] sage: type(a.exp()) - + sage: a=matrix([[1/2,2/3],[3/4,4/5]]) sage: a.exp() diff --git a/src/sage/matrix/matrix_complex_ball_dense.pyx b/src/sage/matrix/matrix_complex_ball_dense.pyx index 4a3fd675681..4bd1313506d 100644 --- a/src/sage/matrix/matrix_complex_ball_dense.pyx +++ b/src/sage/matrix/matrix_complex_ball_dense.pyx @@ -143,7 +143,7 @@ cdef class Matrix_complex_ball_dense(Matrix_dense): sage: a = Matrix_complex_ball_dense.__new__( # indirect doctest ....: Matrix_complex_ball_dense, Mat(CBF, 2), 0, 0, 0) sage: type(a) - + """ sig_str("Arb exception") acb_mat_init(self.value, self._nrows, self._ncols) diff --git a/src/sage/matrix/matrix_cyclo_dense.pyx b/src/sage/matrix/matrix_cyclo_dense.pyx index eef7a331ee7..1845be41cbd 100644 --- a/src/sage/matrix/matrix_cyclo_dense.pyx +++ b/src/sage/matrix/matrix_cyclo_dense.pyx @@ -96,7 +96,7 @@ cdef class Matrix_cyclo_dense(Matrix_dense): sage: from sage.matrix.matrix_cyclo_dense import Matrix_cyclo_dense sage: A = Matrix_cyclo_dense.__new__(Matrix_cyclo_dense, MatrixSpace(CyclotomicField(3),2), [0,1,2,3], True, True) sage: type(A) - + Note that the entries of A haven't even been set yet above; that doesn't happen until ``__init__`` is called:: diff --git a/src/sage/matrix/matrix_gap.pyx b/src/sage/matrix/matrix_gap.pyx index 0fff7a1f006..4a19dd4904e 100644 --- a/src/sage/matrix/matrix_gap.pyx +++ b/src/sage/matrix/matrix_gap.pyx @@ -27,13 +27,13 @@ cdef class Matrix_gap(Matrix_dense): sage: m1 = M([1, 0, 2, -3]) sage: m2 = M([2, 2, 5, -1]) sage: type(m1) - + sage: m1 * m2 [ 2 2] [-11 7] sage: type(m1 * m2) - + sage: M = MatrixSpace(QQ, 5, 3, implementation='gap') sage: m = M(range(15)) @@ -94,11 +94,11 @@ cdef class Matrix_gap(Matrix_dense): [2 0] [0 2] sage: type(M(0)) - + sage: type(M(1)) - + sage: type(M(2)) - + sage: M = MatrixSpace(QQ, 2, 3, implementation='gap') sage: M(0) @@ -175,7 +175,7 @@ cdef class Matrix_gap(Matrix_dense): sage: m [ [ 1, 2 ], [ 2, 1 ] ] sage: type(m) - + sage: m.MatrixAutomorphisms() Group([ (1,2) ]) diff --git a/src/sage/matrix/matrix_generic_dense.pyx b/src/sage/matrix/matrix_generic_dense.pyx index 3f01179dd14..7c0058db1d2 100644 --- a/src/sage/matrix/matrix_generic_dense.pyx +++ b/src/sage/matrix/matrix_generic_dense.pyx @@ -27,7 +27,7 @@ cdef class Matrix_generic_dense(matrix_dense.Matrix_dense): sage: A = random_matrix(Integers(25)['x'], 2) sage: type(A) - + sage: TestSuite(A).run() Test comparisons:: @@ -270,7 +270,7 @@ cdef class Matrix_generic_dense(matrix_dense.Matrix_dense): [ x y] [x^2 y^2] sage: type(a) - + sage: a*a [ x^2*y + x^2 y^3 + x*y] [x^2*y^2 + x^3 y^4 + x^2*y] diff --git a/src/sage/matrix/matrix_gfpn_dense.pyx b/src/sage/matrix/matrix_gfpn_dense.pyx index 32b77a861fa..1115e7b2c87 100644 --- a/src/sage/matrix/matrix_gfpn_dense.pyx +++ b/src/sage/matrix/matrix_gfpn_dense.pyx @@ -345,7 +345,7 @@ cdef class Matrix_gfpn_dense(Matrix_dense): [1 2 3] [4 0 1] sage: type(M) - + The documentation of the ``__init__`` methods shows further ways of creating a :class:`Matrix_gfpn_dense` instance. @@ -565,7 +565,7 @@ cdef class Matrix_gfpn_dense(Matrix_dense): sage: F. = GF(9) sage: M = MatrixSpace(F,3)(sorted(list(F))) sage: type(M) - + sage: M # indirect doctest [ 0 1 2] [ z z + 1 z + 2] @@ -709,7 +709,7 @@ cdef class Matrix_gfpn_dense(Matrix_dense): [ 2*z^2 + z 2*z 2*z^2 + 2*z + 1 2*z^2 + 1 2*z^2 + 2*z + 1 2*z^2 + z] [ 2*z + 1 z^2 + z z^2 z^2 2*z^2 + 2*z z + 1] sage: type(M) - + sage: MS.random_element(nonzero=True) [ 2*z 1 z^2 + 2*z + 1 2*z^2 + z + 1 z^2 z^2 + z + 1] [ 2*z^2 + 2*z 2*z^2 + z + 2 2*z + 1 z^2 + 2*z 2*z^2 + 2*z z^2] @@ -1732,11 +1732,11 @@ cdef class Matrix_gfpn_dense(Matrix_dense): implementation of dense matrices:: sage: type(M) - + sage: MS = MatrixSpace(M.base_ring(), M.nrows(), M.ncols(), implementation='generic') sage: X = MS(M) sage: type(X) - + sage: X.echelon_form() [ 0 1 0 0 0 0 0 0 0 4*x + 4] [ 0 0 1 0 0 0 0 0 0 4*x + 2] @@ -1876,7 +1876,7 @@ def mtx_unpickle(f, int nr, int nc, data, bint m): [ 6 7 8 9 10] [12 11 10 9 8] sage: type(N) - + We demonstrate that a slightly different pickle format can be understood as well, that was at some point used by some optional package:: diff --git a/src/sage/matrix/matrix_integer_dense.pyx b/src/sage/matrix/matrix_integer_dense.pyx index 5422d985eee..c9dcecdef47 100644 --- a/src/sage/matrix/matrix_integer_dense.pyx +++ b/src/sage/matrix/matrix_integer_dense.pyx @@ -216,7 +216,7 @@ cdef class Matrix_integer_dense(Matrix_dense): sage: from sage.matrix.matrix_integer_dense import Matrix_integer_dense sage: a = Matrix_integer_dense.__new__(Matrix_integer_dense, Mat(ZZ,3), 0,0,0) sage: type(a) - + TESTS:: @@ -1303,7 +1303,7 @@ cdef class Matrix_integer_dense(Matrix_dense): sage: M = MatrixSpace(ZZ, 2) sage: A = M(range(0, 2^2)) sage: type(A) - + sage: A.charpoly('x') x^2 - 3*x - 2 sage: A.charpoly('y') @@ -5546,7 +5546,7 @@ cdef class Matrix_integer_dense(Matrix_dense): sage: A = matrix(ZZ, 2, 3, range(6)) sage: type(A) - + sage: B = A.transpose() sage: print(B) [0 3] @@ -5592,7 +5592,7 @@ cdef class Matrix_integer_dense(Matrix_dense): sage: A = matrix(2,3,range(6)) sage: type(A) - + sage: A.antitranspose() [5 2] [4 1] @@ -5645,7 +5645,7 @@ cdef class Matrix_integer_dense(Matrix_dense): sage: pari(a) [1, 2; 3, 4] sage: type(pari(a)) - + """ return integer_matrix(self._matrix, 0) diff --git a/src/sage/matrix/matrix_mod2_dense.pyx b/src/sage/matrix/matrix_mod2_dense.pyx index 8f1374eb39f..d583e5fa2e7 100644 --- a/src/sage/matrix/matrix_mod2_dense.pyx +++ b/src/sage/matrix/matrix_mod2_dense.pyx @@ -17,7 +17,7 @@ EXAMPLES:: sage: a.rank() 2 sage: type(a) - + sage: a[0,0] = 1 sage: a.rank() 3 @@ -237,7 +237,7 @@ cdef class Matrix_mod2_dense(matrix_dense.Matrix_dense): # dense or sparse EXAMPLES:: sage: type(random_matrix(GF(2),2,2)) - + sage: Matrix(GF(2),3,3,1) [1 0 0] @@ -1528,7 +1528,7 @@ cdef class Matrix_mod2_dense(matrix_dense.Matrix_dense): # dense or sparse Traceback (most recent call last): ... TypeError: right must either be a matrix or a vector. Not - + """ cdef Matrix_mod2_dense other diff --git a/src/sage/matrix/matrix_modn_dense_double.pyx b/src/sage/matrix/matrix_modn_dense_double.pyx index cb8f2a09e24..dfd27b78db2 100644 --- a/src/sage/matrix/matrix_modn_dense_double.pyx +++ b/src/sage/matrix/matrix_modn_dense_double.pyx @@ -68,7 +68,7 @@ cdef class Matrix_modn_dense_double(Matrix_modn_dense_template): sage: A = random_matrix(IntegerModRing(2^16), 4, 4) sage: type(A[0,0]) - + """ self._get_template = self._base_ring.zero() # note that INTEGER_MOD_INT32_LIMIT is ceil(sqrt(2^31-1)) < 2^23 diff --git a/src/sage/matrix/matrix_modn_dense_float.pyx b/src/sage/matrix/matrix_modn_dense_float.pyx index 8a215de6f66..9435794c4c1 100644 --- a/src/sage/matrix/matrix_modn_dense_float.pyx +++ b/src/sage/matrix/matrix_modn_dense_float.pyx @@ -63,7 +63,7 @@ cdef class Matrix_modn_dense_float(Matrix_modn_dense_template): sage: A = random_matrix(GF(7), 4, 4) sage: type(A[0,0]) - + """ self._get_template = self._base_ring.zero() diff --git a/src/sage/matrix/matrix_modn_dense_template.pxi b/src/sage/matrix/matrix_modn_dense_template.pxi index a04d3874a0f..010365d76f5 100644 --- a/src/sage/matrix/matrix_modn_dense_template.pxi +++ b/src/sage/matrix/matrix_modn_dense_template.pxi @@ -475,13 +475,13 @@ cdef class Matrix_modn_dense_template(Matrix_dense): sage: A = random_matrix(GF(3),1000,1000) sage: type(A) - + sage: A = random_matrix(Integers(10),1000,1000) sage: type(A) - + sage: A = random_matrix(Integers(2^16),1000,1000) sage: type(A) - + TESTS:: @@ -1350,7 +1350,7 @@ cdef class Matrix_modn_dense_template(Matrix_dense): sage: M = MatrixSpace(Integers(37), 2) sage: A = M(range(0, 2^2)) sage: type(A) - + sage: A.charpoly('x').variables() (x,) sage: A.charpoly('y').variables() diff --git a/src/sage/matrix/matrix_modn_sparse.pyx b/src/sage/matrix/matrix_modn_sparse.pyx index 9762f857e7c..fb9c6736ea0 100644 --- a/src/sage/matrix/matrix_modn_sparse.pyx +++ b/src/sage/matrix/matrix_modn_sparse.pyx @@ -16,7 +16,7 @@ EXAMPLES:: [3 4 5] [6 7 8] sage: type(a) - + sage: parent(a) Full MatrixSpace of 3 by 3 sparse matrices over Ring of integers modulo 37 sage: a^2 @@ -359,13 +359,13 @@ cdef class Matrix_modn_sparse(matrix_sparse.Matrix_sparse): [ 9 12 15] [19 26 33] sage: type(c) - + sage: a = matrix(GF(2), 20, 20, sparse=True) sage: a*a == a._matrix_times_matrix_dense(a) True sage: type(a._matrix_times_matrix_dense(a)) - + """ cdef Matrix_modn_sparse right cdef matrix_dense.Matrix_dense ans diff --git a/src/sage/matrix/matrix_rational_dense.pyx b/src/sage/matrix/matrix_rational_dense.pyx index bf343014db5..b54751066f4 100644 --- a/src/sage/matrix/matrix_rational_dense.pyx +++ b/src/sage/matrix/matrix_rational_dense.pyx @@ -139,7 +139,7 @@ cdef class Matrix_rational_dense(Matrix_dense): sage: from sage.matrix.matrix_rational_dense import Matrix_rational_dense sage: a = Matrix_rational_dense.__new__(Matrix_rational_dense, Mat(ZZ,3), 0,0,0) sage: type(a) - + .. WARNING:: @@ -1022,7 +1022,7 @@ cdef class Matrix_rational_dense(Matrix_dense): sage: M = MatrixSpace(QQ, 2) sage: A = M(range(0, 2^2)) sage: type(A) - + sage: A.charpoly('x') x^2 - 3*x - 2 sage: A.charpoly('y') @@ -2548,7 +2548,7 @@ cdef class Matrix_rational_dense(Matrix_dense): sage: A = matrix(QQ, 2, 3, range(6)) sage: type(A) - + sage: B = A.transpose() sage: print(B) [0 3] @@ -2599,7 +2599,7 @@ cdef class Matrix_rational_dense(Matrix_dense): sage: A = matrix(QQ,2,3,range(6)) sage: type(A) - + sage: A.antitranspose() [5 2] [4 1] diff --git a/src/sage/matrix/matrix_rational_sparse.pyx b/src/sage/matrix/matrix_rational_sparse.pyx index b00416b8e92..aa92bf206a7 100644 --- a/src/sage/matrix/matrix_rational_sparse.pyx +++ b/src/sage/matrix/matrix_rational_sparse.pyx @@ -229,7 +229,7 @@ cdef class Matrix_rational_sparse(Matrix_sparse): [ 9 12 15] [19 26 33] sage: type(c) - + """ cdef Matrix_rational_sparse right cdef Matrix_rational_dense ans @@ -620,9 +620,9 @@ cdef class Matrix_rational_sparse(Matrix_sparse): EXAMPLES:: sage: a = matrix(QQ,2,[1..4],sparse=True); type(a) - + sage: type(a.dense_matrix()) - + sage: a.dense_matrix() [1 2] [3 4] diff --git a/src/sage/matrix/matrix_sparse.pyx b/src/sage/matrix/matrix_sparse.pyx index ac795c9b71e..0d8c4abb46e 100644 --- a/src/sage/matrix/matrix_sparse.pyx +++ b/src/sage/matrix/matrix_sparse.pyx @@ -176,7 +176,7 @@ cdef class Matrix_sparse(matrix.Matrix): sage: A = matrix(QQ['x,y'], 2, [0,-1,2,-2], sparse=True) sage: type(A) - + sage: B = matrix(QQ['x,y'], 2, [-1,-1,-2,-2], sparse=True) sage: A * B [2 2] @@ -239,7 +239,7 @@ cdef class Matrix_sparse(matrix.Matrix): sage: A = matrix(QQ['x,y'], 2, [0,-1,2,-2], sparse=True) sage: type(A) - + sage: B = matrix(QQ['x,y'], 2, [-1,-1,-2,-2], sparse=True) sage: A._multiply_classical_with_cache(B) [2 2] diff --git a/src/sage/matrix/matrix_symbolic_dense.pyx b/src/sage/matrix/matrix_symbolic_dense.pyx index f67a25e9ccb..ded3a0dc0a1 100644 --- a/src/sage/matrix/matrix_symbolic_dense.pyx +++ b/src/sage/matrix/matrix_symbolic_dense.pyx @@ -264,7 +264,7 @@ cdef class Matrix_symbolic_dense(Matrix_generic_dense): sage: spectrum = am.eigenvectors_left() sage: symbolic_evalue = spectrum[2][0] sage: type(symbolic_evalue) - + sage: symbolic_evalue 1/2*sqrt(5) - 1/2 @@ -484,7 +484,7 @@ cdef class Matrix_symbolic_dense(Matrix_generic_dense): sage: M = MatrixSpace(SR, 2) sage: A = M(range(0, 2^2)) sage: type(A) - + sage: A.charpoly('x') x^2 - 3*x - 2 sage: A.charpoly('y') diff --git a/src/sage/matrix/special.py b/src/sage/matrix/special.py index 5e56ddeebea..bcb0b0293af 100644 --- a/src/sage/matrix/special.py +++ b/src/sage/matrix/special.py @@ -399,9 +399,9 @@ def random_matrix(ring, nrows, ncols=None, algorithm='randomize', implementation sage: K. = FiniteField(2^8) sage: type(random_matrix(K, 2, 5)) - + sage: type(random_matrix(K, 2, 5, implementation="generic")) - + Random rational matrices. Now ``num_bound`` and ``den_bound`` control the generation of random elements, by specifying limits on the absolute value of diff --git a/src/sage/rings/asymptotic/asymptotic_ring.py b/src/sage/rings/asymptotic/asymptotic_ring.py index a474bf4d1eb..f7e3d0c235e 100644 --- a/src/sage/rings/asymptotic/asymptotic_ring.py +++ b/src/sage/rings/asymptotic/asymptotic_ring.py @@ -2601,7 +2601,7 @@ def substitute(self, rules=None, domain=None, **kwds): ... TypeError: Cannot substitute u in u since it is neither an asymptotic expansion nor a string - (but a ). + (but a ). :: diff --git a/src/sage/rings/cfinite_sequence.py b/src/sage/rings/cfinite_sequence.py index c7821c2a387..b73764ce5d2 100644 --- a/src/sage/rings/cfinite_sequence.py +++ b/src/sage/rings/cfinite_sequence.py @@ -776,7 +776,7 @@ def series(self, n): sage: s = r.series(4); s x + 2*x^2 + 3*x^3 + 4*x^4 + O(x^5) sage: type(s) - + """ R = LaurentSeriesRing(QQ, 'x', default_prec=n) return R(self.ogf()) diff --git a/src/sage/rings/complex_arb.pyx b/src/sage/rings/complex_arb.pyx index 9aa6ba15d7b..da6aac2dab5 100644 --- a/src/sage/rings/complex_arb.pyx +++ b/src/sage/rings/complex_arb.pyx @@ -2476,7 +2476,7 @@ cdef class ComplexBall(RingElement): sage: CBF(sqrt(2)).contains_exact(sqrt(2)) Traceback (most recent call last): ... - TypeError: unsupported type: + TypeError: unsupported type: """ cdef fmpz_t tmpz cdef fmpq_t tmpq diff --git a/src/sage/rings/complex_double.pyx b/src/sage/rings/complex_double.pyx index aa45ef96602..fb56eb43da2 100644 --- a/src/sage/rings/complex_double.pyx +++ b/src/sage/rings/complex_double.pyx @@ -23,7 +23,7 @@ EXAMPLES:: sage: CDF Complex Double Field sage: type(CDF.0) - + sage: ComplexDoubleElement(sqrt(2),3) 1.4142135623730951 + 3.0*I sage: parent(CDF(-2)) diff --git a/src/sage/rings/complex_mpc.pyx b/src/sage/rings/complex_mpc.pyx index 04e8019bb2e..e7f287aa9c9 100644 --- a/src/sage/rings/complex_mpc.pyx +++ b/src/sage/rings/complex_mpc.pyx @@ -409,7 +409,7 @@ cdef class MPComplexField_class(sage.rings.ring.Field): sage: C20(i*4, 7) Traceback (most recent call last): ... - TypeError: unable to coerce to a ComplexNumber: + TypeError: unable to coerce to a ComplexNumber: Each part can be set with strings (written in base ten):: diff --git a/src/sage/rings/complex_mpfr.pyx b/src/sage/rings/complex_mpfr.pyx index e3f609a43c6..d36f24a6fd5 100644 --- a/src/sage/rings/complex_mpfr.pyx +++ b/src/sage/rings/complex_mpfr.pyx @@ -1382,11 +1382,11 @@ cdef class ComplexNumber(sage.structure.element.FieldElement): sage: pari(a).type() 't_COMPLEX' sage: type(pari(a)) - + sage: a.__pari__() 2.00000000000000 + 1.00000000000000*I sage: type(a.__pari__()) - + sage: a = CC(pi) sage: pari(a) 3.14159265358979 diff --git a/src/sage/rings/continued_fraction.py b/src/sage/rings/continued_fraction.py index 7e4611e435f..cf5f8b1f9eb 100644 --- a/src/sage/rings/continued_fraction.py +++ b/src/sage/rings/continued_fraction.py @@ -2051,7 +2051,7 @@ def __init__(self, w, value=None, check=True): sage: w = words.ThueMorseWord([int(1), int(2)]) sage: t = continued_fraction(w) sage: type(t.quotient(1)) - + """ ContinuedFraction_base.__init__(self) self._w = w @@ -2157,7 +2157,7 @@ def _Integer_quotient(self, n): sage: t.quotient(1) 2 sage: type(t.quotient(1)) # indirect doctest - + """ return Integer(self._w[n]) @@ -2407,7 +2407,7 @@ def continued_fraction_list(x, type="std", partial_convergents=False, sage: a = 1.575709393346379 sage: type(a) - + sage: continued_fraction_list(a) [1, 1, 1, 2, 1, 4, 18, 1, 5, 2, 25037802, 7, 1, 3, 1, 28, 1, 8, 2] diff --git a/src/sage/rings/fast_arith.pyx b/src/sage/rings/fast_arith.pyx index aecfdf6bb0f..1eab26ba803 100644 --- a/src/sage/rings/fast_arith.pyx +++ b/src/sage/rings/fast_arith.pyx @@ -96,9 +96,9 @@ cpdef prime_range(start, stop=None, algorithm=None, bint py_ints=False): sage: prime_range(10**30,10**30+100,"pari_isprime") [1000000000000000000000000000057, 1000000000000000000000000000099] sage: type(prime_range(8)[0]) - + sage: type(prime_range(8,algorithm="pari_isprime")[0]) - + .. NOTE:: diff --git a/src/sage/rings/finite_rings/element_base.pyx b/src/sage/rings/finite_rings/element_base.pyx index d4c06183317..492a30983c9 100755 --- a/src/sage/rings/finite_rings/element_base.pyx +++ b/src/sage/rings/finite_rings/element_base.pyx @@ -339,7 +339,7 @@ cdef class FinitePolyExtElement(FiniteRingElement): sage: t_element 3*b^2 + 2*b + 4 sage: type(t_element) - + """ if var is None: var = self.parent().variable_name() diff --git a/src/sage/rings/finite_rings/element_givaro.pyx b/src/sage/rings/finite_rings/element_givaro.pyx index 82f4bb2e99a..e28808d84bf 100644 --- a/src/sage/rings/finite_rings/element_givaro.pyx +++ b/src/sage/rings/finite_rings/element_givaro.pyx @@ -300,7 +300,7 @@ cdef class Cache_givaro(Cache_base): sage: e.parent() is k True sage: type(e) - + sage: P. = PowerSeriesRing(GF(3^3, 'a')) sage: P.random_element(5).parent() is P @@ -1413,7 +1413,7 @@ cdef class FiniteField_givaroElement(FinitePolyExtElement): sage: b._log_to_int() 5 sage: type(b._log_to_int()) - + """ return Integer(self._cache.log_to_int(self.element)) @@ -1494,7 +1494,7 @@ cdef class FiniteField_givaroElement(FinitePolyExtElement): sage: f = (b^2+1).polynomial(); f b + 4 sage: type(f) - + sage: parent(f) Univariate Polynomial Ring in b over Finite Field of size 5 """ diff --git a/src/sage/rings/finite_rings/element_pari_ffelt.pyx b/src/sage/rings/finite_rings/element_pari_ffelt.pyx index 57baa162b0b..95922cd42d0 100644 --- a/src/sage/rings/finite_rings/element_pari_ffelt.pyx +++ b/src/sage/rings/finite_rings/element_pari_ffelt.pyx @@ -98,7 +98,7 @@ cdef class FiniteFieldElement_pari_ffelt(FinitePolyExtElement): sage: a = K.gen(); a a sage: type(a) - + TESTS:: diff --git a/src/sage/rings/finite_rings/finite_field_constructor.py b/src/sage/rings/finite_rings/finite_field_constructor.py index 0980ff8dbdf..d7b4e15985f 100644 --- a/src/sage/rings/finite_rings/finite_field_constructor.py +++ b/src/sage/rings/finite_rings/finite_field_constructor.py @@ -284,7 +284,7 @@ class FiniteFieldFactory(UniqueFactory): sage: f = K.modulus(); f x^5 + 4*x + 1 sage: type(f) - + By default, the given generator is not guaranteed to be primitive (a generator of the multiplicative group), use diff --git a/src/sage/rings/finite_rings/finite_field_givaro.py b/src/sage/rings/finite_rings/finite_field_givaro.py index e686ef8424b..dbeddd8705e 100644 --- a/src/sage/rings/finite_rings/finite_field_givaro.py +++ b/src/sage/rings/finite_rings/finite_field_givaro.py @@ -152,7 +152,7 @@ def characteristic(self): sage: p = GF(19^5,'a').characteristic(); p 19 sage: type(p) - + """ return Integer(self._cache.characteristic()) @@ -169,7 +169,7 @@ def order(self): sage: n = GF(19^5,'a').order(); n 2476099 sage: type(n) - + """ return self._cache.order() @@ -218,7 +218,7 @@ def random_element(self, *args, **kwds): sage: e.parent() is k True sage: type(e) - + sage: P. = PowerSeriesRing(GF(3^3, 'a')) sage: P.random_element(5).parent() is P 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 28c8b3935c0..698c54e71b5 100644 --- a/src/sage/rings/finite_rings/hom_finite_field_givaro.pyx +++ b/src/sage/rings/finite_rings/hom_finite_field_givaro.pyx @@ -204,13 +204,13 @@ cdef class FrobeniusEndomorphism_givaro(FrobeniusEndomorphism_finite_field): sage: Frob = k.frobenius_endomorphism(); Frob Frobenius endomorphism t |--> t^5 on Finite Field in t of size 5^3 sage: type(Frob) - + sage: k. = GF(5^20) sage: Frob = k.frobenius_endomorphism(); Frob Frobenius endomorphism t |--> t^5 on Finite Field in t of size 5^20 sage: type(Frob) - + """ if not isinstance(domain, FiniteField_givaro): raise TypeError("The domain is not an instance of FiniteField_givaro") diff --git a/src/sage/rings/finite_rings/residue_field.pyx b/src/sage/rings/finite_rings/residue_field.pyx index 007a68e4c0f..62bebc2303b 100644 --- a/src/sage/rings/finite_rings/residue_field.pyx +++ b/src/sage/rings/finite_rings/residue_field.pyx @@ -963,7 +963,7 @@ cdef class ReductionMap(Map): sage: K = R.fraction_field() sage: f = k.convert_map_from(K) sage: type(f) - + sage: f(1/t) a^4 + a sage: f(1/h) @@ -1143,7 +1143,7 @@ cdef class ResidueFieldHomomorphism_global(RingHomomorphism): From: Maximal Order in Cyclotomic Field of order 5 and degree 4 To: Residue field in a of Fractional ideal (7) sage: type(phi) - + sage: R. = GF(2)[]; P = R.ideal(t^7 + t^6 + t^5 + t^4 + 1) sage: k = P.residue_field(); f = k.coerce_map_from(R) @@ -1606,7 +1606,7 @@ class ResidueFiniteField_prime_modn(ResidueField_generic, FiniteField_prime_modn 2 sage: V = k.vector_space(map=False); v = V([3]) sage: type(k.convert_map_from(V)) - + sage: k(v) # indirect doctest 3 @@ -1698,7 +1698,7 @@ class ResidueFiniteField_pari_ffelt(ResidueField_generic, FiniteField_pari_ffelt 6677 sage: V = ff.vector_space(map=False); v = V([3,-2]) sage: type(ff.convert_map_from(V)) - + sage: ff(v) # indirect doctest 10005*alpha + 3 @@ -1800,7 +1800,7 @@ class ResidueFiniteField_givaro(ResidueField_generic, FiniteField_givaro): 2*abar + 4 sage: V = k.vector_space(map=False); v = V([3,-2]) sage: type(k.convert_map_from(V)) - + sage: k(v) # indirect doctest 59*abar + 3 @@ -1906,7 +1906,7 @@ class ResidueFiniteField_ntl_gf2e(ResidueField_generic, FiniteField_ntl_gf2e): 2*abar + 4 sage: V = k.vector_space(map=False); v = V([3,-2]) sage: type(k.convert_map_from(V)) - + sage: k(v) # indirect doctest 59*abar + 3 diff --git a/src/sage/rings/fraction_field.py b/src/sage/rings/fraction_field.py index c5b5c55a785..8d8d4c49c80 100644 --- a/src/sage/rings/fraction_field.py +++ b/src/sage/rings/fraction_field.py @@ -948,7 +948,7 @@ def __init__(self, R, sage: R. = QQ[]; K = R.fraction_field() sage: K._element_class - + """ FractionField_generic.__init__(self, R, element_class) diff --git a/src/sage/rings/fraction_field_FpT.pyx b/src/sage/rings/fraction_field_FpT.pyx index 7ad2a7359ab..b81535fe5bd 100644 --- a/src/sage/rings/fraction_field_FpT.pyx +++ b/src/sage/rings/fraction_field_FpT.pyx @@ -1033,7 +1033,7 @@ cdef class Polyring_FpT_coerce(RingHomomorphism): From: Univariate Polynomial Ring in t over Finite Field of size 5 To: Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 5 sage: type(f) - + TESTS:: @@ -1222,7 +1222,7 @@ cdef class FpT_Polyring_section(Section): From: Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 5 To: Univariate Polynomial Ring in t over Finite Field of size 5 sage: type(f) - + .. WARNING:: @@ -1351,7 +1351,7 @@ cdef class Fp_FpT_coerce(RingHomomorphism): From: Finite Field of size 5 To: Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 5 sage: type(f) - + TESTS:: @@ -1524,7 +1524,7 @@ cdef class FpT_Fp_section(Section): From: Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 5 To: Finite Field of size 5 sage: type(f) - + .. WARNING:: @@ -1673,7 +1673,7 @@ cdef class ZZ_FpT_coerce(RingHomomorphism): From: Integer Ring To: Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 17 sage: type(f) - + TESTS:: diff --git a/src/sage/rings/fraction_field_element.pyx b/src/sage/rings/fraction_field_element.pyx index 4206b1dd4d8..4d1235c88c4 100644 --- a/src/sage/rings/fraction_field_element.pyx +++ b/src/sage/rings/fraction_field_element.pyx @@ -861,15 +861,15 @@ cdef class FractionFieldElement(FieldElement): sage: a = x^2; a x^2 sage: type(a.numerator()) - + sage: type(a.denominator()) - + sage: a = x^(-2); a 1/x^2 sage: type(a.numerator()) - + sage: type(a.denominator()) - + sage: x^0 1 sage: ((x+y)/(x-y))^2 diff --git a/src/sage/rings/integer.pyx b/src/sage/rings/integer.pyx index f468b59bf68..f88a4d4ea89 100644 --- a/src/sage/rings/integer.pyx +++ b/src/sage/rings/integer.pyx @@ -2132,7 +2132,7 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): 2^I sage: r = 2 ^ int(-3); r; type(r) 1/8 - + sage: f = 2^(sin(x)-cos(x)); f 2^(-cos(x) + sin(x)) sage: f(x=3) @@ -5948,7 +5948,7 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): sage: m = n.__pari__(); m 9390823 sage: type(m) - + TESTS:: @@ -6187,13 +6187,13 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): TESTS:: sage: type(5.sqrt()) - + sage: type(5.sqrt(prec=53)) - + sage: type((-5).sqrt(prec=53)) - + sage: type(0.sqrt(prec=53)) - + Check that :trac:`9466` and :trac:`26509` are fixed:: @@ -7058,7 +7058,7 @@ def GCD_list(v): sage: w = GCD_list([3,9,30]); w 3 sage: type(w) - + Check that the bug reported in :trac:`3118` has been fixed:: @@ -7072,7 +7072,7 @@ def GCD_list(v): sage: w = GCD_list([int(3), int(9), '30']); w 3 sage: type(w) - + Check that the GCD of the empty list is zero (:trac:`17257`):: @@ -7137,11 +7137,11 @@ cdef class int_to_Z(Morphism): sage: f(5r) 5 sage: type(f(5r)) - + sage: 1 + 2r 3 sage: type(1 + 2r) - + This is intended for internal use by the coercion system, to facilitate fast expressions mixing ints and more complex diff --git a/src/sage/rings/integer_ring.pyx b/src/sage/rings/integer_ring.pyx index 99befbb94a7..f6308251e80 100644 --- a/src/sage/rings/integer_ring.pyx +++ b/src/sage/rings/integer_ring.pyx @@ -26,7 +26,7 @@ other types will also coerce to the integers, when it makes sense. sage: b = Z(5678); b 5678 sage: type(a) - + sage: a + b 6912 sage: Z('94803849083985934859834583945394') @@ -183,7 +183,7 @@ cdef class IntegerRing_class(PrincipalIdealDomain): sage: b = Z(5678); b 5678 sage: type(a) - + sage: a + b 6912 sage: b + a @@ -206,18 +206,18 @@ cdef class IntegerRing_class(PrincipalIdealDomain): sage: a / b 617/2839 sage: type(a/b) - + sage: a/a 1 sage: type(a/a) - + For floor division, use the ``//`` operator instead:: sage: a // b 0 sage: type(a//b) - + Next we illustrate arithmetic with automatic coercion. The types that coerce are: str, int, long, Integer. @@ -1046,7 +1046,7 @@ cdef class IntegerRing_class(PrincipalIdealDomain): (1,) 1 sage: type(ZZ.gens()[0]) - + """ return (self(1), ) @@ -1066,7 +1066,7 @@ cdef class IntegerRing_class(PrincipalIdealDomain): sage: ZZ.gen() 1 sage: type(ZZ.gen()) - + """ if n == 0: return self(1) diff --git a/src/sage/rings/multi_power_series_ring.py b/src/sage/rings/multi_power_series_ring.py index 2b8639ed2a3..a8f8cc47d57 100644 --- a/src/sage/rings/multi_power_series_ring.py +++ b/src/sage/rings/multi_power_series_ring.py @@ -163,7 +163,7 @@ sage: S = PowerSeriesRing(GF(11),2,'x,y'); S Multivariate Power Series Ring in x, y over Finite Field of size 11 sage: type(x) - + sage: type(S(x)) diff --git a/src/sage/rings/number_field/number_field.py b/src/sage/rings/number_field/number_field.py index 3ad7ffa26ef..2e0b86df657 100644 --- a/src/sage/rings/number_field/number_field.py +++ b/src/sage/rings/number_field/number_field.py @@ -8050,7 +8050,7 @@ def _coerce_map_from_(self, R): sage: S.coerce(-Integer(2)) -2 sage: z = S.coerce(-7/8); z, type(z) - (-7/8, ) + (-7/8, ) sage: S.coerce(y) is y True @@ -8106,13 +8106,13 @@ def _coerce_map_from_(self, R): sage: K. = NumberField(polygen(QQ)^3-2) sage: type(K.coerce_map_from(QQ)) - + Make sure we still get our optimized morphisms for special fields:: sage: K. = NumberField(polygen(QQ)^2-2) sage: type(K.coerce_map_from(QQ)) - + """ if R is int: @@ -10397,12 +10397,12 @@ class NumberField_cyclotomic(NumberField_absolute): sage: cf6(z3) zeta6 - 1 sage: type(cf6(z3)) - + sage: cf1 = CyclotomicField(1) ; z1 = cf1.0 sage: cf3(z1) 1 sage: type(cf3(z1)) - + """ def __init__(self, n, names, embedding=None, assume_disc_small=False, maximize_at_primes=None): """ @@ -10432,13 +10432,13 @@ def __init__(self, n, names, embedding=None, assume_disc_small=False, maximize_a :: sage: type(CyclotomicField(4).zero()) - + sage: type(CyclotomicField(6).one()) - + sage: type(CyclotomicField(6).an_element()) - + sage: type(CyclotomicField(15).zero()) - + """ f = QQ['x'].cyclotomic_polynomial(n) if names[0].startswith('zeta'): @@ -11744,9 +11744,9 @@ def __init__(self, polynomial, name=None, latex_name=None, check=True, embedding sage: k. = QuadraticField(7) sage: type(k.zero()) - + sage: type(k.one()) - + sage: TestSuite(k).run() @@ -11958,13 +11958,13 @@ def class_number(self, proof=None): TESTS:: sage: type(QuadraticField(-23,'a').class_number()) - + sage: type(NumberField(x^3 + 23, 'a').class_number()) - + sage: type(NumberField(x^3 + 23, 'a').extension(x^2 + 5, 'b').class_number()) - + sage: type(CyclotomicField(10).class_number()) - + """ proof = proof_flag(proof) diff --git a/src/sage/rings/number_field/number_field_element.pyx b/src/sage/rings/number_field/number_field_element.pyx index c34cfc9e42f..9dbbf6f2be7 100644 --- a/src/sage/rings/number_field/number_field_element.pyx +++ b/src/sage/rings/number_field/number_field_element.pyx @@ -359,7 +359,7 @@ cdef class NumberFieldElement(FieldElement): sage: cf4(one) 1 sage: type(cf4(1)) - + sage: cf33 = CyclotomicField(33) ; z33 = cf33.0 sage: cf66 = CyclotomicField(66) ; z66 = cf66.0 sage: z33._lift_cyclotomic_element(cf66) @@ -574,7 +574,7 @@ cdef class NumberFieldElement(FieldElement): sage: libgap(E8 + 3/2*E8^2 + 100*E8^7) E(8)+3/2*E(8)^2-100*E(8)^3 sage: type(_) - + Check that :trac:`15276` is fixed:: @@ -3807,7 +3807,7 @@ cdef class NumberFieldElement(FieldElement): sage: b.ord(P) 1 sage: type(b.valuation(P)) - + The function can be applied to elements in relative number fields:: @@ -4829,7 +4829,7 @@ cdef class NumberFieldElement_relative(NumberFieldElement): sage: L. = NumberField([x^2 + 1, x^2 + 2]) sage: type(a) # indirect doctest - + """ NumberFieldElement.__init__(self, parent, f) @@ -5126,7 +5126,7 @@ cdef class OrderElement_absolute(NumberFieldElement_absolute): sage: K. = NumberField(x^3 + 2) sage: O2 = K.order(2*a) sage: type(O2.1) # indirect doctest - + """ K = order.number_field() NumberFieldElement_absolute.__init__(self, K, f) @@ -5230,7 +5230,7 @@ cdef class OrderElement_relative(NumberFieldElement_relative): sage: c = O.1; c (-2*b^2 - 2)*a - 2*b^2 - b sage: type(c) - + """ def __init__(self, order, f): r""" @@ -5238,7 +5238,7 @@ cdef class OrderElement_relative(NumberFieldElement_relative): sage: O = EquationOrder([x^2 + x + 1, x^3 - 2],'a,b') sage: type(O.1) # indirect doctest - + """ K = order.number_field() NumberFieldElement_relative.__init__(self, K, f) diff --git a/src/sage/rings/number_field/number_field_element_quadratic.pyx b/src/sage/rings/number_field/number_field_element_quadratic.pyx index afe40d7ffdb..510d0a4a3ec 100644 --- a/src/sage/rings/number_field/number_field_element_quadratic.pyx +++ b/src/sage/rings/number_field/number_field_element_quadratic.pyx @@ -173,7 +173,7 @@ cdef class NumberFieldElement_quadratic(NumberFieldElement_absolute): sage: F. = QuadraticField(-7) sage: c = a + 7 sage: type(c) # indirect doctest - + """ self.D = parent._D cdef Integer a, b, denom @@ -2612,7 +2612,7 @@ cdef class OrderElement_quadratic(NumberFieldElement_quadratic): sage: OK. = EquationOrder(x^2 + 5) sage: v = OK.1 # indirect doctest sage: type(v) - + """ K = order.number_field() NumberFieldElement_quadratic.__init__(self, K, f) @@ -2878,14 +2878,14 @@ cdef class Z_to_quadratic_field_element(Morphism): sage: K. = QuadraticField(3) sage: phi = K.coerce_map_from(ZZ) # indirect doctest sage: type(phi) - + sage: phi == loads(dumps(phi)) # todo: comparison not implemented True sage: R. = CyclotomicField(6) sage: psi = R.coerce_map_from(ZZ) # indirect doctest sage: type(psi) - + sage: psi == loads(dumps(psi)) # todo: comparison not implemented True """ @@ -2980,14 +2980,14 @@ cdef class Q_to_quadratic_field_element(Morphism): sage: K. = QuadraticField(3) sage: phi = K.coerce_map_from(QQ) # indirect doctest sage: type(phi) - + sage: phi == loads(dumps(phi)) # todo: comparison not implemented True sage: R. = CyclotomicField(6) sage: psi = R.coerce_map_from(QQ) sage: type(psi) - + sage: psi == loads(dumps(psi)) # todo: comparison not implemented True """ diff --git a/src/sage/rings/number_field/number_field_ideal.py b/src/sage/rings/number_field/number_field_ideal.py index 8a27624e577..1f5bca3ce33 100644 --- a/src/sage/rings/number_field/number_field_ideal.py +++ b/src/sage/rings/number_field/number_field_ideal.py @@ -3214,7 +3214,7 @@ def __init__(self, K, M_OK_change, Q, I): From: Number Field in a with defining polynomial x^3 + 4 To: Residue field of Fractional ideal (1/2*a^2 + 1) sage: f.__class__ - + """ self.__M_OK_change = M_OK_change self.__Q = Q @@ -3270,7 +3270,7 @@ def __init__(self, OK, M_OK_map, Q, I): sage: I = K.ideal(1 + a^2/2) sage: f = I.residue_field().lift_map() sage: f.__class__ - + """ self.__I = I self.__OK = OK diff --git a/src/sage/rings/number_field/number_field_rel.py b/src/sage/rings/number_field/number_field_rel.py index 3097a98002d..71760700442 100644 --- a/src/sage/rings/number_field/number_field_rel.py +++ b/src/sage/rings/number_field/number_field_rel.py @@ -1686,7 +1686,7 @@ def pari_absolute_base_polynomial(self): sage: K.pari_absolute_base_polynomial() y^2 + 3 sage: type(K.pari_absolute_base_polynomial()) - + sage: z = ZZ['z'].0 sage: K. = NumberField([z^2 + 2, z^2 + 3, z^2 + 5]); K Number Field in a with defining polynomial z^2 + 2 over its base field @@ -1697,7 +1697,7 @@ def pari_absolute_base_polynomial(self): sage: len(QQ['y'](K.pari_absolute_base_polynomial()).roots(K.base_field())) 4 sage: type(K.pari_absolute_base_polynomial()) - + """ abs_base, from_abs_base, to_abs_base = self.absolute_base_field() return abs_base.pari_polynomial('y') diff --git a/src/sage/rings/number_field/totallyreal.pyx b/src/sage/rings/number_field/totallyreal.pyx index 0512f0559fc..69a1103ce9d 100644 --- a/src/sage/rings/number_field/totallyreal.pyx +++ b/src/sage/rings/number_field/totallyreal.pyx @@ -237,7 +237,7 @@ def enumerate_totallyreal_fields_prim(n, B, a = [], verbose=0, return_seqs=False sage: enumerate_totallyreal_fields_prim(2, 10) [[5, x^2 - x - 1], [8, x^2 - 2]] sage: type(enumerate_totallyreal_fields_prim(2, 10)[0][1]) - + sage: enumerate_totallyreal_fields_prim(2, 10, return_pari_objects=False)[0][0].parent() Integer Ring sage: enumerate_totallyreal_fields_prim(2, 10, return_pari_objects=False)[0][1].parent() diff --git a/src/sage/rings/number_field/totallyreal_rel.py b/src/sage/rings/number_field/totallyreal_rel.py index e531dcaa126..4211a2a4769 100644 --- a/src/sage/rings/number_field/totallyreal_rel.py +++ b/src/sage/rings/number_field/totallyreal_rel.py @@ -706,7 +706,7 @@ def enumerate_totallyreal_fields_rel(F, m, B, a=[], verbose=0, is set to ``False``:: sage: type(enumerate_totallyreal_fields_rel(F, 2, 2000)[0][1]) - + sage: enumerate_totallyreal_fields_rel(F, 2, 2000, return_pari_objects=False)[0][0].parent() Integer Ring sage: enumerate_totallyreal_fields_rel(F, 2, 2000, return_pari_objects=False)[0][1].parent() @@ -938,7 +938,7 @@ def enumerate_totallyreal_fields_all(n, B, verbose=0, return_seqs=False, sage: enumerate_totallyreal_fields_all(2, 10) [[5, x^2 - x - 1], [8, x^2 - 2]] sage: type(enumerate_totallyreal_fields_all(2, 10)[0][1]) - + sage: enumerate_totallyreal_fields_all(2, 10, return_pari_objects=False)[0][1].parent() Univariate Polynomial Ring in x over Rational Field diff --git a/src/sage/rings/padics/CA_template.pxi b/src/sage/rings/padics/CA_template.pxi index 5a3065ff10a..e4c5966ad3a 100644 --- a/src/sage/rings/padics/CA_template.pxi +++ b/src/sage/rings/padics/CA_template.pxi @@ -189,7 +189,7 @@ cdef class CAElement(pAdicTemplateElement): sage: a = ZpCA(5)(-3) sage: type(a) - + sage: loads(dumps(a)) == a True """ @@ -1005,7 +1005,7 @@ cdef class CAElement(pAdicTemplateElement): sage: a.unit_part() 18 + O(17^3) sage: type(a) - + sage: R(0).unit_part() O(17^0) """ @@ -1105,7 +1105,7 @@ cdef class pAdicCoercion_ZZ_CA(RingHomomorphism): EXAMPLES:: sage: f = ZpCA(5).coerce_map_from(ZZ); type(f) - + """ RingHomomorphism.__init__(self, ZZ.Hom(R)) self._zero = R.element_class(R, 0) @@ -1181,7 +1181,7 @@ cdef class pAdicCoercion_ZZ_CA(RingHomomorphism): sage: R = ZpCA(5,4) sage: type(R(10,2)) - + sage: R(10,2) # indirect doctest 2*5 + O(5^2) sage: R(10,3,1) @@ -1255,7 +1255,7 @@ cdef class pAdicConvert_CA_ZZ(RingMap): EXAMPLES:: sage: f = ZpCA(5).coerce_map_from(ZZ).section(); type(f) - + sage: f.category() Category of homsets of sets """ @@ -1300,7 +1300,7 @@ cdef class pAdicConvert_QQ_CA(Morphism): EXAMPLES:: sage: f = ZpCA(5).convert_map_from(QQ); type(f) - + """ Morphism.__init__(self, Hom(QQ, R, SetsWithPartialMaps())) self._zero = R.element_class(R, 0) @@ -1371,7 +1371,7 @@ cdef class pAdicConvert_QQ_CA(Morphism): sage: R = ZpCA(5,4) sage: type(R(10/3,2)) - + sage: R(10/3,2) # indirect doctest 4*5 + O(5^2) sage: R(10/3,3,1) @@ -1436,7 +1436,7 @@ cdef class pAdicCoercion_CA_frac_field(RingHomomorphism): sage: R. = ZqCA(27, implementation='FLINT') sage: K = R.fraction_field() sage: f = K.coerce_map_from(R); type(f) - + """ RingHomomorphism.__init__(self, R.Hom(K)) self._zero = K(0) @@ -1652,7 +1652,7 @@ cdef class pAdicConvert_CA_frac_field(Morphism): sage: R. = ZqCA(27, implementation='FLINT') sage: K = R.fraction_field() sage: f = R.convert_map_from(K); type(f) - + """ Morphism.__init__(self, Hom(K, R, SetsWithPartialMaps())) self._zero = R(0) diff --git a/src/sage/rings/padics/CR_template.pxi b/src/sage/rings/padics/CR_template.pxi index 68c0dc9d194..7318873f9c5 100644 --- a/src/sage/rings/padics/CR_template.pxi +++ b/src/sage/rings/padics/CR_template.pxi @@ -299,7 +299,7 @@ cdef class CRElement(pAdicTemplateElement): sage: a = ZpCR(5)(-3) sage: type(a) - + sage: loads(dumps(a)) == a # indirect doctest True """ @@ -1423,13 +1423,13 @@ cdef class CRElement(pAdicTemplateElement): sage: a.unit_part() 1 + 17 + O(17^4) sage: type(a) - + sage: R = Qp(17,4,'capped-rel') sage: a = R(18*17) sage: a.unit_part() 1 + 17 + O(17^4) sage: type(a) - + sage: a = R(2*17^2); a 2*17^2 + O(17^6) sage: a.unit_part() @@ -1562,7 +1562,7 @@ cdef class pAdicCoercion_ZZ_CR(RingHomomorphism): EXAMPLES:: sage: f = Zp(5).coerce_map_from(ZZ); type(f) - + """ RingHomomorphism.__init__(self, ZZ.Hom(R)) self._zero = R.element_class(R, 0) @@ -1652,7 +1652,7 @@ cdef class pAdicCoercion_ZZ_CR(RingHomomorphism): sage: R = Zp(5,4) sage: type(R(10,2)) - + sage: R(10,2) # indirect doctest 2*5 + O(5^2) sage: R(10,3,1) @@ -1724,7 +1724,7 @@ cdef class pAdicConvert_CR_ZZ(RingMap): EXAMPLES:: sage: f = Qp(5).coerce_map_from(ZZ).section(); type(f) - + sage: f.category() Category of homsets of sets with partial maps sage: Zp(5).coerce_map_from(ZZ).section().category() @@ -1780,7 +1780,7 @@ cdef class pAdicCoercion_QQ_CR(RingHomomorphism): EXAMPLES:: sage: f = Qp(5).coerce_map_from(QQ); type(f) - + """ RingHomomorphism.__init__(self, QQ.Hom(R)) self._zero = R.element_class(R, 0) @@ -1872,7 +1872,7 @@ cdef class pAdicCoercion_QQ_CR(RingHomomorphism): sage: R = Qp(5,4) sage: type(R(10/3,2)) - + sage: R(10/3,2) # indirect doctest 4*5 + O(5^2) sage: R(10/3,3,1) @@ -1944,7 +1944,7 @@ cdef class pAdicConvert_CR_QQ(RingMap): EXAMPLES:: sage: f = Qp(5).coerce_map_from(QQ).section(); type(f) - + sage: f.category() Category of homsets of sets """ @@ -1994,7 +1994,7 @@ cdef class pAdicConvert_QQ_CR(Morphism): EXAMPLES:: sage: f = Zp(5).convert_map_from(QQ); type(f) - + """ Morphism.__init__(self, Hom(QQ, R, SetsWithPartialMaps())) self._zero = R.element_class(R, 0) @@ -2073,7 +2073,7 @@ cdef class pAdicConvert_QQ_CR(Morphism): sage: R = Zp(5,4) sage: type(R(10/3,2)) - + sage: R(10/3,2) # indirect doctest 4*5 + O(5^2) sage: R(10/3,3,1) @@ -2156,7 +2156,7 @@ cdef class pAdicCoercion_CR_frac_field(RingHomomorphism): sage: R. = ZqCR(27, implementation='FLINT') sage: K = R.fraction_field() sage: f = K.coerce_map_from(R); type(f) - + """ RingHomomorphism.__init__(self, R.Hom(K)) self._zero = K(0) @@ -2377,7 +2377,7 @@ cdef class pAdicConvert_CR_frac_field(Morphism): sage: R. = ZqCR(27, implementation='FLINT') sage: K = R.fraction_field() sage: f = R.convert_map_from(K); type(f) - + """ Morphism.__init__(self, Hom(K, R, SetsWithPartialMaps())) self._zero = R(0) diff --git a/src/sage/rings/padics/FM_template.pxi b/src/sage/rings/padics/FM_template.pxi index 16926c3fe86..1dc94645c75 100644 --- a/src/sage/rings/padics/FM_template.pxi +++ b/src/sage/rings/padics/FM_template.pxi @@ -173,7 +173,7 @@ cdef class FMElement(pAdicTemplateElement): sage: a = ZpFM(5)(-3) sage: type(a) - + sage: loads(dumps(a)) == a True """ @@ -795,7 +795,7 @@ cdef class FMElement(pAdicTemplateElement): sage: R(0).unit_part() 0 sage: type(R(5).unit_part()) - + sage: R = ZpFM(5, 5); a = R(75); a.unit_part() 3 """ @@ -890,7 +890,7 @@ cdef class pAdicCoercion_ZZ_FM(RingHomomorphism): EXAMPLES:: sage: f = ZpFM(5).coerce_map_from(ZZ); type(f) - + """ RingHomomorphism.__init__(self, ZZ.Hom(R)) self._zero = R.element_class(R, 0) @@ -972,7 +972,7 @@ cdef class pAdicCoercion_ZZ_FM(RingHomomorphism): sage: R = ZpFM(5,4) sage: type(R(10,2)) - + sage: R(30,2) 5 + 5^2 sage: R(30,3,1) @@ -1030,7 +1030,7 @@ cdef class pAdicConvert_FM_ZZ(RingMap): EXAMPLES:: sage: f = ZpFM(5).coerce_map_from(ZZ).section(); type(f) - + sage: f.category() Category of homsets of sets """ @@ -1075,7 +1075,7 @@ cdef class pAdicConvert_QQ_FM(Morphism): EXAMPLES:: sage: f = ZpFM(5).convert_map_from(QQ); type(f) - + """ Morphism.__init__(self, Hom(QQ, R, SetsWithPartialMaps())) self._zero = R.element_class(R, 0) @@ -1154,7 +1154,7 @@ cdef class pAdicConvert_QQ_FM(Morphism): sage: R = ZpFM(5,4) sage: type(R(1/7,2)) - + sage: R(1/7,2) 3 + 3*5 + 2*5^3 sage: R(1/7,3,1) @@ -1201,7 +1201,7 @@ cdef class pAdicCoercion_FM_frac_field(RingHomomorphism): sage: R. = ZqFM(27) sage: K = R.fraction_field() sage: f = K.coerce_map_from(R); type(f) - + """ RingHomomorphism.__init__(self, R.Hom(K)) self._zero = K(0) @@ -1408,7 +1408,7 @@ cdef class pAdicConvert_FM_frac_field(Morphism): sage: R. = ZqFM(27) sage: K = R.fraction_field() sage: f = R.convert_map_from(K); type(f) - + """ Morphism.__init__(self, Hom(K, R, SetsWithPartialMaps())) self._zero = R(0) diff --git a/src/sage/rings/padics/FP_template.pxi b/src/sage/rings/padics/FP_template.pxi index c7ce3937c0d..a4eed73ced7 100644 --- a/src/sage/rings/padics/FP_template.pxi +++ b/src/sage/rings/padics/FP_template.pxi @@ -290,7 +290,7 @@ cdef class FPElement(pAdicTemplateElement): sage: a = ZpFP(5)(-3) sage: type(a) - + sage: loads(dumps(a)) == a True """ @@ -1152,7 +1152,7 @@ cdef class FPElement(pAdicTemplateElement): ... ValueError: unit part of 0 and infinity not defined sage: type(R(5).unit_part()) - + sage: R = ZpFP(5, 5); a = R(75); a.unit_part() 3 """ @@ -1268,7 +1268,7 @@ cdef class pAdicCoercion_ZZ_FP(RingHomomorphism): EXAMPLES:: sage: f = ZpFP(5).coerce_map_from(ZZ); type(f) - + """ RingHomomorphism.__init__(self, ZZ.Hom(R)) self._zero = R.element_class(R, 0) @@ -1350,7 +1350,7 @@ cdef class pAdicCoercion_ZZ_FP(RingHomomorphism): sage: R = ZpFP(5,4) sage: type(R(10,2)) - + sage: R(30,2) 5 sage: R(30,3,2) @@ -1416,7 +1416,7 @@ cdef class pAdicConvert_FP_ZZ(RingMap): EXAMPLES:: sage: f = ZpFP(5).coerce_map_from(ZZ).section(); type(f) - + sage: f.category() Category of homsets of sets """ @@ -1480,7 +1480,7 @@ cdef class pAdicCoercion_QQ_FP(RingHomomorphism): EXAMPLES:: sage: f = QpFP(5).coerce_map_from(QQ); type(f) - + """ RingHomomorphism.__init__(self, QQ.Hom(R)) self._zero = R.element_class(R, 0) @@ -1571,7 +1571,7 @@ cdef class pAdicCoercion_QQ_FP(RingHomomorphism): sage: R = QpFP(5,4) sage: type(R(10/3,2)) - + sage: R(10/3,2) 4*5 sage: R(10/3,3,1) @@ -1636,7 +1636,7 @@ cdef class pAdicConvert_FP_QQ(RingMap): EXAMPLES:: sage: f = QpFP(5).coerce_map_from(QQ).section(); type(f) - + sage: f.category() Category of homsets of sets with partial maps """ @@ -1684,7 +1684,7 @@ cdef class pAdicConvert_QQ_FP(Morphism): EXAMPLES:: sage: f = ZpFP(5).convert_map_from(QQ); type(f) - + """ Morphism.__init__(self, Hom(QQ, R, SetsWithPartialMaps())) self._zero = R.element_class(R, 0) @@ -1765,7 +1765,7 @@ cdef class pAdicConvert_QQ_FP(Morphism): sage: R = ZpFP(5,4) sage: type(R(1/7,2)) - + sage: R(1/7,2) 3 + 3*5 sage: R(1/7,3,2) @@ -1820,7 +1820,7 @@ cdef class pAdicCoercion_FP_frac_field(RingHomomorphism): sage: R. = ZqFP(27, implementation='FLINT') sage: K = R.fraction_field() sage: f = K.coerce_map_from(R); type(f) - + """ RingHomomorphism.__init__(self, R.Hom(K)) self._zero = K(0) @@ -1997,7 +1997,7 @@ cdef class pAdicConvert_FP_frac_field(Morphism): sage: R. = ZqFP(27, implementation='FLINT') sage: K = R.fraction_field() sage: f = R.convert_map_from(K); type(f) - + """ Morphism.__init__(self, Hom(K, R, SetsWithPartialMaps())) self._zero = R(0) diff --git a/src/sage/rings/padics/padic_ZZ_pX_CR_element.pyx b/src/sage/rings/padics/padic_ZZ_pX_CR_element.pyx index 8d44034b121..9d678d0f11d 100644 --- a/src/sage/rings/padics/padic_ZZ_pX_CR_element.pyx +++ b/src/sage/rings/padics/padic_ZZ_pX_CR_element.pyx @@ -1905,7 +1905,7 @@ cdef class pAdicZZpXCRElement(pAdicZZpXElement): sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5 sage: W. = R.ext(f) sage: type(W(0)) - + sage: W(0)^0 1 + O(w^25) sage: W(0)^0 == W(1) diff --git a/src/sage/rings/padics/padic_ZZ_pX_FM_element.pyx b/src/sage/rings/padics/padic_ZZ_pX_FM_element.pyx index c58954582ea..9b660621dea 100644 --- a/src/sage/rings/padics/padic_ZZ_pX_FM_element.pyx +++ b/src/sage/rings/padics/padic_ZZ_pX_FM_element.pyx @@ -718,7 +718,7 @@ cdef class pAdicZZpXFMElement(pAdicZZpXElement): sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5 sage: W. = R.ext(f) sage: type(W(0)) - + sage: W(0)^0 1 sage: W(0)^0 == W(1) diff --git a/src/sage/rings/padics/padic_base_leaves.py b/src/sage/rings/padics/padic_base_leaves.py index 4c525237c4f..2a567fce5d4 100644 --- a/src/sage/rings/padics/padic_base_leaves.py +++ b/src/sage/rings/padics/padic_base_leaves.py @@ -92,11 +92,11 @@ sage: (a * b) // 5^3 1 + 2*5 + O(5^2) sage: type((a * b) // 5^3) - + sage: (a * b) / 5^3 1 + 2*5 + O(5^2) sage: type((a * b) / 5^3) - + The fixed modulus type is the leanest of the p-adic rings: it is basically just a wrapper around `\ZZ / p^n \ZZ` diff --git a/src/sage/rings/padics/padic_capped_absolute_element.pyx b/src/sage/rings/padics/padic_capped_absolute_element.pyx index a34e1b27d77..387dd7c8b65 100644 --- a/src/sage/rings/padics/padic_capped_absolute_element.pyx +++ b/src/sage/rings/padics/padic_capped_absolute_element.pyx @@ -44,7 +44,7 @@ cdef class PowComputer_(PowComputer_base): sage: R = ZpCA(5) sage: type(R.prime_pow) - + sage: R.prime_pow._prec_type 'capped-abs' """ diff --git a/src/sage/rings/padics/padic_capped_relative_element.pyx b/src/sage/rings/padics/padic_capped_relative_element.pyx index c59c8e3573b..bea6c17af19 100644 --- a/src/sage/rings/padics/padic_capped_relative_element.pyx +++ b/src/sage/rings/padics/padic_capped_relative_element.pyx @@ -47,7 +47,7 @@ cdef class PowComputer_(PowComputer_base): sage: R = ZpCR(5) sage: type(R.prime_pow) - + sage: R.prime_pow._prec_type 'capped-rel' """ diff --git a/src/sage/rings/padics/padic_fixed_mod_element.pyx b/src/sage/rings/padics/padic_fixed_mod_element.pyx index 4b2723b7a8a..e012cbba9fc 100644 --- a/src/sage/rings/padics/padic_fixed_mod_element.pyx +++ b/src/sage/rings/padics/padic_fixed_mod_element.pyx @@ -44,7 +44,7 @@ cdef class PowComputer_(PowComputer_base): sage: R = ZpFM(5) sage: type(R.prime_pow) - + sage: R.prime_pow._prec_type 'fixed-mod' """ @@ -152,7 +152,7 @@ cdef class pAdicFixedModElement(FMElement): sage: R = Zp(7,4,'fixed-mod'); a = R(8); a.lift() 8 sage: type(a.lift()) - + """ return self.lift_c() diff --git a/src/sage/rings/padics/padic_floating_point_element.pyx b/src/sage/rings/padics/padic_floating_point_element.pyx index 89132c93025..b3eb407918e 100644 --- a/src/sage/rings/padics/padic_floating_point_element.pyx +++ b/src/sage/rings/padics/padic_floating_point_element.pyx @@ -42,7 +42,7 @@ cdef class PowComputer_(PowComputer_base): sage: R = ZpFP(5) sage: type(R.prime_pow) - + sage: R.prime_pow._prec_type 'floating-point' """ diff --git a/src/sage/rings/padics/padic_template_element.pxi b/src/sage/rings/padics/padic_template_element.pxi index f4629a5d598..b30d8cf0ae9 100644 --- a/src/sage/rings/padics/padic_template_element.pxi +++ b/src/sage/rings/padics/padic_template_element.pxi @@ -89,7 +89,7 @@ cdef class pAdicTemplateElement(pAdicGenericElement): sage: a = Zp(5)(1/2,3); a 3 + 2*5 + 2*5^2 + O(5^3) sage: type(a) - + sage: TestSuite(a).run() TESTS:: @@ -888,7 +888,7 @@ cdef class ExpansionIter(object): sage: E = Zp(5,4)(373).expansion() sage: I = iter(E) # indirect doctest sage: type(I) - + """ cdef pAdicTemplateElement elt cdef celement tmp @@ -1021,7 +1021,7 @@ cdef class ExpansionIterable(object): sage: E = Zp(5,4)(373).expansion() # indirect doctest sage: type(E) - + """ cdef pAdicTemplateElement elt cdef celement tmp @@ -1076,13 +1076,13 @@ cdef class ExpansionIterable(object): sage: E = Zp(5,4)(373).expansion() sage: type(iter(E)) - + sage: E = Zp(5,4)(373).expansion(start_val=-1) sage: type(iter(E)) - + sage: E = Zp(5,4)(373).expansion(start_val=1) sage: type(iter(E)) - + """ cdef ExpansionIter expansion = ExpansionIter(self.elt, self.prec, self.mode) if self.val_shift == 0: diff --git a/src/sage/rings/padics/pow_computer_ext.pyx b/src/sage/rings/padics/pow_computer_ext.pyx index f4e60ee393b..8c08b52e6d8 100644 --- a/src/sage/rings/padics/pow_computer_ext.pyx +++ b/src/sage/rings/padics/pow_computer_ext.pyx @@ -1813,7 +1813,7 @@ cdef class PowComputer_ZZ_pX_small_Eis(PowComputer_ZZ_pX_small): sage: A = PowComputer_ext_maker(5, 10, 10, 40, False, ntl.ZZ_pX([-5,75,15,0,1],5^10), 'small', 'e',ntl.ZZ_pX([1,-15,-3],5^10)) sage: type(A) - + sage: TestSuite(A).run() """ self._ext_type = 'e' @@ -2244,7 +2244,7 @@ cdef class PowComputer_ZZ_pX_big_Eis(PowComputer_ZZ_pX_big): sage: A = PowComputer_ext_maker(5, 3, 10, 40, False, ntl.ZZ_pX([-5,75,15,0,1],5^10), 'big', 'e',ntl.ZZ_pX([1,-15,-3],5^10)) sage: type(A) - + sage: TestSuite(A).run() """ self._ext_type = 'e' diff --git a/src/sage/rings/padics/pow_computer_flint.pyx b/src/sage/rings/padics/pow_computer_flint.pyx index 4d64096e4ee..9f914defcc6 100644 --- a/src/sage/rings/padics/pow_computer_flint.pyx +++ b/src/sage/rings/padics/pow_computer_flint.pyx @@ -41,7 +41,7 @@ cdef class PowComputer_flint(PowComputer_class): sage: from sage.rings.padics.pow_computer_flint import PowComputer_flint sage: type(PowComputer_flint(5, 20, 20, 20, False)) - + """ # fmpz_init does not allocate memory @@ -204,7 +204,7 @@ cdef class PowComputer_flint_1step(PowComputer_flint): sage: R. = ZZ[]; f = x^3 - 8*x - 2 sage: A = PowComputer_flint_1step(5, 20, 20, 20, False, f) sage: type(A) - + """ cdef Polynomial_integer_dense_flint poly = _poly @@ -467,7 +467,7 @@ cdef class PowComputer_flint_unram(PowComputer_flint_1step): sage: R. = ZZ[]; f = x^3 - 8*x - 2 sage: A = PowComputer_flint_unram(5, 20, 20, 20, False, f) sage: type(A) - + """ # fmpz_init does not allocate memory @@ -579,7 +579,7 @@ cdef class PowComputer_flint_eis(PowComputer_flint_1step): sage: R. = ZZ[]; f = x^3 - 25*x + 5 sage: A = PowComputer_flint_eis(5, 20, 20, 60, False, f) sage: type(A) - + """ PowComputer_flint_1step.__init__(self, prime, cache_limit, prec_cap, ram_prec_cap, in_field, poly) @@ -633,11 +633,11 @@ def PowComputer_flint_maker(prime, cache_limit, prec_cap, ram_prec_cap, in_field sage: from sage.rings.padics.pow_computer_flint import PowComputer_flint_maker sage: R. = ZZ[] sage: A = PowComputer_flint_maker(3, 20, 20, 20, False, x^3 + 2*x + 1, 'capped-rel'); type(A) - + sage: A = PowComputer_flint_maker(3, 20, 20, 20, False, x^3 + 2*x + 1, 'capped-abs'); type(A) - + sage: A = PowComputer_flint_maker(3, 20, 20, 20, False, x^3 + 2*x + 1, 'fixed-mod'); type(A) - + """ if prec_type == 'capped-rel': diff --git a/src/sage/rings/padics/qadic_flint_CA.pyx b/src/sage/rings/padics/qadic_flint_CA.pyx index a1ae9a48c0e..d10e4b3eaff 100644 --- a/src/sage/rings/padics/qadic_flint_CA.pyx +++ b/src/sage/rings/padics/qadic_flint_CA.pyx @@ -14,7 +14,7 @@ cdef class PowComputer_(PowComputer_flint_unram): sage: R. = ZqCA(125) sage: type(R.prime_pow) - + sage: R.prime_pow._prec_type 'capped-abs' """ diff --git a/src/sage/rings/padics/qadic_flint_CR.pyx b/src/sage/rings/padics/qadic_flint_CR.pyx index eaedb7a6c12..dfadaa2f053 100644 --- a/src/sage/rings/padics/qadic_flint_CR.pyx +++ b/src/sage/rings/padics/qadic_flint_CR.pyx @@ -14,7 +14,7 @@ cdef class PowComputer_(PowComputer_flint_unram): sage: R. = ZqCR(125) sage: type(R.prime_pow) - + sage: R.prime_pow._prec_type 'capped-rel' """ diff --git a/src/sage/rings/padics/qadic_flint_FM.pyx b/src/sage/rings/padics/qadic_flint_FM.pyx index 9d192addf2a..4f3afe77e81 100644 --- a/src/sage/rings/padics/qadic_flint_FM.pyx +++ b/src/sage/rings/padics/qadic_flint_FM.pyx @@ -14,7 +14,7 @@ cdef class PowComputer_(PowComputer_flint_unram): sage: R. = ZqFM(125) sage: type(R.prime_pow) - + sage: R.prime_pow._prec_type 'fixed-mod' """ diff --git a/src/sage/rings/padics/qadic_flint_FP.pyx b/src/sage/rings/padics/qadic_flint_FP.pyx index 949e132199c..1e250990c4e 100644 --- a/src/sage/rings/padics/qadic_flint_FP.pyx +++ b/src/sage/rings/padics/qadic_flint_FP.pyx @@ -16,7 +16,7 @@ cdef class PowComputer_(PowComputer_flint_unram): sage: R. = ZqFP(125) sage: type(R.prime_pow) - + sage: R.prime_pow._prec_type 'floating-point' """ diff --git a/src/sage/rings/polynomial/laurent_polynomial.pyx b/src/sage/rings/polynomial/laurent_polynomial.pyx index c0229a7b935..78d63fcf8e5 100644 --- a/src/sage/rings/polynomial/laurent_polynomial.pyx +++ b/src/sage/rings/polynomial/laurent_polynomial.pyx @@ -1990,7 +1990,7 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): sage: k = tuple(D)[0] sage: v = D[k] sage: type(k), type(v) - (<... 'tuple'>, ) + (<... 'tuple'>, ) sage: LQ(D) x^-1*y sage: tuple(D)[0] is k diff --git a/src/sage/rings/polynomial/multi_polynomial.pyx b/src/sage/rings/polynomial/multi_polynomial.pyx index e4b64c26a68..3f838d69a30 100644 --- a/src/sage/rings/polynomial/multi_polynomial.pyx +++ b/src/sage/rings/polynomial/multi_polynomial.pyx @@ -273,9 +273,9 @@ cdef class MPolynomial(CommutativeRingElement): sage: v = K(0) sage: vf = fast_callable(v) sage: type(v(0r, 0r, 0r)) - + sage: type(vf(0r, 0r, 0r)) - + sage: K. = QQ[] sage: from sage.ext.fast_eval import fast_float sage: fast_float(K(0)).op_list() @@ -313,7 +313,7 @@ cdef class MPolynomial(CommutativeRingElement): sage: R. = PolynomialRing(FiniteField(5)) sage: f = x^3*y^5 + x^7*y sage: type(f) - + sage: f.derivative(x) 2*x^6*y - 2*x^2*y^5 sage: f.derivative(y) @@ -1776,9 +1776,9 @@ cdef class MPolynomial(CommutativeRingElement): sage: x.denominator() 1 sage: type(x.denominator()) - + sage: type(a.denominator()) - + sage: from sage.rings.polynomial.multi_polynomial_element import MPolynomial sage: isinstance(a / b, MPolynomial) False diff --git a/src/sage/rings/polynomial/multi_polynomial_element.py b/src/sage/rings/polynomial/multi_polynomial_element.py index cbade28354c..05ba8094a42 100644 --- a/src/sage/rings/polynomial/multi_polynomial_element.py +++ b/src/sage/rings/polynomial/multi_polynomial_element.py @@ -1002,7 +1002,7 @@ def exponents(self, as_ETuples=True): By default the list of exponents is a list of ETuples:: sage: type(f.exponents()[0]) - + sage: type(f.exponents(as_ETuples=False)[0]) <... 'tuple'> diff --git a/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx b/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx index ec706f3129d..49297b16088 100644 --- a/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx +++ b/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx @@ -62,7 +62,7 @@ We show how to construct various multivariate polynomial rings:: sage: P. = Zmod(2521352)[]; P Multivariate Polynomial Ring in x, y, z over Ring of integers modulo 2521352 sage: type(P) - + sage: P. = Zmod(25213521351515232)[]; P Multivariate Polynomial Ring in x, y, z over Ring of integers modulo 25213521351515232 @@ -267,12 +267,12 @@ cdef class MPolynomialRing_libsingular(MPolynomialRing_base): sage: MPolynomialRing_libsingular(QQ, 3, ('x', 'y', 'z'), TermOrder('degrevlex', 3)) Multivariate Polynomial Ring in x, y, z over Rational Field sage: type(_) - + sage: P. = QQ[]; P Multivariate Polynomial Ring in x, y, z over Rational Field sage: type(P) - + """ self._ring = NULL @@ -336,7 +336,7 @@ cdef class MPolynomialRing_libsingular(MPolynomialRing_base): sage: P. = Zmod(2521352)[]; P Multivariate Polynomial Ring in x, y, z over Ring of integers modulo 2521352 sage: type(P) - + sage: P. = Zmod(25213521351515232)[]; P Multivariate Polynomial Ring in x, y, z over Ring of integers modulo 25213521351515232 @@ -470,7 +470,7 @@ cdef class MPolynomialRing_libsingular(MPolynomialRing_base): sage: R. = QQ[] sage: type(R) - + sage: R.has_coerce_map_from(ZZ['t']) False sage: R.coerce_map_from(ZZ['x']) @@ -2380,7 +2380,7 @@ cdef class MPolynomial_libsingular(MPolynomial): sage: g = f^(-1); g 1/(x^3 + y) sage: type(g) - + sage: P. = PolynomialRing(ZZ) sage: P(2)**(-1) diff --git a/src/sage/rings/polynomial/multi_polynomial_ring.py b/src/sage/rings/polynomial/multi_polynomial_ring.py index d4c91fbc3f0..88f7fc4ca51 100644 --- a/src/sage/rings/polynomial/multi_polynomial_ring.py +++ b/src/sage/rings/polynomial/multi_polynomial_ring.py @@ -251,13 +251,13 @@ def __call__(self, x=0, check=True): sage: x,y,z = var('x,y,z') sage: R = QQ['x,y,z'] sage: type(x) - + sage: type(R(x)) - + sage: f = R(x^3 + y^3 - z^3); f x^3 + y^3 - z^3 sage: type(f) - + sage: parent(f) Multivariate Polynomial Ring in x, y, z over Rational Field diff --git a/src/sage/rings/polynomial/pbori/pbori.pyx b/src/sage/rings/polynomial/pbori/pbori.pyx index b98e726945e..615357f9aac 100644 --- a/src/sage/rings/polynomial/pbori/pbori.pyx +++ b/src/sage/rings/polynomial/pbori/pbori.pyx @@ -1901,7 +1901,7 @@ class BooleanMonomialMonoid(UniqueRepresentation, Monoid_class): sage: M.gens() (x, y) sage: type(M.gen(0)) - + Since :trac:`9138`, boolean monomial monoids are unique parents and are fit into the category framework:: diff --git a/src/sage/rings/polynomial/polynomial_complex_arb.pyx b/src/sage/rings/polynomial/polynomial_complex_arb.pyx index 6f6e45d81ac..3d1f3bebb00 100644 --- a/src/sage/rings/polynomial/polynomial_complex_arb.pyx +++ b/src/sage/rings/polynomial/polynomial_complex_arb.pyx @@ -16,7 +16,7 @@ version 2, or later. TESTS: sage: type(polygen(ComplexBallField(140))) - + sage: Pol. = CBF[] sage: (x+1/2)^3 x^3 + 1.500000000000000*x^2 + 0.7500000000000000*x + 0.1250000000000000 @@ -45,7 +45,7 @@ cdef class Polynomial_complex_arb(Polynomial): sage: Pol. = CBF[] sage: type(x) - + sage: Pol(), Pol(1), Pol([0,1,2]), Pol({1: pi, 3: i}) (0, diff --git a/src/sage/rings/polynomial/polynomial_element.pyx b/src/sage/rings/polynomial/polynomial_element.pyx index 31fc3613876..680644fcf5a 100644 --- a/src/sage/rings/polynomial/polynomial_element.pyx +++ b/src/sage/rings/polynomial/polynomial_element.pyx @@ -213,7 +213,7 @@ cdef class Polynomial(CommutativeAlgebraElement): sage: f = x*y; f y*x sage: type(f) - + sage: p = (y+1)^10; p(1) 1024 @@ -3489,7 +3489,7 @@ cdef class Polynomial(CommutativeAlgebraElement): sage: x.denominator() 1 sage: type(x.denominator()) - + sage: isinstance(x.numerator() / x.denominator(), Polynomial) True sage: isinstance(x.numerator() / R(1), Polynomial) @@ -5711,7 +5711,7 @@ cdef class Polynomial(CommutativeAlgebraElement): sage: f = y^3 + x*y -3*x; f y^3 + x*y - 3*x sage: type(f) - + sage: v = f.list(); v [-3*x, x, 0, 1] sage: v[0] = 10 @@ -9680,9 +9680,9 @@ cdef class Polynomial(CommutativeAlgebraElement): Test the output type when ``certificate=True``:: sage: type((x^2 - 2).is_cyclotomic(certificate=True)) - + sage: type((x -1).is_cyclotomic(certificate=True)) - + Check that the arguments are forwarded when the input is not a polynomial with coefficients in `\ZZ`:: @@ -10992,7 +10992,7 @@ cdef class Polynomial_generic_dense(Polynomial): Make sure we're testing the right method:: sage: type(f) - + """ return make_generic_polynomial, (self._parent, self.__coeffs) @@ -11300,7 +11300,7 @@ cdef class Polynomial_generic_dense(Polynomial): Check that :trac:`12552` is fixed:: sage: type(f.degree()) - + """ return smallInteger(len(self.__coeffs) - 1) @@ -11317,7 +11317,7 @@ cdef class Polynomial_generic_dense(Polynomial): sage: R. = PolynomialRing(PolynomialRing(QQ,'y'), 'x') sage: p = x^2 + 2*x + 4 sage: type(p) - + sage: p.shift(0) x^2 + 2*x + 4 sage: p.shift(-1) @@ -11474,7 +11474,7 @@ cdef class Polynomial_generic_dense(Polynomial): :: sage: type(f) - + """ l = len(self.__coeffs) if n > l: @@ -11779,7 +11779,7 @@ cdef class ConstantPolynomialSection(Map): From: Univariate Polynomial Ring in y_1 over Finite Field of size 3 To: Finite Field of size 3 sage: type(phi) - + sage: phi(P0.one()) 1 sage: phi(y_1) @@ -11971,7 +11971,7 @@ cdef class PolynomialBaseringInjection(Morphism): From: Univariate Polynomial Ring in x over Real Double Field To: Real Double Field sage: type(m.section()) - + """ return ConstantPolynomialSection(self._codomain, self.domain()) diff --git a/src/sage/rings/polynomial/polynomial_integer_dense_flint.pyx b/src/sage/rings/polynomial/polynomial_integer_dense_flint.pyx index 112b17e8d24..75f61f37a46 100644 --- a/src/sage/rings/polynomial/polynomial_integer_dense_flint.pyx +++ b/src/sage/rings/polynomial/polynomial_integer_dense_flint.pyx @@ -182,11 +182,11 @@ cdef class Polynomial_integer_dense_flint(Polynomial): sage: f = R([-1, 2, 5]); f 5*x^2 + 2*x - 1 sage: type(f) - + sage: type(pari(f)) - + sage: type(R(pari(f))) - + sage: R(pari(f)) 5*x^2 + 2*x - 1 @@ -205,7 +205,7 @@ cdef class Polynomial_integer_dense_flint(Polynomial): sage: f = (x^3 - 1) / (x - 1) sage: type(f) - + sage: g = R(f); g x^2 + x + 1 @@ -1389,7 +1389,7 @@ cdef class Polynomial_integer_dense_flint(Polynomial): TESTS:: sage: type(x.degree()) - + """ return smallInteger(fmpz_poly_degree(self.__poly)) diff --git a/src/sage/rings/polynomial/polynomial_integer_dense_ntl.pyx b/src/sage/rings/polynomial/polynomial_integer_dense_ntl.pyx index 75227af230f..160899b6d64 100644 --- a/src/sage/rings/polynomial/polynomial_integer_dense_ntl.pyx +++ b/src/sage/rings/polynomial/polynomial_integer_dense_ntl.pyx @@ -127,11 +127,11 @@ cdef class Polynomial_integer_dense_ntl(Polynomial): sage: f = R([-1, 2, 5]); f 5*x^2 + 2*x - 1 sage: type(f) - + sage: type(pari(f)) - + sage: type(R(pari(f))) - + sage: R(pari(f)) 5*x^2 + 2*x - 1 @@ -150,7 +150,7 @@ cdef class Polynomial_integer_dense_ntl(Polynomial): sage: f = (x^3 - 1) / (x - 1) sage: type(f) - + sage: g = R(f); g x^2 + x + 1 diff --git a/src/sage/rings/polynomial/polynomial_quotient_ring.py b/src/sage/rings/polynomial/polynomial_quotient_ring.py index 4c89ef22db1..b069cdd749c 100644 --- a/src/sage/rings/polynomial/polynomial_quotient_ring.py +++ b/src/sage/rings/polynomial/polynomial_quotient_ring.py @@ -1333,7 +1333,7 @@ def S_class_group(self, S, proof=True): sage: type(CG[0][0][1]) sage: type(CG[0][1]) - + TESTS: @@ -1493,7 +1493,7 @@ def class_group(self, proof=True): sage: type(CG[0][0][1]) sage: type(CG[0][1]) - + """ return self.S_class_group((), proof=proof) @@ -1559,7 +1559,7 @@ def S_units(self, S, proof=True): sage: type(U[0][0]) sage: type(U[0][1]) - + sage: type(U[1][1]) @@ -1645,7 +1645,7 @@ def units(self, proof=True): sage: type(U[0][0]) sage: type(U[0][1]) - + sage: type(U[1][1]) diff --git a/src/sage/rings/polynomial/polynomial_rational_flint.pyx b/src/sage/rings/polynomial/polynomial_rational_flint.pyx index 8fd36a34dd0..7c71af6fb75 100644 --- a/src/sage/rings/polynomial/polynomial_rational_flint.pyx +++ b/src/sage/rings/polynomial/polynomial_rational_flint.pyx @@ -392,7 +392,7 @@ cdef class Polynomial_rational_flint(Polynomial): TESTS:: sage: type(f.degree()) - + """ return smallInteger(fmpq_poly_degree(self.__poly)) diff --git a/src/sage/rings/polynomial/polynomial_real_mpfr_dense.pyx b/src/sage/rings/polynomial/polynomial_real_mpfr_dense.pyx index 10e852d52f3..e806ae2d228 100644 --- a/src/sage/rings/polynomial/polynomial_real_mpfr_dense.pyx +++ b/src/sage/rings/polynomial/polynomial_real_mpfr_dense.pyx @@ -248,7 +248,7 @@ cdef class PolynomialRealDense(Polynomial): TESTS:: sage: type(f.degree()) - + """ return smallInteger(self._degree) diff --git a/src/sage/rings/polynomial/polynomial_ring.py b/src/sage/rings/polynomial/polynomial_ring.py index 7cef097c1a8..bab1c470ccb 100644 --- a/src/sage/rings/polynomial/polynomial_ring.py +++ b/src/sage/rings/polynomial/polynomial_ring.py @@ -219,7 +219,7 @@ def is_PolynomialRing(x): sage: is_PolynomialRing(R) False sage: type(R) - + """ return isinstance(x, PolynomialRing_general) @@ -1794,12 +1794,12 @@ def __init__(self, base_ring, name="x", sparse=False, implementation=None, sage: R = PRing(ZZ, 'x'); R Univariate Polynomial Ring in x over Integer Ring sage: type(R.gen()) - + sage: R = PRing(ZZ, 'x', implementation='NTL'); R Univariate Polynomial Ring in x over Integer Ring (using NTL) sage: type(R.gen()) - + """ self._implementation_repr = '' if element_class is None: @@ -1964,7 +1964,7 @@ def __init__(self, base_ring, name="x", sparse=False, element_class=None, catego sage: R = PRing(QQ, 'x'); R Univariate Polynomial Ring in x over Rational Field sage: type(R.gen()) - + sage: R = PRing(QQ, 'x', sparse=True); R Sparse Univariate Polynomial Ring in x over Rational Field sage: type(R.gen()) @@ -2384,7 +2384,7 @@ def __init__(self, base_ring, name="x", element_class=None, implementation=None) sage: S = PolynomialRing_dense_finite_field(GF(25, 'a'), implementation='NTL') sage: type(S(0)) - + sage: S = PolynomialRing_dense_finite_field(GF(64), implementation='superfast') Traceback (most recent call last): @@ -2976,17 +2976,17 @@ def __init__(self, base_ring, name=None, element_class=None, sage: R = PRing(Zmod(15), 'x'); R Univariate Polynomial Ring in x over Ring of integers modulo 15 sage: type(R.gen()) - + sage: R = PRing(Zmod(15), 'x', implementation='NTL'); R Univariate Polynomial Ring in x over Ring of integers modulo 15 (using NTL) sage: type(R.gen()) - + sage: R = PRing(Zmod(2**63*3), 'x', implementation='NTL'); R Univariate Polynomial Ring in x over Ring of integers modulo 27670116110564327424 (using NTL) sage: type(R.gen()) - + sage: R = PRing(Zmod(2**63*3), 'x', implementation='FLINT') Traceback (most recent call last): @@ -2996,7 +2996,7 @@ def __init__(self, base_ring, name=None, element_class=None, sage: R = PRing(Zmod(2**63*3), 'x'); R Univariate Polynomial Ring in x over Ring of integers modulo 27670116110564327424 (using NTL) sage: type(R.gen()) - + """ if element_class is None: implementation = self._implementation_names(implementation, base_ring)[0] @@ -3131,24 +3131,24 @@ def __init__(self, base_ring, name="x", implementation=None, category=None): sage: P = GF(2)['x']; P Univariate Polynomial Ring in x over Finite Field of size 2 (using GF2X) sage: type(P.gen()) - + sage: from sage.rings.polynomial.polynomial_ring import PolynomialRing_dense_mod_p sage: P = PolynomialRing_dense_mod_p(GF(5), 'x'); P Univariate Polynomial Ring in x over Finite Field of size 5 sage: type(P.gen()) - + sage: P = PolynomialRing_dense_mod_p(GF(5), 'x', implementation='NTL'); P Univariate Polynomial Ring in x over Finite Field of size 5 (using NTL) sage: type(P.gen()) - + sage: P = PolynomialRing_dense_mod_p(GF(9223372036854775837), 'x') sage: P Univariate Polynomial Ring in x over Finite Field of size 9223372036854775837 (using NTL) sage: type(P.gen()) - + This caching bug was fixed in :trac:`24264`:: diff --git a/src/sage/rings/polynomial/polynomial_ring_constructor.py b/src/sage/rings/polynomial/polynomial_ring_constructor.py index c88f6705ccd..0c96760861c 100644 --- a/src/sage/rings/polynomial/polynomial_ring_constructor.py +++ b/src/sage/rings/polynomial/polynomial_ring_constructor.py @@ -426,7 +426,7 @@ def PolynomialRing(base_ring, *args, **kwds): sage: R = PolynomialRing(ZZ, 'x,y', implementation="generic"); type(R) sage: S = PolynomialRing(ZZ, 'x,y'); type(S) - + Sparse univariate polynomials only support a generic implementation:: diff --git a/src/sage/rings/polynomial/polynomial_zmod_flint.pyx b/src/sage/rings/polynomial/polynomial_zmod_flint.pyx index fc7898dde64..18d04f404d8 100644 --- a/src/sage/rings/polynomial/polynomial_zmod_flint.pyx +++ b/src/sage/rings/polynomial/polynomial_zmod_flint.pyx @@ -16,10 +16,10 @@ EXAMPLES:: sage: R. = PolynomialRing(Integers(100)) sage: type(a) - + sage: R. = PolynomialRing(Integers(5*2^64)) sage: type(a) - + sage: R. = PolynomialRing(Integers(5*2^64), implementation="FLINT") Traceback (most recent call last): ... diff --git a/src/sage/rings/power_series_pari.pyx b/src/sage/rings/power_series_pari.pyx index b4d32da0b98..038c66dd1b7 100644 --- a/src/sage/rings/power_series_pari.pyx +++ b/src/sage/rings/power_series_pari.pyx @@ -18,21 +18,21 @@ not the type of the parents:: sage: type(R) sage: type(q) - + sage: type(S) sage: type(t) - + If `k` is a finite field implemented using PARI, this is the default implementation for power series over `k`:: sage: k. = GF(5^12) sage: type(c) - + sage: A. = k[[]] sage: type(x) - + .. WARNING:: diff --git a/src/sage/rings/power_series_ring_element.pyx b/src/sage/rings/power_series_ring_element.pyx index a021390d012..71ff6407c18 100644 --- a/src/sage/rings/power_series_ring_element.pyx +++ b/src/sage/rings/power_series_ring_element.pyx @@ -1005,7 +1005,7 @@ cdef class PowerSeries(AlgebraElement): sage: t.inverse() t^-1 sage: type(_) - + sage: (1-t).inverse() 1 + t + t^2 + t^3 + t^4 + t^5 + t^6 + t^7 + t^8 + ... """ diff --git a/src/sage/rings/qqbar.py b/src/sage/rings/qqbar.py index e75d09d58f0..87e59a14ab1 100644 --- a/src/sage/rings/qqbar.py +++ b/src/sage/rings/qqbar.py @@ -5210,7 +5210,7 @@ def _ensure_real(self): sage: b._value 0.7071067811865475244? sage: type(b._value) - + """ if is_ComplexIntervalFieldElement(self._value): self._value = self._value.real() diff --git a/src/sage/rings/quotient_ring_element.py b/src/sage/rings/quotient_ring_element.py index af2b3d43bb4..8d09a28f6ba 100644 --- a/src/sage/rings/quotient_ring_element.py +++ b/src/sage/rings/quotient_ring_element.py @@ -506,7 +506,7 @@ def _rational_(self): TESTS:: sage: type(S(-2/3)._rational_()) - + """ from sage.rings.rational_field import QQ return QQ(self.lift()) diff --git a/src/sage/rings/rational.pyx b/src/sage/rings/rational.pyx index 2be63156923..6e02cf4387d 100644 --- a/src/sage/rings/rational.pyx +++ b/src/sage/rings/rational.pyx @@ -404,7 +404,7 @@ cdef class Rational(sage.structure.element.FieldElement): sage: a = -2/3 sage: type(a) - + sage: parent(a) Rational Field sage: Rational('1/0') @@ -2526,7 +2526,7 @@ cdef class Rational(sage.structure.element.FieldElement): sage: a = (0/1)^(0/1); a 1 sage: type(a) - + If the result is rational, it is returned as a rational:: @@ -2562,7 +2562,7 @@ cdef class Rational(sage.structure.element.FieldElement): sage: a = int(2)^(3/1); a 8 sage: type(a) - + The exponent must fit in a long unless the base is -1, 0, or 1:: @@ -3482,7 +3482,7 @@ cdef class Rational(sage.structure.element.FieldElement): sage: (0/1)._lcm(0/1) 0 sage: type((2/3)._lcm(3/5)) - + """ if mpz_cmp_si(mpq_numref(self.value), 0) == 0 and \ mpz_cmp_si(mpq_numref(other.value), 0) == 0: @@ -3773,7 +3773,7 @@ cdef class Rational(sage.structure.element.FieldElement): sage: m = n.__pari__(); m 9390823/17 sage: type(m) - + sage: m.type() 't_FRAC' """ @@ -4148,7 +4148,7 @@ cdef class Q_to_Z(Map): TESTS:: sage: type(ZZ.convert_map_from(QQ)) - + """ cpdef Element _call_(self, x): """ diff --git a/src/sage/rings/rational_field.py b/src/sage/rings/rational_field.py index 059593e3836..fbd0fd79d65 100644 --- a/src/sage/rings/rational_field.py +++ b/src/sage/rings/rational_field.py @@ -173,7 +173,7 @@ def __init__(self): sage: Q('49/7') 7 sage: type(Q('49/7')) - + sage: a = Q('19/374'); a 19/374 sage: b = Q('17/371'); b diff --git a/src/sage/rings/real_arb.pyx b/src/sage/rings/real_arb.pyx index 72164d0ec13..eb0e513c70a 100644 --- a/src/sage/rings/real_arb.pyx +++ b/src/sage/rings/real_arb.pyx @@ -2548,7 +2548,7 @@ cdef class RealBall(RingElement): sage: RBF(sqrt(2)).contains_exact(sqrt(2)) Traceback (most recent call last): ... - TypeError: unsupported type: + TypeError: unsupported type: TESTS:: diff --git a/src/sage/rings/real_double.pyx b/src/sage/rings/real_double.pyx index 7356600a482..4e0a8136cdb 100644 --- a/src/sage/rings/real_double.pyx +++ b/src/sage/rings/real_double.pyx @@ -1223,7 +1223,7 @@ cdef class RealDoubleElement(FieldElement): sage: a = r.integer_part(); a -1 sage: type(a) - + sage: r = RDF(0.0/0.0) sage: a = r.integer_part() Traceback (most recent call last): diff --git a/src/sage/rings/real_lazy.pyx b/src/sage/rings/real_lazy.pyx index 24b679f8935..1ac123cfdb3 100644 --- a/src/sage/rings/real_lazy.pyx +++ b/src/sage/rings/real_lazy.pyx @@ -1709,7 +1709,7 @@ cdef class LazyWrapperMorphism(Morphism): sage: a = f(3); a 3 sage: type(a) - + sage: a._value 3 sage: a._value.parent() @@ -1727,7 +1727,7 @@ cdef class LazyWrapperMorphism(Morphism): sage: a = f(1/3); a # indirect doctest 0.3333333333333334? sage: type(a) - + sage: Reals(100)(a) 0.33333333333333333333333333333 diff --git a/src/sage/rings/real_mpfr.pyx b/src/sage/rings/real_mpfr.pyx index 5d4557a6d37..326a071b655 100644 --- a/src/sage/rings/real_mpfr.pyx +++ b/src/sage/rings/real_mpfr.pyx @@ -5366,7 +5366,7 @@ cdef class RealNumber(sage.structure.element.RingElement): :: sage: type(z) - + sage: R(z) 1.64493406684823 """ @@ -5753,9 +5753,9 @@ cdef class RealLiteral(RealNumber): The result is a non-literal:: sage: type(1.3) - + sage: type(n(1.3)) - + """ if prec is None: prec = digits_to_bits(digits) diff --git a/src/sage/rings/ring.pyx b/src/sage/rings/ring.pyx index 7cc9c6d3f70..562dd5cd2ff 100644 --- a/src/sage/rings/ring.pyx +++ b/src/sage/rings/ring.pyx @@ -1406,9 +1406,9 @@ cdef class CommutativeRing(Ring): sage: ZZ.krull_dimension() 1 sage: type(R); type(QQ); type(ZZ) - + - + All orders in number fields have Krull dimension 1, including non-maximal orders:: @@ -2049,7 +2049,7 @@ cdef class PrincipalIdealDomain(IntegralDomain): sage: QQ.gcd(ZZ(42), ZZ(48)); type(QQ.gcd(ZZ(42), ZZ(48))) 6 - + sage: QQ.gcd(1/2, 1/3) 1/6 @@ -2091,7 +2091,7 @@ cdef class PrincipalIdealDomain(IntegralDomain): sage: QQ.content(ZZ(42), ZZ(48)); type(QQ.content(ZZ(42), ZZ(48))) 6 - + sage: QQ.content(1/2, 1/3) 1/6 sage: factor(1/2); factor(1/3); factor(1/6) diff --git a/src/sage/rings/ring_extension.pyx b/src/sage/rings/ring_extension.pyx index 754b8c2ca63..640971fb47e 100644 --- a/src/sage/rings/ring_extension.pyx +++ b/src/sage/rings/ring_extension.pyx @@ -507,7 +507,7 @@ cdef class RingExtension_generic(CommutativeAlgebra): Rational Field over its base sage: type(Q) - + sage: TestSuite(Q).run() @@ -705,7 +705,7 @@ cdef class RingExtension_generic(CommutativeAlgebra): sage: K = GF(7^3).over() sage: type(K) - + sage: loads(dumps(K)) is K True """ @@ -841,7 +841,7 @@ cdef class RingExtension_generic(CommutativeAlgebra): sage: E.print_options(over=ZZ) Traceback (most recent call last): ... - TypeError: unable to coerce to an integer + TypeError: unable to coerce to an integer """ if over is not None and over is not Infinity: over = ZZ(over) @@ -1900,7 +1900,7 @@ cdef class RingExtensionFractionField(RingExtension_generic): Fraction Field of Integer Ring over its base sage: type(Q) - + sage: TestSuite(Q).run() @@ -2457,7 +2457,7 @@ cdef class RingExtensionWithGen(RingExtensionWithBasis): sage: K = A.over() sage: type(K) - + sage: TestSuite(K).run() diff --git a/src/sage/rings/ring_extension_conversion.pyx b/src/sage/rings/ring_extension_conversion.pyx index f432faf8bb2..36e12b8fcac 100644 --- a/src/sage/rings/ring_extension_conversion.pyx +++ b/src/sage/rings/ring_extension_conversion.pyx @@ -198,7 +198,7 @@ cdef _backend_morphism(f): sage: K. = GF(7^3).over() sage: f = End(K)(Frob) sage: type(f) - + sage: backend_morphism(f) == Frob # indirect doctest True @@ -219,7 +219,7 @@ cdef _backend_morphism(f): sage: iota = End(K).identity() sage: type(iota) - + sage: backend_morphism(iota) Identity endomorphism of Finite Field in z3 of size 7^3 """ diff --git a/src/sage/rings/ring_extension_element.pyx b/src/sage/rings/ring_extension_element.pyx index 1f34ba48078..610291dc620 100644 --- a/src/sage/rings/ring_extension_element.pyx +++ b/src/sage/rings/ring_extension_element.pyx @@ -91,7 +91,7 @@ cdef class RingExtensionElement(CommutativeAlgebraElement): sage: K = GF(5^3).over() sage: x = K.random_element() sage: type(x) - + sage: loads(dumps(x)) == x True """ @@ -566,7 +566,7 @@ cdef class RingExtensionFractionFieldElement(RingExtensionElement): sage: Q = Z.fraction_field() sage: x = Q.random_element() sage: type(x) - + sage: TestSuite(x).run() """ def __hash__(self): @@ -733,7 +733,7 @@ cdef class RingExtensionWithBasisElement(RingExtensionElement): sage: K. = GF(5^3).over() sage: L. = GF(5^9).over(K) sage: type(b) - + sage: TestSuite(b).run() """ def __hash__(self): diff --git a/src/sage/rings/ring_extension_morphism.pyx b/src/sage/rings/ring_extension_morphism.pyx index 463a07276a6..c5e6b556e56 100644 --- a/src/sage/rings/ring_extension_morphism.pyx +++ b/src/sage/rings/ring_extension_morphism.pyx @@ -93,7 +93,7 @@ cdef class RingExtensionHomomorphism(RingMap): a |--> 1 - a sage: type(phi) - + sage: TestSuite(phi).run() @@ -546,7 +546,7 @@ cdef class RingExtensionBackendIsomorphism(RingExtensionHomomorphism): To: Field in z9 with defining polynomial x^3 + (9*z3^2 + 5*z3 + 1)*x^2 + (4*z3 + 3)*x + 10*z3 over its base sage: type(f) - + sage: TestSuite(f).run() """ @@ -637,7 +637,7 @@ cdef class RingExtensionBackendReverseIsomorphism(RingExtensionHomomorphism): To: Finite Field in z9 of size 11^9 sage: type(f) - + sage: TestSuite(f).run() @@ -723,7 +723,7 @@ cdef class MapFreeModuleToRelativeRing(Map): sage: K = GF(5^2).over() sage: V, i, j = K.free_module() sage: type(i) - + """ def __init__(self, E, K): @@ -810,7 +810,7 @@ cdef class MapRelativeRingToFreeModule(Map): sage: K = GF(5^2).over() sage: V, i, j = K.free_module() sage: type(j) - + """ def __init__(self, E, K): diff --git a/src/sage/rings/semirings/non_negative_integer_semiring.py b/src/sage/rings/semirings/non_negative_integer_semiring.py index 6f80d4749c9..ea3bce495d9 100644 --- a/src/sage/rings/semirings/non_negative_integer_semiring.py +++ b/src/sage/rings/semirings/non_negative_integer_semiring.py @@ -53,7 +53,7 @@ class NonNegativeIntegerSemiring(NonNegativeIntegers): Sage ``Integers`` with ``Integer Ring`` as parent:: sage: x = NN(15); type(x) - + sage: x.parent() Integer Ring sage: x+3 diff --git a/src/sage/rings/universal_cyclotomic_field.py b/src/sage/rings/universal_cyclotomic_field.py index 9c7ed719378..61d21e1acb9 100644 --- a/src/sage/rings/universal_cyclotomic_field.py +++ b/src/sage/rings/universal_cyclotomic_field.py @@ -1477,7 +1477,7 @@ def _element_constructor_(self, elt): Traceback (most recent call last): ... TypeError: [ [ 0, 1 ], [ 0, 2 ] ] - of type not valid + of type not valid to initialize an element of the universal cyclotomic field Some conversions from symbolic functions are possible:: From 8cc350081bebd83ea605e62adde3bb07347bbfca Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 13 Oct 2021 14:35:27 -0700 Subject: [PATCH 348/359] src/sage/rings/polynomial/polynomial_singular_interface.py: Fixup merge --- src/sage/rings/polynomial/polynomial_singular_interface.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/sage/rings/polynomial/polynomial_singular_interface.py b/src/sage/rings/polynomial/polynomial_singular_interface.py index b0e067f1f78..cd0ff7a33a1 100644 --- a/src/sage/rings/polynomial/polynomial_singular_interface.py +++ b/src/sage/rings/polynomial/polynomial_singular_interface.py @@ -384,7 +384,6 @@ def can_convert_to_singular(R): if (base_ring is ZZ or sage.rings.finite_rings.finite_field_constructor.is_FiniteField(base_ring) or is_RationalField(base_ring) - or is_IntegerModRing(base_ring) or isinstance(base_ring, (sage.rings.abc.RealField, sage.rings.abc.ComplexField, sage.rings.abc.RealDoubleField, sage.rings.abc.ComplexDoubleField, sage.rings.abc.IntegerModRing))): From d314399aeb258a26bdc3e5540b3db13f147dd644 Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Mon, 26 Jul 2021 22:00:43 -0400 Subject: [PATCH 349/359] Trac #15219: add test for numerical_integral() of symbolic functions. The switch from fast_float() to fast_callable() in Trac 32234 also happened to fix the issue reported in Trac 15219, namely the inability to integrate symbolic functions by name. Here we add a doctest for the correct behavior. --- src/sage/calculus/integration.pyx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/sage/calculus/integration.pyx b/src/sage/calculus/integration.pyx index 93a3681854d..eab8d3834ba 100644 --- a/src/sage/calculus/integration.pyx +++ b/src/sage/calculus/integration.pyx @@ -250,6 +250,14 @@ def numerical_integral(func, a, b=None, Traceback (most recent call last): ... ValueError: integral does not converge at -infinity + + Symbolic functions can be integrated as conveniently as symbolic + expressions, as in :trac:`15219`:: + + sage: h(x) = x + sage: numerical_integral(h,0,1)[0] # abs tol 1e-8 + 0.5 + """ cdef double abs_err # step size cdef double result From 3bbc5d8fb9aa3abc81fe2a46da52312b843c796e Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 13 Oct 2021 19:30:46 -0700 Subject: [PATCH 350/359] build/pkgs/python3/spkg-build.in: Set rpath --- build/pkgs/python3/spkg-build.in | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/build/pkgs/python3/spkg-build.in b/build/pkgs/python3/spkg-build.in index b75958ab0fd..e45e4805ff6 100644 --- a/build/pkgs/python3/spkg-build.in +++ b/build/pkgs/python3/spkg-build.in @@ -90,7 +90,18 @@ sdh_configure --enable-shared $PYTHON_CONFIGURE # we need to provide paths into $SAGE_LOCAL, so that setup.py finds # the libraries needed for the extension modules - in particular sqlite3. # (The search code there does not know about CPATH and LIBRARY_PATH.) -sdh_make LDFLAGS="-L. -L$SAGE_LOCAL/lib $LDFLAGS" CPPFLAGS="-I$SAGE_LOCAL/include $CPPFLAGS" +make_LDFLAGS="-L. -L$SAGE_LOCAL/lib $LDFLAGS" +make_CPPFLAGS="-I$SAGE_LOCAL/include $CPPFLAGS" + +# Also, we need to add an rpath, like we do for SAGE_LOCAL in src/bin/sage-env. +# SAGE_INST_LOCAL is the installation hierarchy for the current package +# -- for python3, this is SAGE_VENV. +make_LDFLAGS="-Wl,-rpath,$SAGE_INST_LOCAL/lib $make_LDFLAGS" +if [ "$UNAME" = "Linux" ]; then + make_LDFLAGS="-Wl,-rpath-link,$SAGE_INST_LOCAL/lib $make_LDFLAGS" +fi + +sdh_make LDFLAGS="$make_LDFLAGS" CPPFLAGS="$make_CPPFLAGS" if [ "$UNAME" = "Darwin" ]; then export DYLD_LIBRARY_PATH="." From bc3ef1f650dcb6c0406ebb6bc2b920d771d4bd22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Labb=C3=A9?= Date: Thu, 14 Oct 2021 21:10:07 +0200 Subject: [PATCH 351/359] 32693: fixing failing internet doctest --- src/sage/calculus/calculus.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/sage/calculus/calculus.py b/src/sage/calculus/calculus.py index 19966cfb8b6..d3a035e2a36 100644 --- a/src/sage/calculus/calculus.py +++ b/src/sage/calculus/calculus.py @@ -1462,10 +1462,17 @@ def mma_free_limit(expression, v, a, dir=None): """ Limit using Mathematica's online interface. + INPUT: + + - ``expression`` -- symbolic expression + - ``v`` -- variable + - ``a`` -- value where the variable goes to + - ``dir`` -- ``'+'``, ``'-'`` or ``None`` (optional, default:``None``) + EXAMPLES:: sage: from sage.calculus.calculus import mma_free_limit - sage: mma_free_limit(sin(x)/x, x=0) # optional - internet + sage: mma_free_limit(sin(x)/x, x, a=0) # optional - internet 1 Another simple limit:: From cd1dd7489196b6ad43b3d78215d502d0913971ec Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 17 Oct 2021 10:39:59 -0700 Subject: [PATCH 352/359] build/pkgs/flit_core: Update to 3.4.0 --- build/pkgs/flit_core/checksums.ini | 6 +++--- build/pkgs/flit_core/package-version.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/pkgs/flit_core/checksums.ini b/build/pkgs/flit_core/checksums.ini index a6d2508fd40..5a0b6ecb0c1 100644 --- a/build/pkgs/flit_core/checksums.ini +++ b/build/pkgs/flit_core/checksums.ini @@ -1,5 +1,5 @@ tarball=flit_core-VERSION.tar.gz -sha1=cc89ef0fef30582845dc40d73dda7fa3bfa494cd -md5=697eb7da76b4eb5833bbf8bb97131879 -cksum=4051177318 +sha1=941603f1734b9b4af74954429ef51f97540f30e5 +md5=a4bb11b54bcf029ec2cd5cb981c07ded +cksum=2905595733 upstream_url=https://pypi.io/packages/source/f/flit_core/flit_core-VERSION.tar.gz diff --git a/build/pkgs/flit_core/package-version.txt b/build/pkgs/flit_core/package-version.txt index 15a27998172..18091983f59 100644 --- a/build/pkgs/flit_core/package-version.txt +++ b/build/pkgs/flit_core/package-version.txt @@ -1 +1 @@ -3.3.0 +3.4.0 From d6740651c05dc2c90fe84106461b588f7a47cf0a Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 17 Oct 2021 10:40:19 -0700 Subject: [PATCH 353/359] build/pkgs/tomli/dependencies: Drop toml, as flit_core now uses tomli --- build/pkgs/tomli/dependencies | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/pkgs/tomli/dependencies b/build/pkgs/tomli/dependencies index 31b6d3bd71c..7cd1e28759d 100644 --- a/build/pkgs/tomli/dependencies +++ b/build/pkgs/tomli/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | pip flit_core toml +$(PYTHON) | pip flit_core ---------- All lines of this file are ignored except the first. From 7100660478031cc355963056bda40ede2d538543 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 17 Oct 2021 10:48:30 -0700 Subject: [PATCH 354/359] build/pkgs/backcall/dependencies: flit_core now uses tomli --- build/pkgs/backcall/dependencies | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/pkgs/backcall/dependencies b/build/pkgs/backcall/dependencies index 97701a95eec..35228f20368 100644 --- a/build/pkgs/backcall/dependencies +++ b/build/pkgs/backcall/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) flit_core toml +$(PYTHON) | $(PYTHON_TOOLCHAIN) flit_core tomli ---------- All lines of this file are ignored except the first. From 0f5158f08e1129758d92d2936daf5504f2895138 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 17 Oct 2021 10:51:13 -0700 Subject: [PATCH 355/359] build/pkgs/setuptools_scm: Update to 6.3.2 --- build/pkgs/setuptools_scm/checksums.ini | 6 +++--- build/pkgs/setuptools_scm/package-version.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/pkgs/setuptools_scm/checksums.ini b/build/pkgs/setuptools_scm/checksums.ini index 10f9425e48f..a5c492c3e2f 100644 --- a/build/pkgs/setuptools_scm/checksums.ini +++ b/build/pkgs/setuptools_scm/checksums.ini @@ -1,5 +1,5 @@ tarball=setuptools_scm-VERSION.tar.gz -sha1=6d793de55ec500f7516802830f903cbc460a7999 -md5=7e17d25fd5bc5b128cfe2964a2e4cd5b -cksum=1288889703 +sha1=a4f02fddae697614e356cadfddb6241cc7737f38 +md5=32918d8ac566360c21411e0b3556c695 +cksum=1450556136 upstream_url=https://pypi.io/packages/source/s/setuptools_scm/setuptools_scm-VERSION.tar.gz diff --git a/build/pkgs/setuptools_scm/package-version.txt b/build/pkgs/setuptools_scm/package-version.txt index dc0208aba8e..91e4a9f2622 100644 --- a/build/pkgs/setuptools_scm/package-version.txt +++ b/build/pkgs/setuptools_scm/package-version.txt @@ -1 +1 @@ -6.3.1 +6.3.2 From e053097a07f635dae83dd69379a13a6335c0b45e Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 17 Oct 2021 10:55:53 -0700 Subject: [PATCH 356/359] build/pkgs/importlib_metadata/dependencies: setuptools_scm[toml] uses tomli now --- build/pkgs/importlib_metadata/dependencies | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/pkgs/importlib_metadata/dependencies b/build/pkgs/importlib_metadata/dependencies index c136b9290b7..9fcc3b0cc65 100644 --- a/build/pkgs/importlib_metadata/dependencies +++ b/build/pkgs/importlib_metadata/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) zipp typing_extensions | $(PYTHON_TOOLCHAIN) toml +$(PYTHON) zipp typing_extensions | $(PYTHON_TOOLCHAIN) tomli ---------- All lines of this file are ignored except the first. From fa561b2ecfa1899e14d55a44cf6925185e2e5d83 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 17 Oct 2021 11:02:55 -0700 Subject: [PATCH 357/359] build/pkgs/tomli/spkg-install.in: Set up PYTHONPATH --- build/pkgs/tomli/spkg-install.in | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build/pkgs/tomli/spkg-install.in b/build/pkgs/tomli/spkg-install.in index 37ac1a53437..e62010cea1e 100644 --- a/build/pkgs/tomli/spkg-install.in +++ b/build/pkgs/tomli/spkg-install.in @@ -1,2 +1,4 @@ cd src +# tomli's build system, flit_core, has a runtime dependency on tomli. +export PYTHONPATH="$(pwd)" sdh_pip_install . From 9eea50ccf4bf2db2f824c89b21a387334b1e01b4 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 17 Oct 2021 16:33:08 -0700 Subject: [PATCH 358/359] build/pkgs/toml/spkg-configure.m4: If system tox is used, mark as not required --- build/pkgs/toml/spkg-configure.m4 | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 build/pkgs/toml/spkg-configure.m4 diff --git a/build/pkgs/toml/spkg-configure.m4 b/build/pkgs/toml/spkg-configure.m4 new file mode 100644 index 00000000000..0dbc722cde5 --- /dev/null +++ b/build/pkgs/toml/spkg-configure.m4 @@ -0,0 +1,7 @@ +SAGE_SPKG_CONFIGURE([toml], [ + sage_spkg_install_toml=yes + ], [dnl REQUIRED-CHECK + AC_REQUIRE([SAGE_SPKG_CONFIGURE_TOX]) + dnl toml is only needed when we cannot use system tox. + AS_VAR_SET([SPKG_REQUIRE], [$sage_spkg_install_tox]) + ]) From 056b8d4e7bcdc936af39a33d3885925f1c850f80 Mon Sep 17 00:00:00 2001 From: Release Manager Date: Wed, 20 Oct 2021 00:54:28 +0200 Subject: [PATCH 359/359] Updated SageMath version to 9.5.beta4 --- .zenodo.json | 8 ++++---- VERSION.txt | 2 +- build/pkgs/configure/checksums.ini | 6 +++--- build/pkgs/configure/package-version.txt | 2 +- build/pkgs/sagelib/package-version.txt | 2 +- src/VERSION.txt | 2 +- src/bin/sage-version.sh | 6 +++--- src/sage/version.py | 6 +++--- 8 files changed, 17 insertions(+), 17 deletions(-) diff --git a/.zenodo.json b/.zenodo.json index 035015bacf5..f80be3c909b 100644 --- a/.zenodo.json +++ b/.zenodo.json @@ -1,10 +1,10 @@ { "description": "Mirror of the Sage https://sagemath.org/ source tree", "license": "other-open", - "title": "sagemath/sage: 9.5.beta3", - "version": "9.5.beta3", + "title": "sagemath/sage: 9.5.beta4", + "version": "9.5.beta4", "upload_type": "software", - "publication_date": "2021-10-11", + "publication_date": "2021-10-19", "creators": [ { "affiliation": "SageMath.org", @@ -15,7 +15,7 @@ "related_identifiers": [ { "scheme": "url", - "identifier": "https://github.com/sagemath/sage/tree/9.5.beta3", + "identifier": "https://github.com/sagemath/sage/tree/9.5.beta4", "relation": "isSupplementTo" }, { diff --git a/VERSION.txt b/VERSION.txt index 88f7d68ebc9..d035bc57e4b 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -SageMath version 9.5.beta3, Release Date: 2021-10-11 +SageMath version 9.5.beta4, Release Date: 2021-10-19 diff --git a/build/pkgs/configure/checksums.ini b/build/pkgs/configure/checksums.ini index 4720cc7df61..ce3df02bc5b 100644 --- a/build/pkgs/configure/checksums.ini +++ b/build/pkgs/configure/checksums.ini @@ -1,4 +1,4 @@ tarball=configure-VERSION.tar.gz -sha1=bf77cf87636c32930d165719bbf5f376b2830745 -md5=dbd50992848adbd32e1eab9bc0374faf -cksum=2846351532 +sha1=1df4c487d374a7ea9eeda3a9234cc6eed81c1443 +md5=83d4327261e545f26d4ad318030823e8 +cksum=2968565921 diff --git a/build/pkgs/configure/package-version.txt b/build/pkgs/configure/package-version.txt index 901ac7cbb07..3969244814e 100644 --- a/build/pkgs/configure/package-version.txt +++ b/build/pkgs/configure/package-version.txt @@ -1 +1 @@ -ced8aa261e9d69ddfc3e2d25de2ff9c60ed389bf +e8ab458165ec5e5832adf702099f47f4cff94596 diff --git a/build/pkgs/sagelib/package-version.txt b/build/pkgs/sagelib/package-version.txt index 173833eaf87..3fe69eb5038 100644 --- a/build/pkgs/sagelib/package-version.txt +++ b/build/pkgs/sagelib/package-version.txt @@ -1 +1 @@ -9.5.beta3 +9.5.beta4 diff --git a/src/VERSION.txt b/src/VERSION.txt index 173833eaf87..3fe69eb5038 100644 --- a/src/VERSION.txt +++ b/src/VERSION.txt @@ -1 +1 @@ -9.5.beta3 +9.5.beta4 diff --git a/src/bin/sage-version.sh b/src/bin/sage-version.sh index 750e10d31e0..1fa6283f152 100644 --- a/src/bin/sage-version.sh +++ b/src/bin/sage-version.sh @@ -1,5 +1,5 @@ # Sage version information for shell scripts # This file is auto-generated by the sage-update-version script, do not edit! -SAGE_VERSION='9.5.beta3' -SAGE_RELEASE_DATE='2021-10-11' -SAGE_VERSION_BANNER='SageMath version 9.5.beta3, Release Date: 2021-10-11' +SAGE_VERSION='9.5.beta4' +SAGE_RELEASE_DATE='2021-10-19' +SAGE_VERSION_BANNER='SageMath version 9.5.beta4, Release Date: 2021-10-19' diff --git a/src/sage/version.py b/src/sage/version.py index e9950f06043..0cd77c29e31 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 = '9.5.beta3' -date = '2021-10-11' -banner = 'SageMath version 9.5.beta3, Release Date: 2021-10-11' +version = '9.5.beta4' +date = '2021-10-19' +banner = 'SageMath version 9.5.beta4, Release Date: 2021-10-19'